简体   繁体   English

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

[英]Spring LocalResolver based on query parameter 'lang=en'?

Can I tell spring-boot to automatically resolve the requested locale by a queryparameter, eg &lang=en ?我可以告诉spring-boot通过查询参数自动解析请求的locale ,例如&lang=en吗?

I would like to give the query param precedence over Accept-Language parameter.我想让查询参数优先于Accept-Language参数。

I found the following two properties, but nothing about a query param.我发现了以下两个属性,但与查询参数无关。

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.

I tried as follows, which gives an exception:我尝试如下,这给出了一个例外:

@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());
   }
}

Results in:结果是:

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

The solution is probably as follows.解决办法大概如下。 Still I find the setup very counterintuitive.我仍然发现设置非常违反直觉。 Especially I would have expected that:特别是我会期望:

  • the LocaleChangeInterceptor registers itself, but does not and have to call addInterceptors() explicit LocaleChangeInterceptor注册自己,但没有并且必须显式调用addInterceptors()
  • the spring.mvc.locale parameter is still set into the custom LocaleResolver, but does not and have to override manually from WebMvcProperties spring.mvc.locale参数仍设置为自定义 LocaleResolver,但不会并且必须从WebMvcProperties手动覆盖

If all of this is desired, the docs might probably need more explanation on this.如果需要所有这些,文档可能需要对此进行更多解释。

@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;
    }
}

Update improved version after discussion:讨论后更新改进版本:

@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;
    }
}

First, let's see what happen:首先,让我们看看会发生什么:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
...
Caused by: java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
    at org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver.setLocale(AcceptHeaderLocaleResolver.java:142) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.i18n.LocaleChangeInterceptor.preHandle(LocaleChangeInterceptor.java:154) ~[spring-webmvc-5.3.2.jar:5.3.2]
...

After debug, you will know:调试后,你会知道:

  1. accept-header not support preHandle , you cannot use LocaleChangeInterceptor accept-header不支持preHandle ,你不能使用LocaleChangeInterceptor
  2. accept-header have not any supported languages, you must add them manual. accept-header没有任何支持的语言,您必须手动添加它们。 You can see this issue .你可以看到这个问题

accept-header only work when you set supported languages and the language match Content-Language from client browser. accept-header仅在您设置支持的语言并且语言匹配来自客户端浏览器的Content-Language时才有效。

So, you needn't use spring.mvc.locale-resolver or spring.web.locale-resolver .所以,你不需要使用spring.mvc.locale-resolverspring.web.locale-resolver Now spring 5.3.2 , no properties you need.现在spring 5.3.2 ,您不需要任何属性。

The way for your example to solve this is appending another LocaleResolver : spring.io为您的例子来解决这个问题的方法是追加其他LocaleResolverspring.io

    @Bean
    public LocaleResolver localeResolver() {
        return new SessionLocaleResolver();//new CookieLocaleResolver();
    }

And set:并设置:

spring:
  main:
    allow-bean-definition-overriding: true # SpringBoot>=2.1.0 
  web:
    locale: en # default

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM