• spring boot rest api exception解决方案


    1、控制器级别@ExceptionHandler

    public class FooController{
         
        //...
        @ExceptionHandler({ CustomException1.class, CustomException2.class })
        public void handleException() {
            //
        }
    }

    作用:只针对@Controller起作用。

    弊端:

    A、每个@Controller类都要写标记@ExceptionHandler的方法,当然可以统一写Base Controller,并将其写入。但,有些@Controller继承自其他BaseController,而该BaseController在其他jar包中,无法修改。

    B、不能对整个应用起作用。

    2、HandlerExceptionResolver

    1)、DefaultHandlerExceptionResolver

    作用:将标准Spring异常解析为对应的HTTP状态码,如404,500等。参见:spring exception完整列表

    弊端:没有对response的body设置内容。虽然可通过ModelAndView自行写错误内容,但不是最佳的。

    2)、ResponseStatusExceptionResolver

    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public class MyResourceNotFoundException extends RuntimeException {
        public MyResourceNotFoundException() {
            super();
        }
        public MyResourceNotFoundException(String message, Throwable cause) {
            super(message, cause);
        }
        public MyResourceNotFoundException(String message) {
            super(message);
        }
        public MyResourceNotFoundException(Throwable cause) {
            super(cause);
        }
    }

    作用:使用自定义异常类,并在其上加注解@ResponseStatus,将这些异常映射到HTTP状态码。

    弊端:与DefaultHandlerExceptionResolver一样,却是将状态码映射到response上,但body仍为null。

    3)、自定义HandlerExceptionResolver

    例子:如果客户端要求输入application / json,则在出现错误情况时,我们要确保我们返回一个以application / json编码的响应正文

    @Component
    public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver {
     
        @Override
        protected ModelAndView doResolveException(
          HttpServletRequest request, 
          HttpServletResponse response, 
          Object handler, 
          Exception ex) {
            try {
                if (ex instanceof IllegalArgumentException) {
                    return handleIllegalArgument(
                      (IllegalArgumentException) ex, response, handler);
                }
                ...
            } catch (Exception handlerException) {
                logger.warn("Handling of [" + ex.getClass().getName() + "] 
                  resulted in Exception", handlerException);
            }
            return null;
        }
     
        private ModelAndView 
          handleIllegalArgument(IllegalArgumentException ex, HttpServletResponse response) 
          throws IOException {
            response.sendError(HttpServletResponse.SC_CONFLICT);
            String accept = request.getHeader(HttpHeaders.ACCEPT);
            ...
            return new ModelAndView();
        }
    }

    作用:自定义异常

    弊端:返回的依旧是ModelAndView,在这里为response body设置内容。

    3、@ControllerAdvice

    @ControllerAdvice
    public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
     
        @ExceptionHandler(value = { IllegalArgumentException.class, IllegalStateException.class })
        protected ResponseEntity<Object> handleConflict(RuntimeException ex, WebRequest request) {
            String bodyOfResponse = "This should be application specific";
            return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
        }
    }

    作用:@ControllerAdvice为支持全局的@ExceptionHandler,该机制有别于旧的MVC模型,利用ResponseEntity和@@ExceptionHandler带来了便利。

    A、能够设置response的body和状态码。

    B、能将多个异常映射到同一方法,以便一起处理。

    C、充分利用了RESTful ResponseEntity来响应。

    4、ResponseStatusException(适用于spring5及以上)

    @GetMapping(value = "/{id}")
    public Foo findById(@PathVariable("id") Long id, HttpServletResponse response) {
        try {
            Foo resourceById = RestPreconditions.checkFound(service.findOne(id));
     
            eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response));
            return resourceById;
         }
        catch (MyResourceNotFoundException exc) {
             throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Foo Not Found", exc);
        }
    }

    作用:

    A、一种类型(ResponseStatusException),多种状态码。与@ExceptionHandler相比,减少了耦合。

    B、我们将不用创建那么多自定义异常类。

    C、由于可通过编程方式创建异常,因此可以更好的控制异常处理。

    弊端:

    A、没有统一、全局的异常处理方式:对比应用程序范围的全局异常(@ControllerAdvice)来说,提供全局异常很难。

    B、代码复制:在多个Controller类中复制代码。

    那如何解决以上问题呢?

    全局异常:@ControllerAdvice
    局部异常:ResponseStatusException

    但是,如果发生了相同的异常时,是重复执行还是报错?

  • 相关阅读:
    C++ calculate the time cost in 100 nanoseconds precision
    C++ append file via ofstream
    WCF Server Error in '/' Application.
    Webclient "The operation has timed out" and override webclient with customized timeout
    WPF implement SelectedCommand in MVVM via Interaction.Triggers
    将EDGE浏览器首页中的hao123删除的方法--干净的界面
    PHP 获取当前时间的下一个整点时间
    微信小程序添加空格
    为什么upload下的图片不存在,会报模块不存在的错误
    lnmp环境搭建
  • 原文地址:https://www.cnblogs.com/yaoyuan2/p/12248002.html
Copyright © 2020-2023  润新知