如何国际化 Spring 引导中的 API 错误?

How do I internationalize API errors in Spring Boot?

我能够使用

将控制器网页请求国际化
@RequestMapping(value="/image")
public String image(@RequestHeader(name=HEADER_CONSTANTS.ACCEPT_LANGUAGE, required=false) String al) {

在参数列表中。但是我试着把它放在 ResponseEntityExceptionHandler 中,但没有用。

@ControllerAdvice(basePackages="com.example.apis")
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(ApiException.class)
    protected ResponseEntity<Object> handleApiException(ApiException ex, @RequestHeader(name=HEADER_CONSTANTS.ACCEPT_LANGUAGE, required=false) String al) {

2019-05-13 21:59:59.193 WARN 16052 --- [nio-8080-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Failed to invoke @ExceptionHandler method: protected org.springframework.http.ResponseEntity com.example.apis.RestExceptionHandler.handleApiException(com.example.apis.ApiException,java.lang.String)

java.lang.IllegalStateException: Could not resolve method parameter at index 1 in protected org.springframework.http.ResponseEntity com.example.apis.RestExceptionHandler.handleApiException(com.example.apis.ApiException,java.lang.String): No suitable resolver for argument 1 of type 'java.lang.String'

它在没有 @RequestHeader 参数的情况下工作。如何在 JSON API 请求的异常处理程序中获取客户端的 Accept-Language HTTP header?

Spring 引导 1.5.20

如果你需要的是当前用户的语言环境,你应该注册一个LocaleResolver,然后从LocaleContextHolder中获取语言环境。

@Bean
public LocaleResolver localeResolver() {
    // Registering accept-header Locale Resolver with default Locale.US
    AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
    localeResolver.setDefaultLocale(Locale.US);

    return localeResolver;
}

然后您可以通过调用 LocaleContextHolder.getLocale().

在异常处理程序中获取语言环境

Documentation for @ExceptionHandler

语法无效,查看方法签名规则。您可以使用 WebRequest 来获取 Header

@ExceptionHandler(ApiException.class)
protected ResponseEntity<Object> handleApiException(ApiException ex, WebRequest request) {
     request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
}

在特定处理程序中处理异常的注释 类 and/or 处理程序方法。

允许使用此注释注释的处理程序方法具有非常灵活的签名。它们可能具有以下类型的参数,顺序任意:

  • 异常参数:声明为一般异常或更具体的异常。如果注释本身不通过其 value().

  • 缩小异常类型,这也用作映射提示
  • 请求and/or响应对象(通常来自ServletAPI)。您可以选择任何特定的 request/response 类型,例如ServletRequest / HttpServletRequest.

  • Session对象:典型的HttpSession。这种类型的参数将强制存在相应的会话。因此,这样的论点永远不会为空。请注意,会话访问可能不是 thread-safe,特别是在 Servlet 环境中:如果允许多个请求同时访问一个会话,请考虑将 "synchronizeOnSession" 标志切换为 "true"。

  • WebRequest 或 NativeWebRequest。允许通用请求参数访问以及 request/session 属性访问,与本机 Servlet API.

  • 无关
  • 当前请求区域设置的区域设置(由可用的最具体的区域设置解析器确定,即 Servlet 环境中配置的 LocaleResolver)。 InputStream / Reader 用于访问请求的内容。这将是 Servlet API.

  • 公开的原始 InputStream/Reader
  • OutputStream / Writer 用于生成响应的内容。这将是 Servlet API.

  • 公开的原始 OutputStream/Writer
  • 模型作为从处理程序方法返回模型映射的替代方法。请注意,提供的模型 pre-populated 不具有常规模型属性,因此始终为空,以便于为 exception-specific 视图

  • 准备模型

我根据 Deadpool 的回答使用了以下内容。如果语言包不包含给定消息键的翻译,我会遇到异常 (org.springframework.context.NoSuchMessageException)。如果 .properties 文件在一行中不包含翻译,我希望可以默认为英语。

@ExceptionHandler(ApiException.class)
protected ResponseEntity<Object> handleApiException(ApiException ex, Locale locale) {
    String defaultMessage = messages.getMessage(ex.errorMessage, ex.errorArgument, Locale.ENGLISH);
    String localErrorMessage = messages.getMessage(ex.errorMessage, ex.errorArgument, defaultMessage, locale);