2023年11月29日发(作者:)
SpringBoot全局异常拦截捕获处理
⽂章⽬录
SpringBoot 全局异常拦截捕获
⼀、为什么要定义全局异常捕获?
在写代码的时候,可能每个⽅法都会涉及到异常情况!
spring boot 默认情况下会映射到 /error 进⾏异常处理,但是提⽰并不⼗分友好
通常展⽰到页⾯是这样的!!
code: 500 msg: “Failed to convert property value of type ‘’ to required type ‘r’ for
property ‘showId’; nested exception is FormatException: For input string: “eqwe””
或者是这样的页⾯
那么这个时候呢…由于杂乱不堪的错误提⽰页⾯,⽤户看不懂,所以对⽤户来说呢,体验很差
在开发前后端⼀体的单体项⽬时候呢,为了让异常在页⾯显⽰上更好看⼀点,让⽤户体验性更好⼀点,我们通常可以⾃定义⼀些精巧可爱的异
常页 例如 404页⾯ 500页⾯ 401 403 页⾯等等…
现在如⽕如荼的前后端分离模式正在每个公司进⾏,前端的请求到了后端后呢,通常后端是以json形式将数据返回给前端…这个时候,如果
服务器内部出现异常,我们如何处理呢?或者因为前端传递的参数后端业务处理不同过,我们⼿动抛了异常,苛求之前的数据库操作进⾏回
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AjaxResult {
private Integer code;
private String message;
private Object data;
public static AjaxResult success(Object data) {
return AjaxResult.builder().code(200).message("success").data(data).build();
}
public static AjaxResult error(String message,Integer code) {
return AjaxResult.builder().code(code).message(message).build();
}
public static AjaxResult error(String message) {
return AjaxResult.builder().code(-1).message(message).build();
}
}
那么,我们可以将拦截到的异常也构建为这样⼀个对象,返回给前端,前端根据code 判断请求是否成功,然后进⾏友好的提⽰即可…
(1)全局异常设置⽰例:
当我们假设有如下接⼝时: 很明显,当传参为0 时肯定会报错 除数不能为0…
我们针对该异常的捕获措施:
定义类,打上@ 注解,
RestControllerAdvice
public class ExceptionsHandler {}
编写捕获异常⽅法…
/** 0 */
除数不能为
@ExceptionHandler({ArithmeticException.class})
public AjaxResult arithmeticException(ArithmeticException ex) {
log.error("除数不能为0:{} ", ex.getMessage(), ex);
return AjaxResult.error("除数不能为0");
}
如此设置后呢,服务器就能捕获到除数不能为0异常了!
(2)⾃定义异常如何捕获
开发中,我们通常会⾃定义⼀些异常,并且抛出该异常,以达到程序终⽌或数据库操作回滚的⽬的…那么针对⾃定义的异常,我们⼜如何回
滚呢??
⾸先,我们来⾃定⼀个异常…
@Data
public class CommonException extends RuntimeException {
private String message;
private Integer code=-1;
public CommonException() {
}
public CommonException(String message) {
this.message = message;
}
}
编写业务代码,抛出我们的遗产信息
然后呢,我们需要在增强类中,去捕获我们新增的异常…
@ExceptionHandler(CommonException.class)
public AjaxResult CommonException(CommonException exception) {
log.error("公共异常抛出:{}", exception.getMessage());
return AjaxResult.error("公共异常抛出",exception.getCode());
}
这样就可以捕获到咱们⾃定的异常并返回给全端相同格式数据了!
(3)常⽤异常捕获分享
下边是关于项⽬中,常⽤的⼀些异常捕获…
import FileNotFoundException;
import IOException;
import SQLException;
import Slf4j;
import ConversionNotSupportedException;
import TypeMismatchException;
import NoSuchBeanDefinitionException;
import HttpMessageNotReadableException;
import HttpMessageNotWritableException;
import BadSqlGrammarException;
import ExceptionHandler;
import RestControllerAdvice;
/**
* @author leilei
* @version 1.0
* @date 2020/10/21 10:21
* @desc: json
全局异常拦截返回数据响应
*/
@Slf4j
@RestControllerAdvice
public class ExceptionsHandler {
/** */
运⾏时异常
@ExceptionHandler(RuntimeException.class)
public AjaxResult runtimeExceptionHandler(RuntimeException ex) {
log.error("运⾏时异常:{}", ex.getMessage(), ex);
return AjaxResult.error("运⾏时异常");
}
/** */
空指针异常
@ExceptionHandler(NullPointerException.class)
public AjaxResult nullPointerExceptionHandler(NullPointerException ex) {
log.error("空指针异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("空指针异常");
}
/** */
类型转换异常
@ExceptionHandler(ClassCastException.class)
public AjaxResult classCastExceptionHandler(ClassCastException ex) {
log.error("类型转换异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("类型转换异常");
}
/** */
⽂件未找到异常
@ExceptionHandler(FileNotFoundException.class)
public AjaxResult FileNotFoundException(FileNotFoundException ex) {
log.error("⽂件未找到异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("⽂件未找到异常");
}
}
/** */
数字格式异常
@ExceptionHandler(NumberFormatException.class)
public AjaxResult NumberFormatException(NumberFormatException ex) {
log.error("数字格式异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("数字格式异常");
}
/** */
安全异常
@ExceptionHandler(SecurityException.class)
public AjaxResult SecurityException(SecurityException ex) {
log.error("安全异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("安全异常");
}
/** sql */
异常
@ExceptionHandler(SQLException.class)
public AjaxResult SQLException(SQLException ex) {
log.error("sql异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("sql异常");
}
/** */
类型不存在异常
@ExceptionHandler(TypeNotPresentException.class)
public AjaxResult TypeNotPresentException(TypeNotPresentException ex) {
log.error("类型不存在异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("类型不存在异常");
}
/** IO */
异常
@ExceptionHandler(IOException.class)
public AjaxResult iOExceptionHandler(IOException ex) {
log.error("IO异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("IO异常");
}
/** */
未知⽅法异常
@ExceptionHandler(NoSuchMethodException.class)
public AjaxResult noSuchMethodExceptionHandler(NoSuchMethodException ex) {
log.error("未知⽅法异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("未知⽅法异常");
}
/** */
数组越界异常
@ExceptionHandler(IndexOutOfBoundsException.class)
public AjaxResult indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
log.error("数组越界异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("数组越界异常");
}
/** sql */
语法错误异常
@ExceptionHandler(BadSqlGrammarException.class)
public AjaxResult BadSqlGrammarException(BadSqlGrammarException ex) {
log.error("sql语法错误异常:{} ", ex.getMessage(), ex);
return AjaxResult.error("sql语法错误异常");
}
/** bean */
⽆法注⼊异常
@ExceptionHandler(NoSuchBeanDefinitionException.class)
public AjaxResult NoSuchBeanDefinitionException(NoSuchBeanDefinitionException ex) {
log.error("⽆法注⼊bean异常 :{} ", ex.getMessage(), ex);
return AjaxResult.error("⽆法注⼊bean");
}
/** Http */
消息不可读异常
@ExceptionHandler({HttpMessageNotReadableException.class})
public AjaxResult requestNotReadable(HttpMessageNotReadableException ex) {
log.error("400错误..requestNotReadable:{} ", ex.getMessage(), ex);
return AjaxResult.error("Http消息不可读");
}
}
/** 400 */
错误
@ExceptionHandler({TypeMismatchException.class})
public AjaxResult requestTypeMismatch(TypeMismatchException ex) {
log.error("400错误..TypeMismatchException:{} ", ex.getMessage(), ex);
return AjaxResult.error("服务器异常");
}
/** 500 */
错误
@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
public AjaxResult server500(RuntimeException ex) {
log.error("500错误:{} ", ex.getMessage(), ex);
return AjaxResult.error("服务器异常");
}
/** */
栈溢出
@ExceptionHandler({StackOverflowError.class})
public AjaxResult requestStackOverflow(StackOverflowError ex) {
log.error("栈溢出:{} ", ex.getMessage(), ex);
return AjaxResult.error("栈溢出异常");
}
/** 0 */
除数不能为
@ExceptionHandler({ArithmeticException.class})
public AjaxResult arithmeticException(ArithmeticException ex) {
log.error("除数不能为0:{} ", ex.getMessage(), ex);
return AjaxResult.error("除数不能为0异常");
}
/** */
其他错误
@ExceptionHandler({Exception.class})
public AjaxResult exception(Exception ex) {
log.error("其他错误:{} ", ex.getMessage(), ex);
return AjaxResult.error("⽹络连接失败,请退出后再试");
}
}
处理后返给前端的异常如下
{
"code": -1,
"message": "索引越界异常",
"data":null
}
{
"code": -1,
"message": "请求⽂件不存在异常",
"data": null
}
需要注意的是. 异常捕获并⾮万能,有些异常是捕获不了的…例如404等…
RestControllerExceptionHandler
(4)404如何捕获?
我们都知道,web服务错误后,默认是将url映射到 /error
其源码是这样处理的…
在收到错误信息后,返回了⼀个model andView …
那么,我们可以,在服务器将错误请求映射url 时做⼀些处理,使其转发到我们定义的错误url
/error
其实也很简单…定义⼀个类 实现的接⼝ 即可
springErrorController
例如这样:
@RestController
public class MyExceptionController implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping(value = {"/error"})
public AjaxResult error(HttpServletRequest request, HttpServletResponse response) {
int status = response.getStatus();
if (status == 404) {
return AjaxResult.error("404啦!!", 404);
}
return AjaxResult.error("错误了", -1);
}
}
当服务器收到 /error 路径时转发到我们的/error,然后我们返回json数据即可…
实践操作:
当我们请求⼀个服务器不存在的url时候…
如此,便是完成了对异常的捕获了!
404


发布评论