【发布时间】:2014-05-19 12:42:13
【问题描述】:
我正在尝试处理 Spring 3 REST 应用程序中的语言环境更改。
但是语言环境没有改为fr。
控制台日志显示: 2014-05-19 14:29:46,214 调试 [AbstractExceptionHandler] 语言环境:en
这是我的配置:
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
// If true, the key of the message will be displayed if the key is not found, instead of throwing an exception
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
// The value 0 means always reload the messages to be developer friendly
messageSource.setCacheSeconds(0);
return messageSource;
}
// The locale interceptor provides a way to switch the language in any page just by passing the lang=’en’, lang=’fr’, and so on to the url
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setDefaultLocale(new Locale("en"));
return localeResolver;
}
这是我的异常处理程序:
@ControllerAdvice
public class AdminExceptionHandler extends AbstractExceptionHandler {
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public ResponseEntity<ErrorInfo> nullPointerException(HttpServletRequest request, NullPointerException e) {
String url = request.getRequestURL().toString();
String errorMessage = localizeErrorMessage("error.npe", new Object[] { e.getMessage() });
return new ResponseEntity<ErrorInfo>(new ErrorInfo(url, errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
public class AbstractExceptionHandler {
private static Logger logger = LoggerFactory.getLogger(AbstractExceptionHandler.class);
@Autowired
private MessageSource messageSource;
protected String localizeErrorMessage(String errorCode, Object args[]) {
Locale locale = LocaleContextHolder.getLocale();
logger.debug("locale: " + locale);
return messageSource.getMessage(errorCode, args, locale);
}
protected String localizeErrorMessage(String errorCode) {
return localizeErrorMessage(errorCode, null);
}
protected String extractAdminIdFromUrl(String url) {
String adminId = null;
try {
URI uri = new URI(url);
String path = uri.getPath();
adminId = path.substring(path.lastIndexOf('/') + 1);
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
return adminId;
}
}
这是我的测试:
@Test
public void testExceptionLocalizedMessage() throws Exception {
HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + PASSWORD);
MvcResult resultGet = this.mockMvc.perform(
get("/error/npe").headers(httpHeaders)
.param("lang", "fr")
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.message").value("Une erreur inconnue s'est produite. Veuillez nous excuser."))
.andReturn();
httpHeaders.add("Accept-Language", "fr");
resultGet = this.mockMvc.perform(
get("/error/npe").headers(httpHeaders)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.message").value("Une erreur inconnue s'est produite. Veuillez nous excuser."))
.andReturn();
}
我想在 ?lang=en 中处理 url 中的语言环境参数,并将 Accept-Language 标头作为后备。
作为一个 REST 应用程序,我正在考虑使用 AcceptHeaderLocaleResolver 类,但它不支持通过 url 参数设置语言环境。
我认为在 REST 应用程序中使用 SessionLocaleResolver 类没有什么意义。
剩下的就是 CookieLocaleResolver 类,我并不特别相信它应该在 REST 应用程序中使用。
无论如何,检索到的语言环境仍然是 en 而不是 fr,正如我所期望的那样。
编辑:
在测试中,使用语句:
httpHeaders.add("Accept-Language", Locale.FRENCH.getLanguage());
不设置语言环境。 但是使用 locale() 可以。 此测试通过:
this.mockMvc.perform(
get("/error/npe").headers(httpHeaders).locale(Locale.FRENCH)
.accept(MediaType.APPLICATION_JSON))
.andDo(print()
)
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.message").value(localizeErrorMessage("error.npe", Locale.FRENCH)))
.andReturn();
【问题讨论】:
-
我已将语言环境解析器配置为处理 lang=fr,但使用 Accept-Language 标头传递语言环境。难怪没有解决语言环境。
-
但是如果使用 Accept-Language 标头发送,它仍然看不到语言环境。我尝试了 CookieLocaleResolver 类和 SessionLocaleResolver 类,没有效果。
-
如果您更关心 SEO,则在路径中传递语言允许爬虫以所有支持的语言为您的网站编制索引。让我们密切关注这个问题 - Core Spring 团队正在考虑这个 PR 来支持这个问题 - github.com/spring-projects/spring-framework/issues/25791