有天上飞的概念, 就要有落地的实现
概念十遍不如代码一遍, 朋友, 希望你把文中所有的代码案例都敲一遍
先赞后看, 养成习惯
SpringBoot 图文教程系列文章目录
SpringBoot 图文教程 1-SpringBoot+Mybatis 环境搭建 https://mp.weixin.qq.com/s/phk6j3ChBP-kPtS2xZeEZg
SpringBoot 图文教程 2 - 日志的使用「logback」「log4j」 https://mp.weixin.qq.com/s/7Mw_xhFF4Q5NtdtcsHc67Q
SpringBoot 图文教程 3-「'初恋'情结」集成 Jsp https://mp.weixin.qq.com/s/BYzVg5NBcF_ou_PyX8ygag
SpringBoot 图文教程 4-SpringBoot 实现文件上传下载 https://mp.weixin.qq.com/s/6ctykPo3eDBEB7YsC0PAZw
SpringBoot 图文教程 5-SpringBoot 中使用 Aop https://mp.weixin.qq.com/s/17qMRlv_mUfwkcVD05Bh2g
SpringBoot 图文教程 6-SpringBoot 中过滤器的使用 https://mp.weixin.qq.com/s/r2BO4UMNRAw_REA6nNFLKw
SpringBoot 图文教程 7-SpringBoot 拦截器的使用姿势这都有 https://mp.weixin.qq.com/s/YpDhuOTpt1vjYjnhnK8YdQ
SpringBoot 图文教程 8-SpringBoot 集成 MBG「代码生成器」 https://mp.weixin.qq.com/s/uGYO4fkw03Kxpfp_PIA8rQ
SpringBoot 图文教程 9-SpringBoot 导入导出 Excel 「Apache Poi」 https://mp.weixin.qq.com/s/BXfxhO5rFFg6XZQ0rZgGMg
SpringBoot 图文教程 10 - 模板导出 | 百万数据 Excel 导出 | 图片导出「easypoi」 https://mp.weixin.qq.com/s/8Yqfn27UCFP2lU3_IYb5AQ
SpringBoot 图文教程 11 - 从此不写 mapper 文件「SpringBoot 集成 MybatisPlus」 https://mp.weixin.qq.com/s/8KG5Wj77MYEUCIRFqWBdPQ
SpringBoot 图文教程 12-SpringData Jpa 的基本使用 https://mp.weixin.qq.com/s/gPfSjBj1hMWf23J50d5Z_g
SpringBoot 图文教程 13-SpringBoot+IDEA 实现代码热部署 https://mp.weixin.qq.com/s/DYP_12V01D0NJGEBdwK9Ew
SpringBoot 图文教程 14 - 阿里开源 EasyExcel「为百万数据读写设计」 https://mp.weixin.qq.com/s/FNuL3maNtiFCVR7hREYpLA
前言
本文教程示例代码见码云仓库: https://gitee.com/bingqilinpeishenme/boot-demo
异常处理在 Java 中是一种很常规的操作, 在代码中我们常用的方法是 try catch 或者上抛异常.
但是, 如果 Controller 发生异常了怎么办? 业务层的异常可以在 Controller 捕获, Controller 抛出的异常怎么捕获? SpringMvc 的异常怎么捕获?
这个时候常见的操作有两种:
跳转错误页面, 例如: 找不到路径的时候跳转 404, 代码报错的时候跳转 500 等
响应统一的报错信息, 使用 Result 对象 (自定义的实体类) 封装错误码, 错误描述信息响应[分布式服务调用的时候推荐使用]
今天我们就简单的来讲解一下 SpringBoot 中如何进行异常处理, 跳转 404 或者封装错误信息响应.
跳转错误页面
SpringBoot 错误页面的默认配置
在 SpringBoot 中 error page 错误页面是有默认配置的, 默认配置是这样
如果在 static 目录中存在 error 文件夹, 并且文件夹中存在 400.html, 或者 500.HTML, 出现对应的响应状态的时候(404 和 500 的使用), 会跳转到对应的页面
如果你使用的是 webapp 目录, 也是一样的, 只要在 webapp 目录中存在 400.jsp 页面(HTML 也一样), 出现对应的响应状态的时候(404 和 500 的使用), 会跳转到对应的页面
以上是默认配置, 只要是 SpringBoot 的项目都会生效, 接下来我们来测试一下
在 static 目录下创建 error 文件夹, 400.HTML 以及 500.HTML
写一个会报错的 Controller 方法 test500
启动项目分别访问一个不存在的路径[测试] 和访问会报错的 Controller 方法, 效果如下
自定义错误页面的配置
以上是 SpringBoot 关于错误页面的默认配置, 但是很多时候我们的需求比 SpringBoot 的默认配置要复杂很多, 例如: 404 页面不想放在 error 文件夹下, 500 错误的时候也不想跳转页面, 而是响应给页面一个 JSON 的数据等.
这个时候需要做的就是修改 SpringBoot 的默认配置了.
实现的目标:
404 的时候跳转到 static 下的 404 页面
500 的时候响应页面一句话:"后台错误 请联系管理员"
第一步: 创建一个能够响应 "后台错误 请联系管理员" 这句话的 Controller 方法, 将 404 页面放在 static 下面[如果是 webapp 也一样]
第二步: 创建错误页面的配置类, 修改默认的配置
- /**
- * 错误页面配置
- *
- * 继承错误页面注册器 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 页面
访问 http://localhost:8802/test500 效果如下:
以上就是跳转 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. 写两个测试方法 测试全局异常捕获的效果
访问 http://localhost:8802/testReturnPage 会跳转错误页面
访问 http://localhost:8802/testReturnResult 会返回统一的 JSON 数据
总结
恭喜你完成了本章的学习, 为你鼓掌! 如果本文对你有帮助, 请帮忙点赞, 评论, 转发, 这对作者很重要, 谢谢.
让我们再次回顾本文的学习目标
掌握 SpringBoot 中异常处理的基本使用
要掌握 SpringBoot 更多的用法, 请持续关注本系列教程.
求关注, 求点赞, 求转发
来源: https://www.cnblogs.com/bingyang-py/p/12482680.html