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这样的错误就不会去管
以上就是我的⼀些寡谈,有错误欢迎指正


发布评论