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

4404如何捕获?

我们都知道,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