2023年11月29日发(作者:)

SpringBoot全局错误处理的两种⽅式:注解法和覆盖路径法

SpringBoot全局错误处理的两种⽅式:注解法和覆盖路径法

⽂章⽬录

引⾔

对于系统中的异常处理是⼀个⼤问题,需要考虑⼏个问题,⽂后回答

1. 代码中的异常什么时候该抛,什么时候该捕获

2. 系统内部的异常应该在什么位置捕获,controller,service还是dao层

3. 异常应该怎么处理,捕获到异常后应该怎么返回信息

4. 后台应该处理的错误范围是那些

/** * */

异常处理

@ControllerAdvice(basePackages = "ller")

public class MyExceptionHandler {

/**

* IO

处理异常

* @param e

* @return

*/

@ExceptionHandler

public ResponseEntity runTimeExceptionMatchHandle(

IOException e, HttpServletRequest request,

HttpServletResponse response){

System.out.println(request.getMethod());

System.out.println(response);

return return new ResponseEntity(new Object, HttpStatus.OK);

}

/**

*

处理异常

* @param e

* @return

*/

@ExceptionHandler

public ResponseEntity exceptionMatchHandle(Exception e){

if(e instanceof AccessException){

//

做处理

}else if (e instanceof ...)

return return new ResponseEntity(new Object, HttpStatus.OK);

}

}

1. 注解配置好要扫的包

2. ⽅法内部做异常的处理⽅法,参数中的异常等同于注解中的配置,可以很细化,也可以⽐较泛化(注解和参数都有的话注解优先,参数

可能会失效)

3. 当出现异常时,spring 会优先找该异常最近的实现,然后将该异常以及其他servlet信息传给这个⽅法去处理。

4. 这个形式处理⾃定义异常⽐较⽅便,对待⾃⼰已知的并细化给出返回信息

5. ⽅法的返回类型必须是seEntity,不然的话,会发现,接⼝最终返回的结果跟你想象得不⼀样,

因为如果不是ResponseEntity,那么发⽣异常的时候还是会找 /error 路径下的⽅法。

6. 不过要想返回⾃定义的返回数据类型也可以,需要在⽅法上加 @ResponseBody 注解,或者在类上加上 @RestController

SpringBoot全局错误处理第⼆种⽅法:覆盖路径法

此⽅法范围⽐较⼴,可以处理404错误

实现逻辑:

在Spring Boot中,Controller中抛出的异常默认交给了 /error(可以通过属性覆盖)来处理,应⽤程序可以将/error

映射到⼀个特定的Controller中处理来代替Spring Boot的默认实现,可以使⽤继承 AbstractErrorController 来统⼀处理系统的各种异

常。

实现⽅法

1. 继承 AbstractErrorController

2. 实现默认⽅法 public String getErrorPath()

3. 实现构造⽅法,并加上@Controller注解

4. 在类的内部写⼀个具体的错误处理⽅法,并将该⽅法映射路径为("/error");如果修改过就使⽤修改过的错误处理路径。

5. ⽰例代码如下:构造⽅法以及实现默认⽅法参考BasicErrorController,该类是Spring Boot默认的处理,可以参考该类来实现⾃⼰

@Controller

public class MyErrorController extends AbstractErrorController{

//

该属性可以做其他⽤,可以获取错误的相关信息,可以⾃⾏查看其⽅法

private final ErrorProperties errorProperties;

public MyErrorController(ErrorAttributes errorAttributes,

ServerProperties serverProperties{

super(errorAttributes);

this.errorProperties = serverProperties.getError();

}

@Override

public String getErrorPath() {

return errorProperties.getPath();

}

/**

*JSON

处理错误:处理错误返回

* @param request

* @return

*/

@RequestMapping("${:${:/error}}")

@ResponseBody

public ModelAndView error(HttpServletRequest request,HttpServletResponse response){

//Accept”application/json“json

做异常处理或者其他判断,可以根据请求头中的属性是否为,来区别回或者渲染的界⾯

return Response.failure(ErrorCode.ERROR);

}

protected ErrorProperties getErrorProperties() {

return this.errorProperties;

}

}

BasicErrorController的构造⽅法是(ErrorAttributes errorAttributes, ErrorProperties errorProperties)

但在运⾏的时候可能会报异常,ErrorProperties可以通过ServerProperties注⼊。

获取异常的⽅法:

//request

如果流被提取过那么这个异常就可能获取不到,例如注解与路径覆盖法同时⽤

protected Throwable getCause(HttpServletRequest request){

Throwable error = (Throwable)request.getAttribute("ion");

if (error!=null){

//MVCServletException,getCause

有可能会封装异常成需要调⽤获取真正的异常

while(error instanceof ServletException && error.getCause() !=null){

error = ((ServletException) error).getCause();

}

}

return error;

}

两种⽅式的区别

1. 注解⽅法,原理基于AOP;路径覆盖⽅法,基于Control的HandleMapping和HandleAdapter

2. 注解⽅法,可以在⽅法参数中直接获得异常;路径覆盖⽅法,获取异常要基于request,⽐较复杂

3. 优先顺序:同时存在的话,注解先执⾏,覆盖路径的⽅法后执⾏(针对情况:如果没有设置返回参数类型(ResponseEntity)或者加

注解ResponseBody,被注解⽅法处理过后,还会在经过路径覆盖⽅法的代码)

4. ContollerAdvice只能拦截控制器中的异常,换⾔之,只能拦截500之类的异常,但是对于404这样不会进⼊控制器处理的异常不起

作⽤

5. 建议还是使⽤注解法

总结以及回答上⾯的⽅法

现在的SpringBoot封装好东西,⽤起来都⽐较简单化了,如果没那么多的业务需求⽤注解⽐较简单。

回单上⾯的问题:

1. 代码中的异常什么时候该抛,什么时候该捕获

异常不能对业务,出现分⽀的,建议抛出去做处理直接返回,能够对业务起到分⽀的异常建议捕获做分⽀处理

2. 系统内部的异常应该在什么位置捕获,controller,service还是dao层

捕获的异常建议都在service捕获,dao抛出,controller抛出,controller不做异常处理

3. 异常应该怎么处理,捕获到异常后应该怎么返回信息

异常的信息返回,建议有⼀个统⼀的实体类如下,可以拟定状态码,甚⾄细化到每个异常的返回结果都不同

@Datapublic class Response<T> {

private String resMsg;

private int status;

private T data;

}

4. 后台应该处理的错误范围是那些

根据业务需求,有些只针对接⼝调⽤,那么类似于404这样的错误就不会去管

以上就是我的⼀些寡谈,有错误欢迎指正