spring exception处理
1.The Controller level @ExceptionHandler
@RequestMapping(value = "/regist", method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody public Object hualalaRegist(@Validated HualalaRegistVO registVO,BindingResult bindingResult, HttpServletRequest request) throws Exception { if (bindingResult.hasErrors()) return new ResultBean<>(HttpStatus.SC_BAD_REQUEST, "请求参数不合法", null); // if (bindingResult.hasErrors()){ // throw new BindException(bindingResult); // } if (!"dev".equals(profile)) { registVO.setPhoneNumber(LongdaiUtil.decrypt(registVO.getPhoneNumber())); registVO.setGroupID(LongdaiUtil.decrypt(registVO.getGroupID())); } registVO.setIpAddress(NetworkUtil.getIpAddress(request)); return hualalaService.hualalaRegist(registVO); } @ExceptionHandler({BindException.class, ConstraintViolationException.class}) public Object handleException(Exception exception) { return new ResultBean<>(HttpStatus.SC_BAD_REQUEST, exception.getMessage(), null); }
@Controller public class ExceptionHandlingController { // @RequestHandler methods ... // Exception handling methods // Convert a predefined exception to an HTTP Status code @ResponseStatus(value=HttpStatus.CONFLICT, reason="Data integrity violation") // 409 @ExceptionHandler(DataIntegrityViolationException.class) public void conflict() { // Nothing to do } // Specify name of a specific view that will be used to display the error: @ExceptionHandler({SQLException.class,DataAccessException.class}) public String databaseError() { // Nothing to do. Returns the logical view name of an error page, passed // to the view-resolver(s) in usual way. // Note that the exception is NOT available to this view (it is not added // to the model) but see "Extending ExceptionHandlerExceptionResolver" // below. return "databaseError"; } // Total control - setup a model and return the view name yourself. Or // consider subclassing ExceptionHandlerExceptionResolver (see below). @ExceptionHandler(Exception.class) public ModelAndView handleError(HttpServletRequest req, Exception ex) { logger.error("Request: " + req.getRequestURL() + " raised " + ex); ModelAndView mav = new ModelAndView(); mav.addObject("exception", ex); mav.addObject("url", req.getRequestURL()); mav.setViewName("error"); return mav; } }
该ExceptionHandler只作用于该Controller,并且根据上面的代码,由于@Validated 后面紧跟着BindResult 并且bindresult判断出异常并没有继续抛出,所以该ExceptionHandler不会生效。
ExceptionHandler只是捕获当前Controller的异常进行下一步处理。
2.@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 public class ServiceExceptionHandler { private static Logger log = LoggerFactory.getLogger(ServiceExceptionHandler.class); @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody Object handleException(Exception exception) { exception.printStackTrace(); log.error(exception.getMessage()); return new ResultBean<String>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器骄傲了 !", null); } }
@ControllerAdvice @Component public class GlobalExceptionHandler { @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Map handle(MethodArgumentNotValidException exception) { return error(exception.getBindingResult().getFieldErrors() .stream() .map(FieldError::getDefaultMessage) .collect(Collectors.toList())); } @ExceptionHandler @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Map handle(ConstraintViolationException exception) { return error(exception.getConstraintViolations() .stream() .map(ConstraintViolation::getMessage) .collect(Collectors.toList())); } private Map error(Object message) { return Collections.singletonMap("error", message); } }