SpringBoot处理异常的5种方式
- @ControllerAdvice
- 用于修饰类,表示该类是Controller的全局配置类。
- 在此类中,可以对Controller进行如下三种全局配置: 异常处理方案、绑定数据方案、绑定参数方案。
- @ExceptionHandler
- 用于修饰方法,该方法会在Controller出现异常后被调用,用于处理捕获到的异常。
- @ModelAttribute
- 用于修饰方法,该方法会在Controller方法执行前被调用,用于为Model对象绑定参数。
- @DataBinder
- 用于修饰方法,该方法会在Controller方法执行前被调用,用于绑定参数的转换器。
一、自定义错误页面
1.1 SpringBoot 默认的处理异常的机制:
SpringBoot 默认的已经提供了一套处理异常的机制。一旦程序中出现了异常 SpringBoot 会像/error 的 url 发送请求。在 springBoot 中提供了一个叫 BasicExceptionController 来处理/error 请求,然后跳转到默认显示异常的页面来展示异常信息。
1.2 如 果 我 们需要将 所 有 的 异 常 同 一 跳 转 到 自 定 义 的 错 误 页 面 , (需要在src/main/resources/templates 目录下创建error.html页面。注意:名称必须叫 error ??)
然后再处理模板:
1、声明 thymeleaf 模板
2、修改静态资源/相对路径
3、复用首页等头部信息
注解处理异常
由spring提供的全局配置类,本次只用到ExceptionHandler注解。在controller包下新建advice包,新建ExceptionAdvice。
新建通知类
package com.nowcoder.community.controller.advice;
import com.nowcoder.community.util.CommunityUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice {
private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
@ExceptionHandler({Exception.class})
public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
// 记录日志
logger.error("服务器发生异常: " + e.getMessage()); // 异常概括
for (StackTraceElement element : e.getStackTrace()) { // 遍历栈
logger.error(element.toString());
}
// 根据是否是异步请求,返回给浏览器不同的结果
// 请求中获取请求头参数x-requested-with
String xRequestedWith = request.getHeader("x-requested-with");
if ("XMLHttpRequest".equals(xRequestedWith)) { // 说明是异步请求,浏览器希望得到json对象
// 向浏览器返回普通字符串,然后人为的转换为json对象
response.setContentType("application/plain;charset=utf-8"); //声明字符集,支持中文
PrintWriter writer = response.getWriter(); // 获取输出流
writer.write(CommunityUtil.getJSONString(1, "服务器异常!")); // 输出json字符串
} else {
// 否则,不是异步请求,重定向到error界面
response.sendRedirect(request.getContextPath() + "/error");
}
}
}
代码逻辑:
1、@ControllerAdvice(annotations = Controller.class):注解只扫描带有controller注解的那些Bean,这些Bean被统一处理
2、@ExceptionHandler({Exception.class}):表示该方法会处理捕捉到的所有异常(因为 Exception 是所有异常的父类)
好处:不需要对任何一个controller进行处理,就可以捕获异常