一、Springboot捕获controller层异常
参考博客:https://blog.csdn.net/kinginblue/article/details/70186586
https://blog.csdn.net/lkforce/article/details/98494922
Spring boot项目中通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理。
1、@ExceptionHandler注解
优点:将Controller层的异常和数据校验的异常进行统一处理,减少模板代码,减少编码量,提升扩展性和可维护性。
缺点:只能处理Controller层未捕获(往外抛)的异常,对于Interceptor(拦截器)层的异常,Spring框架层的异常,就无能为力了。
1.1 @RestControllerAdvice注解定义全局异常处理类
通过注解@RestControllerAdvice统一处理rest接口的异常信息
@RestControllerAdvice
public class GlobalExceptionHandler {
}
1.2 @ExceptionHandler 注解声明异常处理方法
方法handleException()就会处理所有Controller层抛出的Exception及其子类的异常
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
String handleException(){
return "Exception Deal!";
}
}
1.3 注解的参数
@ExceptionHandler注解中可以添加参数,参数是某个异常类的class,代表这个方法专门处理该类异常
此时注解的参数是NumberFormatException.class,表示只有方法抛出NumberFormatException时,才会调用该方法
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NumberFormatException.class)
@ResponseBody
String handleException(){
return "Exception Deal!";
}
}
二、springboot捕获filter异常
1、问题背景
项目中使用@ExceptionHandler注解的方式统一controller层抛出的异常,即将统一错误信息格式,返回到前端页面,友好的展示给用户,但是在一些token认证或者鉴权认证中,如果认证失败,则不会继续走到controller层,因此抛出的错误信息无法被@ExceptionHandler捕获,使用的是springboot默认的异常拦截器,通过postman访问一个认证鉴权的url并认证失败后会,会返回如下一个错误结构,这个是springboot默认的错误信息返回结构。

2、解决这个问题网上大致有3种方法
方法1:继承springboot的BasicErrorController类,重写里面的error方法
@RestController
@Api(value = "handle filter throws exception", description = "处理filter抛出的异常")
public class ErrorController extends BasicErrorController {
public ErrorController() {
super(new DefaultErrorAttributes(), new ErrorProperties());
}
@Override
@RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",body.get("status"));
map.put("msg",body.get("message"));
return new ResponseEntity<Map<String, Object>>(map, status);
}
}
但是该方法在我的项目中不生效,网上却也有成功的案例,还不是很清楚为啥我的项目里继承这个类不生效
方法2:HandlerExceptionResolver
参考如下博客,该方法在我的项目中仍然不生效
方法3:把异常交给Controller处理
既然Filter中的异常,不能经过我们定义的异常处理类,那我们就把此异常交给controller,让controller经过异常处理类,帮我们处理。
(1)定义过滤器,将异常交给controller处理
(2)调整该过滤器的位置,将这个过滤器的位置要放在存在异常处理器的前面(原因看后面图解)
(3)定义处理异常的controller
具体实现可以参考如下博客:
该方法是个可行的法子,但是因为我的项目中没有controller层,不是webapp的应用,不能使用@PostMapping等方法,因此,第三个步骤对我来说不适用,故使用了第四种方法
方法4:定义优先级更高的filter,在该filter里直接进行异常捕获和处理,并统一异常返回的信息,直接通过response响应返回到前端
(1)创建异常过滤器

(2)注册成bean

再次访问则实现自定义的异常结构,友好展示到前端

本文详细介绍了Springboot如何处理Controller层异常,通过@RestControllerAdvice和@ExceptionHandler实现全局统一异常处理。同时,针对Filter层的异常,文章讨论了不同解决方案,包括继承BasicErrorController、使用HandlerExceptionResolver以及将异常交给Controller处理。最后,由于项目特殊性,采用了创建优先级更高的异常过滤器直接处理并返回统一异常信息。

8384

被折叠的 条评论
为什么被折叠?



