Spring LocalResolver 基于查询参数“lang=en”?

mem*_*und 6 java spring spring-mvc spring-boot

我可以告诉spring-boot自动解析查询参数所请求locale的,例如&lang=en吗?

我想让查询参数优先于Accept-Language参数。

我发现了以下两个属性,但与查询参数无关。

spring.mvc.locale= # Locale to use. By default, this locale is overridden by the "Accept-Language" header.
spring.mvc.locale-resolver=accept-header # Define how the locale should be resolved.
Run Code Online (Sandbox Code Playgroud)

我尝试如下,这给出了一个例外:

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
   @Bean
   public LocaleChangeInterceptor localeChangeInterceptor() {
       LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
       lci.setParamName("lang");
       return lci;
   }

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(localeChangeInterceptor());
   }
}
Run Code Online (Sandbox Code Playgroud)

结果是:

java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy

mem*_*und 3

解决办法大概如下。但我仍然发现这种设置非常违反直觉。我尤其希望:

  • 寄存器LocaleChangeInterceptor本身,但不并且必须addInterceptors()显式调用
  • spring.mvc.locale参数仍然设置到自定义 LocaleResolver 中,但没有并且必须手动覆盖WebMvcProperties

如果需要所有这些,文档可能需要对此进行更多解释。

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
   @Bean
   public LocaleChangeInterceptor localeChangeInterceptor() {
       LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
       lci.setParamName("lang");
       return lci;
   }

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(localeChangeInterceptor());
   }

   @Bean
   public AcceptHeaderLocaleResolver localeResolver(WebMvcProperties mvcProperties) {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver() {
            @Override
            public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
                LocaleContextHolder.setLocale(locale);
            }
        };

        localeResolver.setDefaultLocale(mvcProperties.getLocale());
        return localeResolver;
    }
}
Run Code Online (Sandbox Code Playgroud)

经过讨论更新改进版本:

@Configuration
public class AppConfig implements WebMvcConfigurer {
   @Bean
   public AcceptHeaderLocaleResolver localeResolver(WebMvcProperties mvcProperties) {
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver() {
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            String locale = request.getParameter("lang");
            return locale != null
                    ? org.springframework.util.StringUtils.parseLocaleString(locale)
                    : super.resolveLocale(request);
        }
        };

        localeResolver.setDefaultLocale(mvcProperties.getLocale());
        return localeResolver;
    }
}
Run Code Online (Sandbox Code Playgroud)