总览
学习一个知识点的灵魂三问
为什么?
怎么做?
为啥可以这样做?
1,为什么需要统一异常管理
这个问题也挺简单,当我们在服务端开发时总会遇到一些无法避免的异常,或由于自己疏忽导致的异常等,如参数绑定异常等。
2,怎么对异常进行处理呢
第一种,在error/目录下编写两个html页面,以4xx,5xx命名
原因:默认情况下,发送异常之后,spring底层会发送一个/error请求,处理所有错误的映射
对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。
对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据。
如果我们编写了错误页面,那么就会把响应状态码作为错误页的地址,error/状态码.html
模板引擎最终响应这个页面 error/状态码.html
第二种,自定义异常处理器
实现HandlerExceptionResolver接口,并放入容器@Component,最后@Order调整优先级
首先我们需要先了解spring给我们提供的默认异常处理器
发送异常之后,srping会依次遍历这些异常处理器来进行处理。
所以异常处理器的遍历顺序也就会对彼此进行影响。
默认情况下,我们自定义异常处理器会在最后遍历到。
所以如果我们想让我们的自定义异常处理器能够完全接管异常处理,可以使用设置优先级来进行调整。 @Order(value = Ordered.LOWEST_PRECEDENCE),数值越小,优先级越高
@Order(value = Ordered.LOWEST_PRECEDENCE)
@Component
@Slf4j
public class MyyExceptionController implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView();
mv.setViewName("main");
mv.addObject("err", ex.getMessage());
log.info(ex.getMessage());
if (handler != null) {
log.info(String.valueOf(handler.getClass()));
}
//一般返回null,才会遍历下一个异常处理器,如果设置优先级太高,也就会导致所有的异常都会由这个异常处理器处理
return mv;
}
}
第三种,就是对特定的异常进行处理
@ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的
代码实现
//推荐使用,理论上可以处理所有异常
@Slf4j
@ControllerAdvice
public class MyExeptionController {
//能够处理异常数组,自己选择
@ExceptionHandler({ArithmeticException.class, NullPointerException.class, TooMangException.class, MissingServletRequestParameterException.class})//参数绑定异常
public String soleve(Exception e){
log.error("异常信息{}" + e);
return "table/basic_table";//页面
}
}
自定义异常@ResponseStatus
有时候我们会发现java给我们提供的异常不够用,比如我们不想让某个表的数据量过多,我们希望能够有一个异常来体现。这个时候就需要自己定义我们需要的异常。
@ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息进行封装,value:状态码,reason:异常说明
//这个只是增加了框架中的异常种类而已
//这个一般是java底层的异常种类不够用时才使用,抛出的异常也可以被上面第三点接收处理
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "数量太多了")
public class TooMangException extends RuntimeException{
public TooMangException() {
super();
}
public TooMangException(String message) {
super(message);
}
}
//在需要的地方throw new TooMangException();即可