我可以告诉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.
我尝试如下,但有一个例外:
@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());
}
}
结果:
java.lang.UnsupportedOperationException: Cannot change HTTP accept header - use a different locale resolution strategy
答案 0 :(得分:1)
首先,让我们看看会发生什么:
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]
...
调试后你就会知道:
accept-header
不支持 preHandle
,您不能使用 LocaleChangeInterceptor
accept-header
没有任何支持的语言,您必须手动添加它们。你可以看到这个issue。accept-header
仅在您设置支持的语言并且语言与客户端浏览器中的 Content-Language
匹配时才有效。
因此,您无需使用 spring.mvc.locale-resolver
或 spring.web.locale-resolver
。现在spring 5.3.2,不需要任何属性。
您的示例解决此问题的方法是附加另一个 LocaleResolver
:spring.io
@Bean
public LocaleResolver localeResolver() {
return new SessionLocaleResolver();//new CookieLocaleResolver();
}
并设置:
spring:
main:
allow-bean-definition-overriding: true # SpringBoot>=2.1.0
web:
locale: en # default
答案 1 :(得分:0)
解决方法可能如下。我仍然觉得该设置非常违反直觉。尤其是我曾期望:
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;
}
}
讨论后更新改进的版本:
@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;
}
}