异常传递
如图:服务层和dao层的异常最终都会到达控制层,控制层的异常则会自动记入logback日志系统。所以我们应该在控制层来捕获系统异常
捕获控制层异常
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- @Controller
- public class SampleController {
- //用来手动记录日志
- private static final Logger log = LoggerFactory.getLogger(SampleController.class);
- //触发除0异常
- @GetMapping("/test1")
- public void test1() {
- int i=1/0;
- }
- //触发空指针异常
- @GetMapping("/test2")
- public void test2() {
- String a=null;
- a.length();
- }
- //捕获除0异常
- @ExceptionHandler(ArithmeticException.class)
- public void exception1(ArithmeticException e){
- System.out.println("处理除0异常");
- //继续抛出异常,才能被logback的error级别日志捕获
- throw e;
- }
- //捕获空指针异常
- @ExceptionHandler(NullPointerException.class)
- public String exception2(NullPointerException e){
- System.out.println("处理空指针异常");
- //手动将异常写入logback的error级别日志
- log.error("空指针异常",e);
- return "/null.html";
- }
- }
这个控制类有两个映射,分别抛出两个不同的异常,@ExceptionHandler的方法会分别捕获其参数对应的异常。
现在访问http://localhost/test1,程序最后抛出异常,会跳转到一个系统默认的error页面,这个页面对用户是很不友好的。不过如果你配置了http响应码的跳转页面(以后会讲),或者搭建了nginx之类的代理服务器,可以根据这里的500响应码跳转到一个自定义的友好页面
访问http://localhost/test2,如果没有配置动态页面,最终会跳转到静态的null.html,这样可以给我们用户一个友好的提示页面。注意不能用error.html,这个页面已经被系统占用
捕获所有控制层异常
上面这个类只能捕获当前@Controller的异常,如果要捕获系统中所有@Controller的异常,只需要把类注解@Controller换成@ControllerAdvice。这就变成了一个专门处理异常的类,不过@GetMapping映射就不能再放在这里了
- @ControllerAdvice
- public class SampleController {