!! 🌴 我比你先知道不合适,但我不舍得。
背景
在日常Web
开发过程中,我们常常会在控制层处理业务逻辑的时候,会这么处理异常:
@Operation(summary = "批量新增用户")
@PostMapping("/insertMultiUser")
@Transactional(rollbackFor = Exception.class,timeout = 30000)
public ResponseResult<?> insertMultiUser(@RequestBody List<User> users, HttpServletResponse response){
try{
Assert.isTrue(!users.isEmpty(), "至少传入一个用户");
return ResponseResult.success(userService.insertMultiUser(users));
}catch(Exception e){
response.reset();
response.setContentType("application/json;charset=utf-8");
JSONObject object = new JSONObject();
object.putOnce("message", e.getMessage());
object.putOnce("code", HttpStatus.HTTP_INTERNAL_ERROR);
object.putOnce("success", false);
response.getWriter().write(JSONUtil.toJsonStr(object));
}
}
当然也不是说不能运行,只是如果每个接口都这么写,将有这么一串代码会产生大量冗余:
response.reset();
response.setContentType("application/json;charset=utf-8");
JSONObject object = new JSONObject();
object.putOnce("message", e.getMessage());
object.putOnce("code", HttpStatus.HTTP_INTERNAL_ERROR);
object.putOnce("success", false);
response.getWriter().write(JSONUtil.toJsonStr(object));
那么我们试想一下,我们怎么处理呢?
改造
在上述的改进需求中,我们不由地会想到以下几种思路:
-
利用AOP切面去全局捕获运行的异常,并抛出; -
拦截返回响应 HttpServletResponse
,重写封装类;
第二种思路实现起来会比较麻烦,这里就不罗列了。
第一种思路,我们虽然说可以借助Spring原生AOP
,但我习惯使用AspectJ
去实现:
@Aspect
@Component
public class CommonAspect {
@Pointcut("execution(* xx.xx.xxx.xx.*.controller..*.*(..))")
public void dictPoint() {
}
@Around("dictPoint()")
public Object dictAroundAdvice(ProceedingJoinPoint point) throws Throwable {
try{
Object proceed = point.proceed();
}catch(Exception e){
throw new Exception("xxxxxx");
}
}
}
既然都已经借助切面去实现了,那么能不能在这个基础上继续改进呢?
终章
上面提到利用AOP去实现全局异常捕获,那么可以利用自定义注解的方式去改进,于是我们发现在Spring Boot当中,就存在这个注解:
-
@ControllerAdvice -
@ExceptionHandler(Exception.class)
@ControllerAdvice介绍
@ControllerAdvice
是Spring框架提供的一个注解,用于定义全局的异常处理、数据绑定和数据预处理。它可以被用于任何带有@Controller
注解的类中,作为一个全局的异常处理器。
使用@ControllerAdvice
注解的类可以包含多个通用的异常处理方法,这些方法可以处理不同的异常类型。当系统中发生异常时,@ControllerAdvice
注解的类会根据异常类型选择合适的方法进行处理。
除了异常处理外,@ControllerAdvice
还可以用于全局数据绑定和数据预处理。通过在@ControllerAdvice
注解的类中定义@ModelAttribute
和@InitBinder
注解的方法,可以实现全局的数据绑定和数据预处理。
总之,@ControllerAdvice
注解提供了一种集中管理异常处理、数据绑定和数据预处理的方式,可以减少代码的重复性,并提高系统的可维护性。
@ExceptionHandler介绍
@ExceptionHandler
是一个注解,用于在Spring MVC中处理异常。当控制器方法抛出异常时,@ExceptionHandler
注解可以用来捕获并处理该异常。通过在控制器类中定义一个或多个带有@ExceptionHandler
注解的方法,可以为特定类型的异常提供自定义的处理逻辑。
使用@ExceptionHandler
注解时,需要指定要处理的异常类型作为注解的参数。当控制器方法抛出指定类型的异常时,Spring MVC会自动调用相应的@ExceptionHandler
方法来处理该异常。在@ExceptionHandler
方法中,可以编写自定义的异常处理逻辑,例如返回特定的错误信息或页面。
以下是一个使用@ExceptionHandler
注解的示例:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("error");
modelAndView.addObject("errorMessage", "An error occurred: " + ex.getMessage());
return modelAndView;
}
}
在上述示例中,GlobalExceptionHandler
类使用@ControllerAdvice
注解标记为全局异常处理器。handleException
方法使用@ExceptionHandler(Exception.class)
注解来处理所有类型的异常。当控制器方法抛出异常时,Spring MVC会调用handleException
方法,并将异常对象作为参数传递给该方法。在handleException
方法中,可以根据需要进行异常处理,并返回一个ModelAndView
对象,用于渲染错误页面。
请注意,上述示例中的error
是一个视图名称,可以根据实际情况进行修改。另外,errorMessage
是一个模型属性,用于在错误页面中显示错误信息。
使用案例
最后,我们展示一个具体的案例代码,以供参考:
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CustomExceptionHandler{
@ExceptionHandler(Exception.class)
public void handleException(Exception e, HttpServletResponse response) throws Exception{
response.reset();
response.setContentType("application/json;charset=utf-8");
JSONObject object = new JSONObject();
object.putOnce("message", e.getMessage());
object.putOnce("code", HttpStatus.HTTP_INTERNAL_ERROR);
object.putOnce("success", false);
response.getWriter().write(JSONUtil.toJsonStr(object));
}
}
注:⚠️ HttpStatus
类隶属于hutool
工具包
原文始发于微信公众号(青衫大叔灬):Spring Boot全局异常处理
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/179750.html