spring-boot 異常處理
1. 自定义异常处理@ControllerAdvice/@RestControllerAdvice
@ControllerAdvice/@RestControllerAdvice可以处理Controller层类抛出来的异常。
@ControllerAdvice与@RestControllerAdvice区别类似于@RestController 与 @Controller的区别
@ControllerAdvicepublic class ControllerExceptionHandler {private static final String UNKNOWN_ERROR_CODE = "-1"; public static final String DEFAULT_ERROR_VIEW = "error";private final static Logger LOGGER = LoggerFactory.getLogger(ControllerExceptionHandler.class); @ExceptionHandler(value = PageException.class) public ModelAndView businessExceptionHandler(HttpServletRequest req, Exception e) throws Exception { ModelAndView mav = new ModelAndView(); mav.addObject("message", e.getMessage()); mav.setViewName(DEFAULT_ERROR_VIEW); return mav; } /** * 预期异常内容处理 * @param e * @return */@ExceptionHandler(value = ExpectedException.class)@ResponseBodypublic BasicResponseVo expectedExceptionResolver(ExpectedException e) { LOGGER.error("系统发生{}异常, 异常信息{}:", e.getExceptionCause(), exceptionCodeConfig.getMapperMsg(e.getExceptionCause()), e); return builder(e); }private BasicResponseVo builder(Exception e) { BasicResponseVo responseVo = new BasicResponseVo(); responseVo.setResponseTime(LocalDateTime.now()); if(e instanceof ExpectedException){ responseVo..setRespCode(e.getExceptionCause().getCode()); responseVo.etRespDesc(e.getExceptionCause().getMessage()); }else{ responseVo.setRespCode(UNKNOWN_ERROR_CODE); responseVo.etRespDesc(e.getClass().getName()); } return responseVo; }
}
2. 全局异常处理 BasicErrorController
BasicErrorController是spring-boot默认统一的全局异常类,这个类提供了默认了错误处理方法,包括错误跳转的路径和渲染方法。BasicErrorController会根据根据Accept头的内容,输出不同格式的错误响应当你是页面请求的时候就会返回页面,另外一种是json请求的时候就会返回json错误
org.springframework.boot.autoconfigure.web.servlet.errorBasicErrorController部分源码
@RequestMapping(produces = "text/html")public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null ? modelAndView : new ModelAndView("error", model)); } @RequestMapping @ResponseBody public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<>(body, status); }
BasicErrorController会默认返回error页面或固定格式格式为json,所以如果项目使用就必须重新实现BasicErrorController类。
重写CustomErrorController
/** * @see org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController * @see org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration * Created by Mr.J on 2018/1/20. */@Controllerpublic class CustomErrorController extends BasicErrorController { @Autowired public CustomErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) { super(errorAttributes, serverProperties.getError()); } public CustomErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) { super(errorAttributes, errorProperties, errorViewResolvers); } /** * 覆盖默认的Json响应 */ @Override public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { BasicResponseVo body = this.buildBody(request, this.isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = HttpStatus.OK;// HttpStatus status = this.getStatus(request); return new ResponseEntity(body, status); } /** * 覆盖默认的HTML响应 */ @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { //请求的状态 HttpStatus status = getStatus(request); response.setStatus(getStatus(request).value()); Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); ModelAndView modelAndView = resolveErrorView(request, response, status, model); //指定自定义的视图 return(modelAndView == null ? new ModelAndView("error", model) : modelAndView); } private BasicResponseVo buildBody(HttpServletRequest request, Boolean includeStackTrace){ Map<String,Object> errorAttributes = getErrorAttributes(request, includeStackTrace); String message = String.format("Requested path %s with result %s", errorAttributes.get("path"), errorAttributes.get("message")); String trace =""; BasicResponseVo responseVo = new BasicResponseVo(); responseVo.setResponseTime(LocalDateTime.now()); responseVo.setRespCode((String)errorAttributes.get("status")); responseVo.setRespDesc(message); responseVo.setTrace((String)errorAttributes.get("trace")) return responseVo; }
继承于BasicErrorController,注意一定要添加@Controller,不然Spring无法感知自定义的bean,BasicErrorController还是会起作用。至于新的Controller如何替换BasicErrorController关键在spring boot 在ErrorMvcAutoConfiguration自动装载BasicErrorController Bean的时候使用了@ConditionalOnMissingBean注解。
@Bean@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) { return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers); }
作者:倔强的农民工
链接:https://www.jianshu.com/p/188ec02d6bb2
共同學(xué)習(xí),寫(xiě)下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章