我们今天搞一下全局异常处理,在SpringBoot中用自定义的页面来替换掉默认的异常页面。
一、自定义页面
自定义静态异常页面两种方式,第一种是使用HTTP响应码来命名页面,例如 404.html、405.html、500.html ....,另一种就是直接定义一个 4xx.html,表示400-499 的状态都显示这个异常页面,5xx.html 表示 500-599 的状态显示这个异常页面。
我觉得第一种就足够用了,搞一下:
页面默认是在classpath:/static/error/路径下定义:
400页面
<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>Title</title></head><body><h1>404</h1><p>找不到页面啦!</p></body></html>
500页面
<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>Title</title></head><body><h1>500</h1><p>服务异常,请联系管理员!</p></body></html>
这时启动项目,400的错误就会找到400页面,500的就会去找到500页面。我们发布个接口服务测试下:
"/test") (publicResponseCommon<Object>select(){ ResponseCommonaa=null; aa.getCode(); returnaa; }
测试:
输入一个不存在的路径,可以看到找到了404页面:
输入服务接口,造成空指针异常,找到了500页面:
二、@ControllerAdvice注解实现全局异常统一处理
1.建一个公共响应来统一响应格式
packagecom.xing.carPool.common; importlombok.Data; /*** 公共响应* @param <T>*/publicclassResponseCommon<T> { privateStringcode; privateStringmsg; privateTdata; publicResponseCommon(){ } /*** 成功* @param data data* @return res*/publicstaticResponseCommon<Object>success(Objectdata) { ResponseCommon<Object>res=newResponseCommon<>(); res.setCode(CommonConstants.SUCCESS_CODE); res.setMsg(CommonConstants.SUCCESS_MESSAGE); res.setData(data); returnres; } /*** 失败* @return res*/publicstaticResponseCommon<Object>error(Stringmsg) { ResponseCommon<Object>res=newResponseCommon<>(); res.setCode(CommonConstants.ERROR_CODE); res.setMsg(msg); res.setData(""); returnres; } }
2.自定义一个业务异常
packagecom.xing.carPool.excetion; /*** 自定义异常*/publicclassValidateExceptionextendsRuntimeException { publicValidateException(Stringmsg) { super(msg); } publicValidateException(Stringmsg, Throwablee) { super(msg, e); } }
3.全局异常处理类
packagecom.xing.carPool.excetion; importcom.xing.carPool.common.ResponseCommon; importlombok.extern.slf4j.Slf4j; importorg.springframework.web.bind.annotation.ControllerAdvice; importorg.springframework.web.bind.annotation.ExceptionHandler; importorg.springframework.web.bind.annotation.ResponseBody; importjavax.servlet.http.HttpServletRequest; /*** 全局异常处理*/publicclassGlobalExceptionHandler { /*** 处理自定义的业务异常* @param req req* @param e 异常* @return ResponseCommon*/value=ValidateException.class) (publicResponseCommon<Object>validateExceptionHandler(HttpServletRequestreq, ValidateExceptione){ log.error("发生业务异常!原因是:{}",e.getMessage()); returnResponseCommon.error(e.getMessage()); } /*** 处理空指针的异常* @param req req* @param e 异常* @return ResponseCommon*/value=NullPointerException.class) (publicResponseCommon<Object>exceptionHandler(HttpServletRequestreq, NullPointerExceptione){ log.error("发生空指针异常!原因是:",e); returnResponseCommon.error(e.getMessage()); } /*** 处理其他异常* @param req req* @param e 异常* @return ResponseCommon*/value=Exception.class) (publicResponseCommon<Object>exceptionHandler(HttpServletRequestreq, Exceptione){ log.error("未知异常!原因是:",e); returnResponseCommon.error(e.getMessage()); } }
4.测试
我们直接访问上述空指针的那个接口:
不要出现null,换个汉字:
value=NullPointerException.class) (publicResponseCommon<Object>exceptionHandler(HttpServletRequestreq, NullPointerExceptione){ log.error("发生空指针异常!原因是:",e); returnResponseCommon.error("空指针"); }
再访问:
好了哈,这下有错误直接抛就对啦!
总结:
在classpath:/static/error/路径下自定义静态页面可以替换默认的异常页面,开发接口的时候,可以用@ControllerAdvice注解实现全局异常统一处理,注意一点Exception是所有异常的父类,子类异常一定要放在父类异常的前面,要不就直接被父类拦截处理啦!
END