当前位置: 首页 > 知识库问答 >
问题:

如何在Spring boot 2 Webflux Thymelaf中配置i18n?

景靖琪
2023-03-14

我刚刚开始了一个基于Spring机2的新项目。在升级Spring启动版本时,将sping-boot-starter-web替换为sping-boot-starter-web的类,例如

  • WebMvcConfigurerAdapter
  • 区域设置解析程序
  • LocaleChangeInterceptor

缺少。现在如何配置defaultLocale和拦截器以更改语言?


共有3个答案

柴正祥
2023-03-14

从 Spring Boot 2.4.0 开始,WebFluxAutoConfiguration 包含一个 LocaleContextResolver 的 bean 定义,它允许我们注入自定义 LocaleContextResolver作为参考,以下是 Spring Boot 2.5.4 中的默认 Bean 定义(在早期版本中实现可能有所不同):

@Bean
@Override
@ConditionalOnMissingBean(name = WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
public LocaleContextResolver localeContextResolver() {
    if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
        return new FixedLocaleContextResolver(this.webProperties.getLocale());
    }
    AcceptHeaderLocaleContextResolver localeContextResolver = new AcceptHeaderLocaleContextResolver();
    localeContextResolver.setDefaultLocale(this.webProperties.getLocale());
    return localeContextResolver;
}

您可以通过提供自定义 Bean 定义来提供自己的 LocaleContextResolver 实现,以便从查询参数中获取语言环境:

//@Component("localeContextResolver")
@Component(WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
public class RequestParamLocaleContextResolver implements LocaleContextResolver {
    @Override
    public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
        List<String> lang = exchange.getRequest().getQueryParams().get("lang");
        Locale targetLocale = null;
        if (lang != null && !lang.isEmpty()) {
            targetLocale = Locale.forLanguageTag(lang.get(0));
        }
        if (targetLocale == null) {
            targetLocale = Locale.getDefault();
        }
        return new SimpleLocaleContext(targetLocale);
    }

    @Override
    public void setLocaleContext(ServerWebExchange exchange, LocaleContext localeContext) {
        throw new UnsupportedOperationException(
            "Cannot change lang query parameter - use a different locale context resolution strategy");
    }
}

请注意,框架使用带有特定名称localeContextResolverlocaleContextResolverWebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)。您需要提供具有给定名称的bean。请参见#24209。

宇文俊风
2023-03-14
匿名用户

有了Spring引导启动器网络通量,有

    < li >委托WebFluxConfiguration < li>LocaleContextResolver

例如,要使用查询参数“lang”显式控制语言环境:

> < li>

实现< code > LocaleContextResolver ,以便< code > resolveLocaleContext()返回由GET参数“lang”确定的< code>SimpleLocaleContext。我将这个实现命名为< code > queryparamloclecontextresolver 。请注意,默认的< code > LocaleContextResolver 是一个< code > org . spring framework . web . server . i18n . acceptheaderlocalecontextresolver 。

创建一个@配置类,该类扩展了委托WebF配置。覆盖DelegatingWebFluxConfiguration.localeContextResolver()以返回我们刚刚在步骤1中创建的QueryParamLocaleContextResolver。将此配置类命名为WebConfig

WebConfig 中,覆盖 DedelegateatingWebFluxConfiguration.configureViewResolvers() 并将 ThymeleafReactiveViewResolver bean 添加为视图解析器。我们这样做是因为,由于某种原因,委派WebFluxConfiguration将在步骤2之后错过ThymeleafReactiveViewResolver

另外,我必须提到,要将 i18n 与反应式堆栈一起使用,这个 bean 是必要的:

    @Bean
    public MessageSource messageSource() {
        final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:/messages");
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setDefaultEncoding("UTF-8");
        messageSource.setCacheSeconds(5);
        return messageSource;
}

创建自然模板、一些属性文件和控制器后,您将看到:

>

  • localhost:8080/test?lang=zh给你中文版

    < code >本地主机:8080/test?lang=en为您提供英文版

    只是不要忘记<代码>

  • 卜阳
    2023-03-14

    只需添加一个 WebFilter,该筛选器根据查询参数的值设置接受语言标头。以下示例从 URI 上的语言查询参数(如 http://localhost:8080/examples?language=es)中获取语言:

    import org.springframework.boot.context.event.ApplicationReadyEvent;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.event.EventListener;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.web.server.WebFilter;
    import org.springframework.web.server.WebFilterChain;
    import org.springframework.web.server.adapter.DefaultServerWebExchange;
    import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
    import reactor.core.publisher.Mono;
    
    import static org.springframework.util.StringUtils.isEmpty;
    
    @Component
    public class LanguageQueryParameterWebFilter implements WebFilter {
    
        private final ApplicationContext applicationContext;
    
        private HttpWebHandlerAdapter httpWebHandlerAdapter;
    
        public LanguageQueryParameterWebFilter(final ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        @EventListener(ApplicationReadyEvent.class)
        public void loadHttpHandler() {
            this.httpWebHandlerAdapter = applicationContext.getBean(HttpWebHandlerAdapter.class);
        }
    
        @Override
        public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain) {
            final ServerHttpRequest request = exchange.getRequest();
            final MultiValueMap<String, String> queryParams = request.getQueryParams();
            final String languageValue = queryParams.getFirst("language");
    
            final ServerWebExchange localizedExchange = getServerWebExchange(languageValue, exchange);
            return chain.filter(localizedExchange);
        }
    
        private ServerWebExchange getServerWebExchange(final String languageValue, final ServerWebExchange exchange) {
            return isEmpty(languageValue)
                    ? exchange
                    : getLocalizedServerWebExchange(languageValue, exchange);
        }
    
        private ServerWebExchange getLocalizedServerWebExchange(final String languageValue, final ServerWebExchange exchange) {
            final ServerHttpRequest httpRequest = exchange.getRequest()
                    .mutate()
                    .headers(httpHeaders -> httpHeaders.set("Accept-Language", languageValue))
                    .build();
    
            return new DefaultServerWebExchange(httpRequest, exchange.getResponse(),
                    httpWebHandlerAdapter.getSessionManager(), httpWebHandlerAdapter.getCodecConfigurer(),
                    httpWebHandlerAdapter.getLocaleContextResolver());
        }
    }
    

    它使用 @EventListener(ApplicationReadyEvent.class) 来避免循环依赖。

    请随时测试并提供有关POC的反馈。

     类似资料:
    • 问题内容: 当我将struts.xml放入web-inf时显示错误......当我将src文件夹放入时,它工作正常。(在web- inf中为applicationcontext.xml) 当我将applicationcontext.xml放在src文件夹中时(在(src文件夹或src / resources)中为struts.xml).......这就是说无法在web-inf文件夹中找到appli

    • 问题内容: 我有一个正在Swing中构建的应用程序。它具有可滚动和缩放的图表组件,可以平移和缩放它。整个过程很平滑,除了有时UI会暂停约750 ms,我不知道为什么。这种情况并非总是会发生-但有时应用程序中会发生某些事情,并且每6-8秒就会开始暂停一次。 很显然,EDT上有一些事件需要花费750毫秒左右的时间才能运行,这不应该发生。 我如何特别像这样配置EDT?我真正想做的是获取在每次事件在EDT

    • https://docs . JBoss . org/hibernate/ORM/5.2/javadocs/org/hibernate/interceptor . html说onPrepareStatement(字符串sql)不推荐使用。如果希望检查和修改SQL语句,请提供StatementInspector。 但是我不清楚如何在hibernate中在应用程序级别配置StatementInspec

    • 我在学习Spring Boot时遇到了一些编码问题;我想添加一个像Spring3.x那样的CharacterEncodingFilter。就像这样:

    • 我试图在我的应用程序中实现jpa 发展能力 所以,我的DataConfig看起来像这样: 但是,当我尝试启动应用程序时,会出现错误消息。制造战争- 已连接到服务器[2018-09-26 09:54:32631]工件未命名:正在部署工件,请稍候。。。2018年9月26日09:54:34.460警告[RMI TCP连接(3)-127.0.0.1]组织。阿帕奇。公猫dbcp。dbcp2。基本资源工厂。g

    • 我有一个使用以下方法的会话豆: 返回的CalculationResult无法映射到JSON,并出现以下异常: 如何在 Wildfly 中配置杰克逊及其?

    • 是否可以覆盖嵌入的 CXF JaxRS 容器的 TomEE 中的设置?我一直在尝试集成我自己的拦截器来处理JaxRS服务的路由。 我似乎不能做的是让TomEE在启动我的服务时加载拦截器。 我读过很多文章,其中说我应该能够通过添加以下内容来配置TomEE中的CXF内容 我还看到了一些引用,说明TomEE使用了TomEE。xml替换openejbjar。xml,所以我尝试在那里进行pojo部署,但由于

    • 我使用这个命令运行我的spring应用程序-java-jar,但是当从IDE运行应用程序时,我需要添加运行配置,下面是显示我所添加内容的屏幕截图,但是它对我不起作用。