Springboot全局异常处理:@ControllerAdvice和ErrorController

Springboot全局异常处理:@ControllerAdvice和ErrorController

目前有两种方式可以实现全局异常处理

  1. @ControllerAdvice
  2. ErrorController

两种处理方式可以同时使用,个人理解同时使用时
@ControllerAdvice是用来捕获Controller中抛出的异常;
ErrorController则是捕获未被@ControllerAdvice捕获的异常,用来做兜底异常处理;

一. @ControllerAdvice 实现

@ControllerAdvice + @ExceptionHandler 可以捕获Controller中抛出的异常进行处理(如果在@ExceptionHandler修饰的方法中再次抛出异常,则进入到/error路径下,即转交给ErrorController进行处理)

@ControllerAdvice
class APIResponseExceptionHandler {
    ... ...
    @ExceptionHandler({XDistException.class})
    public ResponseEntity<Object> handleXdistException(APIException te) {
        return exceptionUtilsService.errorResponse(te, INTERNAL_SERVER_ERROR);
    }
    ... ...
}

二. ErrorController 实现

没有进入Controller的其他部分抛出的异常(拦截器,过滤器或直接访问资源文件中抛出的异常)则交由ErrorController处理。

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class APIErrorController implements ErrorController {

    private static final Logger LOGGER = LoggerFactory.getLogger(APIErrorController.class);
    private static final String ERROR_PATH = "/error";

    /**
     * The error service.
     */
    @Autowired
    private ErrorService errorService;

    /**
     * Get error path.
     *
     * @return Error path {@link String}.
     */
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }

    /**
     * Method to execute when the error path is requested.
     * This will return a 404, 405, 415 or 500 error depending on the status to the client.
     *
     * @param request The request object.
     */
    @RequestMapping
    @ResponseBody
    public void error(HttpServletRequest request) {

        CoreRequestProperties requestProperties = (CoreRequestProperties) request.getAttribute(RequestParameters.REQUESTPROPERTIES);
        HttpStatus status = getStatus(request);
        ApiError error;

        switch (status) {
            // not found the request url
            case NOT_FOUND:
                error = errorService.createApiError(CoreErrorCodes.INVALID_PATH, requestProperties.getLocale());
                throw new NoResourceFoundException("Invalid path specified (404). Throwing invalid path error in the " +
                        "APIErrorController.", error);
                // the request method is not allowed
            case METHOD_NOT_ALLOWED:
                error = errorService.createApiError(CoreErrorCodes.METHOD_NOT_ALLOWED, requestProperties.getLocale());
                throw new MethodNotAllowedException("Invalid method specified (405). Throwing invalid method error in the " +
                        "APIErrorController.", error);
                //the media type is unsupported in the request
            case UNSUPPORTED_MEDIA_TYPE:
                error = errorService.createApiError(CoreErrorCodes.UNSUPPORTED_MEDIA_TYPE, requestProperties.getLocale());
                throw new UnsupportedMediaTypeException("Invalid media type (415). Throwing invalid media type in the " +
                        "APIErrorController.", error);
                // unknown error
            default:
                error = errorService.createApiError(CoreErrorCodes.ERROR_CONTROLLER_UNKNOWN_ERROR, requestProperties.getLocale());
                throw new ApplicationException(" Error occurred " + status + ". Throwing 500 in the APIErrorController.", error);
        }
    }

    /**
     * Retrieve the http status from the request.
     *
     * @param request The request object.
     * @return The HTTP status code to return.
     */
    protected HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        //if http status is null then return internal server error
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }

        try {
            return HttpStatus.valueOf(statusCode);
        } catch (Exception ex) {
            LOGGER.warn("Failed to retrieve HttpStatus. Returning default {}", HttpStatus.INTERNAL_SERVER_ERROR, ex);
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值