如何在Webflux中添加自定义LocaleResolverConfiguration

时间:2019-07-02 12:30:56

标签: locale spring-webflux

我在类路径中添加了以下@Bean,以覆盖spring webflux中的默认LocaleContextResolver

@Configuration
public class LocaleResolverConfiguration {

  @Bean(WebHttpHandlerBuilder.LOCALE_CONTEXT_RESOLVER_BEAN_NAME)
  public LocaleContextResolver localeContextResolver() {
    return new LocaleContextResolver() {
      @Override
      public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
        final String langParam = exchange.getRequest().getQueryParams().getFirst("lang");
        if (langParam == null) {
          return new SimpleLocaleContext(Locale.getDefault());
        } else {
          return new SimpleLocaleContext(Locale.forLanguageTag(langParam));
        }
      }

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

}

但是应用程序启动失败并出现以下错误

The bean 'localeContextResolver', defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration$EnableWebFluxConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/acme/webflux/config/LocaleResolverWebFluxConfiguration.class] and overriding is disabled.

当我们已经提供了自己的LocaleContextResolver localeContextResolver()时,为什么webflux不会退缩吗?

还有其他方法可以实现同一目标吗?

2 个答案:

答案 0 :(得分:0)

我进行了以下修改,因为在不摆脱自动配置的情况下,我找不到任何合理的方式来修改localeContextResolver。但这只是黑客,不是合理的解决方案

@Configuration
public class LocaleResolverConfiguration {

  @Bean
  public CommandLineRunner localeContextResolverCustomizer(HttpHandler httpHandler) {
    assert httpHandler instanceof HttpWebHandlerAdapter;
    return args -> {
      ((HttpWebHandlerAdapter) httpHandler).setLocaleContextResolver(new LocaleContextResolver() {
        @Override
        public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
          final String langParam = exchange.getRequest().getQueryParams().getFirst("lang");
          if (langParam == null) {
            return new SimpleLocaleContext(Locale.getDefault());
          } else {
            return new SimpleLocaleContext(Locale.forLanguageTag(langParam));
          }
        }

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

}

答案 1 :(得分:0)

在 webflux 中,我使用了以下代码片段并且它有效。如果在 URL 中找到 lang 参数以便解析关联的消息,否则它将解析与 HTTP 请求标头 Content-Language 关联的消息。如果两者都未设置,则解析默认消息:

@Configuration
public class LocaleResolverConfig {

   @Bean
   @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
   public HttpHandler httpHandler(ApplicationContext applicationContext) {
       HttpHandler delegate = WebHttpHandlerBuilder.applicationContext(applicationContext).build();
       return new HttpWebHandlerAdapter(((HttpWebHandlerAdapter) delegate)) {
       @Override
       protected ServerWebExchange createExchange(
           ServerHttpRequest request, ServerHttpResponse response) {
                ServerWebExchange serverWebExchange = super.createExchange(request, response);

                final MultiValueMap<String, String> queryParams = request.getQueryParams();
                final String languageValue = queryParams.getFirst("lang");
                if (StringUtils.isNoneEmpty(languageValue)) {
                     LocaleContextHolder.setLocaleContext(() -> 
                          Locale.forLanguageTag(languageValue));
                } else {
                     LocaleContext localeContext = serverWebExchange.getLocaleContext();
                     if (localeContext != null) {
                          LocaleContextHolder.setLocaleContext(localeContext);
                     }
                }
                return serverWebExchange;
           }
       };
    }
 }