简体   繁体   English

Spring Boot异常处理

[英]Spring Boot Exception Handling

We are using spring boot for our application. 我们正在为我们的应用程序使用spring boot。 I'm trying to return the localized result in the response when the Rest service is called based on the Accept-Language header. 我正在尝试在基于Accept-Language标头调用Rest服务时返回响应中的本地化结果。 For example if the Accept-Language header is : zh,ja;q=0.8,en. 例如,如果Accept-Language标头是:zh,ja; q = 0.8,en。 So the response will be in chinese since we support that. 因此,我们支持,因此回复将采用中文。

But if Accept-Language header is : zh1,ja;q=0.8,en. 但是如果Accept-Language标题是:zh1,ja; q = 0.8,en。 Then I get Internal server error like below, because it can't invoke @ExceptionHandler i do not get response i like. 然后我得到如下的内部服务器错误,因为它无法调用@ExceptionHandler我没有得到我喜欢的响应。 Below is what I get 以下是我得到的

{
  "timestamp": 1462213062585,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "java.lang.IllegalArgumentException",
  "message": "java.lang.IllegalArgumentException: range=zh1",
  "path": "/user/v1//paymentmethods/creditdebitcards"
}

Instead this is what I want to throw because for all other exceptions we handle and throw a similar response. 相反,这是我想要抛出的,因为对于所有其他异常,我们处理并抛出类似的响应。

{
  "operation": {
    "result": "ERROR",
    "errors": [
      {
        "code": "1000",
        "message": "An unidentified exception has occurred.",
        "field": ""
      }
    ],
    "requestTimeStampUtc": "2016-05-02T18:22:03.356Z",
    "responseTimeStampUtc": "2016-05-02T18:22:03.359Z"
  }
}

Below are my classes, if the header is wrong (like zh1 ,ja;q=0.8,en) then the parse method below throws 500 error like above. 下面是我的类,如果标题错误(如zh1 ,ja; q = 0.8,en),则下面的解析方法会抛出500错误,如上所示。

public class SmartLocaleResolver extends AcceptHeaderLocaleResolver {

    @Autowired
    ExceptionHandling exceptionHandling;

    @Autowired
    MessageHandler    messageHandler;

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        try {
            List<LanguageRange> list = Locale.LanguageRange.parse(request.getHeader("Accept-Language"));
            if (!list.isEmpty()) {
                for (LanguageRange s : list) {
                    if (ApplicationConstants.LOCALE.contains(s.getRange())) {
                        return Locale.forLanguageTag(s.getRange());
                    }
                }
            }
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e);
        }
        return request.getLocale();
    }

Below is the ExceptionHandler class 下面是ExceptionHandler类

@EnableWebMvc
@ControllerAdvice
public class ExceptionHandling extends ResponseEntityExceptionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandling.class);

    @Autowired
    private MessageHandler      messageHandler;

    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler(value = { UnsupportedMediaTypeException.class, InvalidMediaTypeException.class })
    public void unsupportedMediaTypeException() {

    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public @ResponseBody OperationsErrorBean handleglobalException(final HttpServletRequest request,
            final Exception ex) {
        LOGGER.error("Unhandled Exception Occurred: ", ex);
        return errorResponse("1000", messageHandler.localizeErrorMessage("error.1000"), "", request.getRequestURI(),
                request.getAttribute("startTime").toString());

    }
}

This is my ApplicationConfig.java class 这是我的ApplicationConfig.java类

@Configuration
@ComponentScan("com.hsf")
@EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {

    @Value("${spring.application.name}")
    String appName;

    @Bean
    public AlwaysSampler defaultSampler() {
        return new AlwaysSampler();
    }

    @Override
    public void addInterceptors(final InterceptorRegistry registry) {

        if (StringUtils.isNotBlank(appName)) {
            MDC.put("AppName", appName);

        } else {
            MDC.put("AppName", "APPNAME_MISSING");
        }

        registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/user/v1/**");
    }

    @Bean
    public LocaleResolver localeResolver() {
        return new SmartLocaleResolver();
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
        final DispatcherServlet servlet = new DispatcherServlet();
        servlet.setDispatchOptionsRequest(true);
        return servlet;
    }

    @Bean
    public MessageSource messageSource() {
        final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:i18n/messages");
        // 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(10);
        return messageSource;
    }

}

The @ExceptionHandler annotation for the unsupportedMediaTypeException method does not contain IllegalArgumentException , instead of: unsupportedMediaTypeException方法的@ExceptionHandler注释不包含IllegalArgumentException ,而不是:

@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(value = { UnsupportedMediaTypeException.class, 
  InvalidMediaTypeException.class })
public void unsupportedMediaTypeException() { }

it should be: 它应该是:

@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(value = { UnsupportedMediaTypeException.class, 
  InvalidMediaTypeException.class, IllegalArgumentException.class })
public void unsupportedMediaTypeException() { }

Also, since it seems handling of numerous languages is one of requirements of your application I suggest to create a dedicated RuntimeException for this situation InvalidAcceptLanguageException instead of using a generic IllegalArgumentException for this purpose. 此外,由于似乎处理多种语言是您的应用程序的要求之一,我建议为此情况创建一个专用的RuntimeException InvalidAcceptLanguageException而不是为此目的使用泛型IllegalArgumentException

I have the Accept-Language check in the interceptor and I throw a custom exception I created when there is an exception parsing the header. 我在拦截器中进行了Accept-Language检查,并且在解析标头时发生了我创建的自定义异常。 So I throw a 400 Bad request with a proper response I want to display. 所以我抛出一个400 Bad请求,并且我想显示一个正确的响应。

 public class RequestInterceptor extends HandlerInterceptorAdapter {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                    throws Exception {

                final String startTime = DateUtils.getUTCDate();

                request.setAttribute("startTime", startTime);


                **try {
                    Locale.LanguageRange.parse(request.getHeader("Accept-Language"));
                } catch (IllegalArgumentException e) {
                    throw new InvalidAcceptLanguageException();
                }**

                return true;

            }
        }

I have added a method in my ExceptionHandling class to throw InvalidAcceptLanguageException. 我在我的ExceptionHandling类中添加了一个方法来抛出InvalidAcceptLanguageException。

@EnableWebMvc
@ControllerAdvice
public class ExceptionHandling extends ResponseEntityExceptionHandler {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandling.class);


    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = InvalidAcceptLanguageException.class)
    @ResponseBody
    public OperationsErrorBean invalidAcceptLanguageException(final HttpServletRequest request, final Exception ex) {
        return errorResponse("N/A", "Accept-Language is not in correct format", "", request.getRequestURI(),
                request.getAttribute("startTime").toString());
    }
}

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

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