亲宝软件园·资讯

展开

SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」

鹿老师的Java笔记 人气:0
![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205829155-764801728.png) > **有天上飞的概念,就要有落地的实现** > > - 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 > > - 先赞后看,养成习惯 **SpringBoot 图文教程系列文章目录** 1. [SpringBoot图文教程1—SpringBoot+Mybatis 环境搭建](https://mp.weixin.qq.com/s/phk6j3ChBP-kPtS2xZeEZg) 2. [SpringBoot图文教程2—日志的使用「logback」「log4j」](https://mp.weixin.qq.com/s/7Mw_xhFF4Q5NtdtcsHc67Q) 3. [SpringBoot图文教程3—「‘初恋’情结」集成Jsp](https://mp.weixin.qq.com/s/BYzVg5NBcF_ou_PyX8ygag) 4. [SpringBoot图文教程4—SpringBoot 实现文件上传下载](https://mp.weixin.qq.com/s/6ctykPo3eDBEB7YsC0PAZw) 5. [SpringBoot图文教程5—SpringBoot 中使用Aop](https://mp.weixin.qq.com/s/17qMRlv_mUfwkcVD05Bh2g) 6. [SpringBoot图文教程6—SpringBoot中过滤器的使用](https://mp.weixin.qq.com/s/r2BO4UMNRAw_REA6nNFLKw) 7. [SpringBoot图文教程7—SpringBoot拦截器的使用姿势这都有](https://mp.weixin.qq.com/s/YpDhuOTpt1vjYjnhnK8YdQ) 8. [SpringBoot图文教程8—SpringBoot集成MBG「代码生成器」](https://mp.weixin.qq.com/s/uGYO4fkw03Kxpfp_PIA8rQ) 9. [SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」](https://mp.weixin.qq.com/s/BXfxhO5rFFg6XZQ0rZgGMg) 10. [SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」](https://mp.weixin.qq.com/s/8Yqfn27UCFP2lU3_IYb5AQ) 11. [SpringBoot图文教程11—从此不写mapper文件「SpringBoot集成MybatisPlus」](https://mp.weixin.qq.com/s/8KG5Wj77MYEUCIRFqWBdPQ) 12. [SpringBoot图文教程12—SpringData Jpa的基本使用](https://mp.weixin.qq.com/s/gPfSjBj1hMWf23J50d5Z_g) 13. [SpringBoot图文教程13—SpringBoot+IDEA实现代码热部署](https://mp.weixin.qq.com/s/DYP_12V01D0NJGEBdwK9Ew) 14. [SpringBoot图文教程14—阿里开源EasyExcel「为百万数据读写设计」](https://mp.weixin.qq.com/s/FNuL3maNtiFCVR7hREYpLA) ## 前言 > 本文教程示例代码见码云仓库:https://gitee.com/bingqilinpeishenme/boot-demo 异常处理在Java中是一种很常规的操作,在代码中我们常用的方法是try catch或者上抛异常。 但是,如果Controller发生异常了怎么办?业务层的异常可以在Controller捕获,Controller抛出的异常怎么捕获?SpringMvc的异常怎么捕获? 这个时候常见的操作有两种: 1. 跳转错误页面,例如:找不到路径的时候跳转404,代码报错的时候跳转500等 2. 响应统一的报错信息,使用Result对象(自定义的实体类)封装错误码,错误描述信息响应【分布式服务调用的时候推荐使用】 今天我们就简单的来讲解一下SpringBoot中如何进行异常处理,跳转404或者封装错误信息响应。 ## 跳转错误页面 ### SpringBoot 错误页面的默认配置 在SpringBoot中 error page错误页面是有默认配置的,默认配置是这样 - 如果在static目录中存在error文件夹,并且文件夹中存在400.html,或者500.html,出现对应的响应状态的时候(404和500的使用),会跳转到对应的页面 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205829501-641943563.png) - 如果你使用的是webapp目录,也是一样的,只要在webapp目录中存在400.jsp页面(html也一样),出现对应的响应状态的时候(404和500的使用),会跳转到对应的页面 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205830228-839152814.png) 以上是默认配置,只要是SpringBoot的项目都会生效,接下来我们来测试一下 1. 在static目录下创建error文件夹,400.html以及500.html ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205829501-641943563.png) 2. 写一个会报错的Controller方法 test500 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205831066-568235152.png) 3. 启动项目分别访问一个不存在的路径【测试】和访问会报错的Controller方法,效果如下 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205831501-1686966401.png) ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205831972-562426817.png) ### 自定义错误页面的配置 以上是SpringBoot关于错误页面的默认配置,但是很多时候我们的需求比SpringBoot的默认配置要复杂很多,例如:404页面不想放在error文件夹下,500错误的时候也不想跳转页面,而是响应给页面一个json的数据等。 这个时候需要做的就是修改SpringBoot的默认配置了。 > **实现的目标:** > - 404的时候跳转到static下的404页面 > - 500的时候响应页面一句话:“后台错误 请联系管理员” **第一步:创建一个能够响应 “后台错误 请联系管理员” 这句话的Controller方法,将404页面放在static下面【如果是webapp也一样】** ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205832429-1008488395.png) ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205832732-1881453929.png) **第二步:创建错误页面的配置类,修改默认的配置** ``` /** * 错误页面配置 * * 继承错误页面注册器 ErrorPageRegistrar */ @Configuration public class ErrorConfig implements ErrorPageRegistrar { @Override public void registerErrorPages(ErrorPageRegistry registry) { /** * 配置错误页面 * * ErrorPage 有两个参数 * 参数1 响应状态码 NOT_FOUND 404 INTERNAL_SERVER_ERROR 500 * 参数2 出现响应状态码的时候的跳转路径 可以自定义跳转路径 */ ErrorPage error404 = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/testData"); /** * 将ErrorPage 注册到注册器中 */ registry.addErrorPages(error404,error500); } } ``` **第三步:启动项目,可以看到如下效果** 访问不存在的路径,跳转404页面 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205833097-2000763405.png) 访问 http://localhost:8802/test500 效果如下: ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205833512-650920607.png) 以上就是跳转404和统一响应数据的操作,但是还有问题,什么问题呢? 以上的操作实际上没有针对异常进行捕获,而是根据响应的状态码进行不同的处理的,那么如果才能针对不同的异常进行捕获呢?这就要用到全局异常捕获了。 ## 全局异常捕获 还记得文章开头说过的第二个场景吗?使用Result对象(自定义的实体类)统一封装异常状态码,异常信息,进行返回。通过全局异常捕获就可以实现。 > 测试的要求是: > - 捕获自定义异常,封装Result对象以json的格式响应 > - 捕获自定义异常,跳转到错误页面 ### 1.自定义异常 在应用开发过程中,除系统自身的异常外,不同业务场景中用到的异常也不一样,很多时候需要自定义异常,所以我们自定义两个异常,分别是: - ErrorReturnResultException 如果出现这个异常,就返回统一Result对象 - ErrorReturnPageException 如果出现这个异常,就跳转错误页面 **ErrorReturnResultException** ``` package com.lu.bootexception.exception; public class ErrorReturnResultException extends RuntimeException { /** * 错误码 */ private int code; public ErrorReturnResultException() { } public ErrorReturnResultException(String message) { super(message); } public ErrorReturnResultException(String message, int code) { super(message); this.code = code; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } } ``` **ErrorReturnPageException** ``` package com.lu.bootexception.exception; public class ErrorReturnPageException extends RuntimeException { /** * 错误码 */ private int code; public ErrorReturnPageException() { } public ErrorReturnPageException(String message, int code) { super(message); this.code = code; } public ErrorReturnPageException(String message) { super(message); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } } ``` ### 2.自定义响应实体 定义返回的异常信息的格式,这样异常信息风格更为统一 ``` package com.lu.bootexception.exception; import lombok.Data; @Data @NoArgsConstructor @AllArgsConstructor public class Result { private int code; private String message; } ``` ### 3.全局异常捕获实现 利用Spring的API定义一个全局异常处理的类,代码和注释如下: ``` package com.lu.bootexception.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; /** * @ControllerAdvice 增强Controller的注解 可以实现全局异常捕获 */ @ControllerAdvice public class GlobalExceptionHandler { /** * @ExceptionHandler 指明要捕获那个异常 * 不加@ResponseBody 会使用视图解析器跳转页面 * 形参处是Exception 简单来说就是会把捕获到的异常通过形参传入方法中 */ @ExceptionHandler(ErrorReturnPageException.class) public String errorReturnPageException(Exception e){ // 打印错误信息 System.out.println(e.getMessage()); // 跳转500页面 return "forward:/500.html"; } /** * 捕获 ErrorReturnResultException 异常 * 通过 @ResponseBody 注解响应数据 会以json的格式响应 */ @ExceptionHandler(ErrorReturnResultException.class) @ResponseBody public Result errorReturnResultException(final Exception e) { ErrorReturnResultException exception = (ErrorReturnResultException) e; /** * Result 中可以写入自定义的异常状态码 */ return new Result(5001, exception.getMessage()); } /** * 捕获 RuntimeException 异常 */ @ExceptionHandler(RuntimeException.class) @ResponseBody public Result runtimeExceptionHandler(final Exception e) { RuntimeException exception = (RuntimeException) e; /** * Result 中可以写入自定义的异常状态码 */ return new Result(4004, exception.getMessage()); } } ``` > 代码中用到的注解 > - **@ControllerAdvice** 捕获抛出的异常,如果添加 `@ResponseBody` 返回信息则为`JSON`格式。 > - **@RestControllerAdvice** 相当于 `@ControllerAdvice` 与 `@ResponseBody` 的结合体。 > - **@ExceptionHandler** 指明要捕获那个异常 > ### 4.写两个测试方法 测试全局异常捕获的效果 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205834057-826215414.png) 访问 http://localhost:8802/testReturnPage 会跳转错误页面 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205834826-1556641335.png) 访问 http://localhost:8802/testReturnResult 会返回统一的json数据 ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205835239-1432527185.png) ## 总结 **恭喜你完成了本章的学习,为你鼓掌!如果本文对你有帮助,请帮忙点赞,评论,转发,这对作者很重要,谢谢。** ![](https://img2020.cnblogs.com/other/1003051/202003/1003051-20200312205835661-1791815467.gif) 让我们再次回顾本文的学习目标 > * 掌握SpringBoot中异常处理的基本使用 要掌握SpringBoot更多的用法,请持续关注本系列教程。 ## 求关注,求点赞,求转发 > 欢迎关注本人公众号:鹿老师的Java笔记,将在长期更新Java技术图文教程和视频教程,Java学习经验,Java面试经验以及Java实战开发经验。

加载全部内容

相关教程
猜你喜欢
用户评论