程序的异常:Throwable
严重错误问题:Error 我们不处理。这种问题一般都是很严重的,我们一般处理不了,比如说内存溢出。
问题:Exception
1.运行期问题:RuntimeException 这种问题我们也不处理,因为是你写代码的问题,而且这个问题的出现肯定是我们的代码不够严谨,需要修正代码的。
2.编译期问题:不是RuntimeException的异常 必须进行处理的,因为你不处理,编译就不能通过。
如果程序出现了问题,我们没有做任何处理,最终JVM会做出默认的处理。
1.把异常的名称、原因及出现的位置等信息输出在控制台。
2.同时会结束程序。
(但是呢,其余没有问题的程序就不能继续执行了)
所以感觉JVM的默认处理不够好,既然不好那我们就自己来处理呗。
1、自定义错误页面
SpringBoot默认的异常处理机制:springboot默认提供了一套处理异常的机制。一旦程序出现了异常,SpringBoot会向/error的url发送请求。在springboot中提供了一个叫BasicErrorController 来处理/error 请求,然后跳转到默认显示异常的页面来展示异常信息。
如 果 我 们 需 要 将 所 有 的 异 常 统一 跳 转 到 自 定 义 的 错 误 页 面 , 需 要 再
src/main/resources/templates 目录下创建 error.html 页面。注意:名称必须叫 error
还可以在src/main/resources/templates/error目录下编写状态码.html文件,会默认先从这里找,找不到再找src/main/resources/templates下的error.html
2、@ExceptionHandle 注解处理异常
上一种方法不管发生什么异常,都只能跳转到一个页面,颗粒度太大,这一种方式可以实现对不同的异常做不同的处理。
@RequestMapping @Controller public class ExceptionController { @PostMapping("/exception") public String hello(){ //int i = 1/0; return "index"; } /** * 该方法返回ModelAndView:目的是为了可以让我们封装视图和错误信息 * @param e 参数 Exception e:会将产生异常对象注入到方法中 * @return */ @ExceptionHandler(value = {java.lang.ArithmeticException.class}) public ModelAndView arithmeticExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",e); mv.setViewName("error"); return mv; } }
优点:可以自定义存储异常信息的key,和跳转视图的名称。
缺点:需要编写大量的异常方法,不能跨controller,如果两个controller中出现同样的异常,需要重新编写异常处理方法。
3、@ControllerAdvice+@ExceptionHandler 注解处理异常
上一种方式必须要在每一个Controler里面重复写异常处理代码,代码复用性太差,这一种方法可以实现异常的全局处理。需要创建一个能够处理异常的全局异常类。在该类上需要添加@ControllerAdvice 注解
/** * 全局异常处理类 */ @ControllerAdvice public class GlobalController { /** * 该方法返回ModelAndView:目的是为了可以让我们封装视图和错误信息 * @param e 参数 Exception e:会将产生异常对象注入到方法中 * @return */ //拦截的异常可以写Exception @ExceptionHandler(value = {java.lang.ArithmeticException.class}) public ModelAndView arithmeticExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",e+"controllerAdvice"); mv.setViewName("error"); return mv; } }
缺点:编写大量的异常处理方法,代码冗余。
4、配置 SimpleMappingExceptionResolver 处理异常
上一种方式,每处理一种异常就要写一个处理方法,如果有很多异常需要处理,写起来会很麻烦,这一种方式可以很好的解决这种问题,需要在全局异常类中添加一个方法完成异常的统一处理。
/** * 通过 SimpleMappingExceptionResolver 做全局异常处理 */ @Configuration public class GlobalException { /** * 该方法必须要有返回值。返回值类型必须是: SimpleMappingExceptionResolver * @return */ @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties prop = new Properties(); //参数1:异常的全类名 参数2:视图的名字 prop.setProperty("java.lang.ArithmeticException","error"); prop.setProperty("java.lang.NullPointerException","error"); //设置异常与视图的映射信息 resolver.setExceptionMappings(prop); return resolver; } }
缺点:不显示具体异常信息
5、自定义 HandlerExceptionResolver 类处理异常
上一种方式不能在跳转页面的同时携带异常信息,这样不利于排错,当前这种方式可以解决上述问题,我们需 要 在全局异常处理类中实现HandlerExceptionResolver 接口。
/** * 通过实现 HandlerExceptionResolver 接口做全局异常处理 */ @Configuration public class GlobalException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mv = new ModelAndView(); //判断不同的异常类型跳转不同视图 if(ex instanceof ArithmeticException){ mv.setViewName("error"); } if(ex instanceof NullPointerException){ mv.setViewName("error"); } mv.addObject("errorMsg",ex.toString()); return mv; } }
通用异常处理:
1、自定义异常枚举类
public enum ExceptionEnum { //枚举常量 PRICE_CANNOT_BE_NULL(500,"商品价格不能为空"), ; private int code; //状态码 private String msg; //异常信息 ExceptionEnum() { } ExceptionEnum(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
2、自定义异常类
/** * 自定义异常类,继承RuntimeException */ public class MyException extends RuntimeException{ private ExceptionEnum exceptionEnum; public MyException() { } public MyException(ExceptionEnum exceptionEnum) { this.exceptionEnum = exceptionEnum; } public ExceptionEnum getExceptionEnum() { return exceptionEnum; } public void setExceptionEnum(ExceptionEnum exceptionEnum) { this.exceptionEnum = exceptionEnum; } @Override public String toString() { return "MyException{" + "exceptionEnum=" + exceptionEnum + '}'; } }
3、自定义异常结果处理类
/** * 自定义异常结果处理类 */ public class ResultException { private Integer statusCode; //状态码 private String message; //异常信息 private Long timeStamp; //时间戳 public ResultException() { } public ResultException(ExceptionEnum em){ this.statusCode = em.getCode(); this.message = em.getMsg(); this.timeStamp = System.currentTimeMillis(); } public Integer getStatusCode() { return statusCode; } public void setStatusCode(Integer statusCode) { this.statusCode = statusCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Long getTimeStamp() { return timeStamp; } public void setTimeStamp(Long timeStamp) { this.timeStamp = timeStamp; } @Override public String toString() { return "ResultException{" + "statusCode=" + statusCode + ", message='" + message + '\'' + ", timeStamp=" + timeStamp + '}'; } }
4、全局异常处理
/** * @ControllerAdvice + @ExceptionHandler +自定义异常 来做全局异常处理 */ @ControllerAdvice public class GlobalException { /** * 拦截自定义异常MyException * @param e * @return */ // @ExceptionHandler(MyException.class) // public @ResponseBody ResultException handlerRuntimeException(MyException e){ // ExceptionEnum exceptionEnum = e.getExceptionEnum(); // ResultException res = new ResultException(exceptionEnum); //
到此这篇关于springboot处理异常的5种方式的文章就介绍到这了,更多相关springboot处理异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!