Controller层为处于请求处理的最顶层,再往上就是框架代码的。因此,肯定需要在Controller捕获所有异常,并且做适当处理,返回给前端一个友好的错误码
Spring 统一异常处理有 3 种方式,分别为:
- 使用 @ ExceptionHandler 注解
- 使用 @ControllerAdvice 注解
- 实现 HandlerExceptionResolver 接口
使用 @ ExceptionHandler 注解
这种异常处理只局部于某个 Controller 内,在 Controller 内部,用 @ExceptionHandler
注解的方法,就会作为该Controller内部的异常处理方法。能够对异常类型进行细粒度的控制,通过注解可以有选择的指定异常处理方法应用的异常类型:
@Controller
public class ExceptionHandlerController {
@ExceptionHandler(value={IOException.class,SQLException.class})
@ResponseBody
public ResponseEntity<?> exp(Exception ex) {
log.error("execption:",ex)
return new ResponseEntity<Object>(new Object(), HttpStatus.BAD_REQUEST);
}
}
使用 @ControllerAdvice 注解
定义一个存放异常处理函数的类,并使用 @Controlleradvice修饰,通过@Controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。
@ControllerAdvice
@ResponseBody
public class WebExceptionHandle {
private static Logger logger = LoggerFactory.getLogger(WebExceptionHandle.class);
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public ServiceResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
logger.error("参数解析失败", e);
return ServiceResponseHandle.failed("could_not_read_json");
}
}
实现 HandlerExceptionResolver 接口
可以实现自己的HandlerExceptionResolver,当然这也包括使用Spring已经为我们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver
SimpleMappingExceptionResolver需要重写doResolveException
可以用提供的ModelAndView,也可以自己写servletOutputStream
public class HandlerExceptionResolverImpl extends SimpleMappingExceptionResolver {
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
try {
String requestURL = request.getRequestURI();
String requestParams = request.getQueryString();
ServletOutputStream servletOutputStream = response.getOutputStream();
if(ex instanceof NullPointerException){
logger.error("npe{}{}",requestURL,requestParams);
Object result = new Object();
servletOutputStream.write(JSON.toJSONString(result).getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
之后需要在xml里配置这个bean