1. 异常定义
异常:阻止当前方法或作用域继续执行的问题。虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常。绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败。之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意。
2. 异常体系
2.1. Throwable
Throwable 类是 Java 语言中所有错误或异常的超类(这就是一切皆可抛的东西)。它有两个子类:Error和Exception。
2.2. Error
Error:用于指示合理的应用程序不应该试图捕获的严重问题。这种情况是很大的问题,大到你不能处理了,所以听之任之就行了,你不用管它。比如说VirtualMachineError:当 Java 虚拟机崩溃或用尽了它继续操作所需的资源时,抛出该错误。好吧,就算这个异常的存在了,那么应该何时,如何处理它呢??交给JVM吧,没有比它更专业的了。
2.3. Exception
Exception:它指出了合理的应用程序想要捕获的条件。
Exception又分为两类:一种是CheckedException,一种是UncheckedException。这两种Exception的区别主要是CheckedException需要用try...catch...显示的捕获,而UncheckedException不需要捕获。
2.3.1. UncheckedException(RuntimeException)
通常UncheckedException又叫做RuntimeException。
《effective java》指出:对于可恢复的条件使用被检查的异常(CheckedException),对于程序错误(言外之意不可恢复,大错已经酿成)使用运行时异常(RuntimeException)。
我们常见的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException等等。
2.3.2. CheckedException
对于那些CheckedException就不胜枚举了,我们在编写程序过程中try...catch...捕捉的异常都是CheckedException。io包中的IOException及其子类,这些都是CheckedException。
3. 异常处理
3.1. try,catch,finally
三个语句块的执行顺序是try—>catch—>finally。
注意:在使用try..catch..finally块的时候,注意千万不要在finally块中使用return,因为finally中的return会覆盖已有的返回值。
切忌使用空catch块
3.2. throws和thow关键字
- throws出现在方法的声明中,表示该方法可能会抛出的异常。
- throw只会出现在方法体中,抛出一个异常。 throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
4. 自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
4.1. 示例
package pers.h.springbootdemo.exception;
/**
* @author :h
* @description:自定异常处理测试异常
* @date :Created in 2020/2/22 11:26
*/
public class TestException extends RuntimeException {
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public TestException(String message) {
super(message);
}
}
测试
/**
* 测试异常
*
* @author :h
* @date :Created in 2020/3/1 12:21
*/
public class ExceptionMainDemo {
public static void main(String[] arg) {
throw new TestException("测试自定义异常");
}
}
结果
5. @ControllerAdvice注解拦截controller异常并统一处理。
@ControllerAdvice是一个特殊的@Component,用于标识一个类,这个类中被以下三种注解标识的方法:@ExceptionHandler,@InitBinder,@ModelAttribute,将作用于所有的@Controller类的接口上。
5.1. @ExceptionHandler
Annotation for handling exceptions in specific handler classes and/or handler methods. 用于在特定处理程序类和/或处理程序方法中处理异常的注释。
5.1.1. 示例:
将会拦截Controller的TestException异常
@ControllerAdvice
public class MyExceptionHandler {
// Annotation for handling exceptions in specific handler classes and/or handler methods.
// 转发到系统的错误处理
// @ExceptionHandler(TestException.class)
// public String handleException(Exception e, HttpServletRequest request) {
// Map<String, Object> map = new HashMap<>();
// /*对异常信息进行处理*/
// //传入我们自己的错误状态码 4xx 5xx
// Integer statusCode = (Integer) request
// .getAttribute("javax.servlet.error.status_code");
// request.setAttribute("javax.servlet.error.status_code", 400);
// map.put("code", "user.notexist");
// map.put("message", "用户出错啦");
// request.setAttribute("ext", map);
//
// //转发到/error
// return "forward:/error";
// }
// Annotation for handling exceptions in specific handler classes and/or handler methods.
@ExceptionHandler(TestException.class)
@ResponseBody
public Map handleException(Exception e, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
/*对异常信息进行处理*/
//传入我们自己的错误状态码 4xx 5xx
Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
map.put("code", statusCode);
map.put("message", "自定义异常出错了!");
//转发到/error
return map;
}
}
//调用
@RequestMapping({"/errorTest"})
public String errorTest() {
throw new TestException("测试自定义异常");
}
结果
6. springboot自定义异常数据和页面。
在templates文件或static静态资源目录下创建对应的目录和文件即可,springboot会默认先从templates目录下寻找,其次在static目录下寻找,如果还是没有则使用系统默认的。