Spring Boot全局异常处理

!! 🌴 我比你先知道不合适,但我不舍得。

背景

在日常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 eHttpServletResponse responsethrows 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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!