SpringBoot实现全局异常处理方法总结

 更新时间:2022年03月04日 11:19:12   作者:springboot葵花宝典  
在项目开发中出现异常时很平常不过的事情,我们处理异常也有很多种方式。本文将详细为大家讲解SpringBoot实现全局异常处理几种方法,感兴趣的可以学习一下

在项目开发中出现异常时很平常不过的事情,我们处理异常也有很多种方式,可能如下:

public int div(int a ,int b){
        int c=0;
        try{
           c=a/b;
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return  c;
    }

如果我们这样处理异常,代码中就会出现特别多的异常处理模块,这样代码就会变得可读性非常差,而且业务模块逻辑会夹杂特别多的非业务逻辑。但是在项目开发的过程中我们应该将主要精力放在业务模块,除了必要的异常处理模块最好不要再包含其他无关紧要的代码。那么我们如何处理项目中无处不在的异常呢?这就引出了我们要介绍的全局异常处理方法,主要有两种种方式:

HandlerExceptionResolver。

@ControllerAdvice+@ExceptionHandler 今天我们主要介绍一下@ControllerAdvice+@ExceptionHandler模式处理全局异常。

全局异常处理

首先我们先介绍一下@ControllerAdvice和@ExceptionHandler

@ControllerAdvice注解: 他是一个比较特殊的@Component,用于定义全局异常处理类作用在所有的@Controller类型的接口上。

@ExceptionHandler注解: 用于声明处理异常的方法。

配置全局异常

@ControllerAdvice+@ExceptionHandler只要设计得当,就不用再在Controller使用trg-catch了!下面我们先写介绍一个Controller层全局异常处理类。

@ControllerAdvice
public class GlobalExceptionHandler {
   @ResponseBody
    @ExceptionHandler(Exception.class)
    public CommonResult exceptionHandler(HttpServletRequest request, Exception exception) throws Exception {    
        Map<String, Object> result = new HashMap<>(3);
        String message =exception.getMessage()+request.getRequestURL().toString();
        return CommonResult.failed(message);
    }
}

注:@ResponseBody的作用其实是将java对象转为json格式的数据。然后到这里为止,一个简单的全局异常处理解决方式就完成了,这只是一个简单的异常处理方式,远远不能达到完整项目中全局异常处理的方案。

全局异常处理的升级

我们项目中业务处理,可以通过自定义的异常知道哪一个模块发生异常,并且不同的业务模块也有不同的异常处理方式,这也方便我们做扩展

public class ServiceException extends RuntimeException {
    private IErrorCode errorCode;
    public ServiceException(IErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }
    public ServiceException(String message) {
        super(message);
    }
    public ServiceException(Throwable cause) {
        super(cause);
    }
    public ServiceException(String message, Throwable cause) {
        super(message, cause);
    }
    public IErrorCode getErrorCode() {
        return errorCode;
    }
}

加入自定义异常处理

@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理所有Service层异常
     */
    @ResponseBody
    @ExceptionHandler(value = ServiceException.class)
    public CommonResult handle(ServiceException e) {
        if (e.getErrorCode() != null) {
            return CommonResult.failed(e.getErrorCode());
        }
        return CommonResult.failed(e.getMessage());
    }
    /**
     * 处理所有不可知的异常
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public CommonResult exceptionHandler(HttpServletRequest request, Exception exception) throws Exception {
     
        Map<String, Object> result = new HashMap<>(3);
        String message =exception.getMessage()+request.getRequestURL().toString();
        return CommonResult.failed(message);
    }
 
}

处理 Controller 数据绑定、数据校验的异常

在用户登录Model字段上注解数据校验规则。

@Data
@EqualsAndHashCode(callSuper = false)
public class UserLoginParam {
    @NotEmpty
    private String username;
    @NotEmpty
    private String password;
}

SpringBoot中可以使用@Validated + @RequestBody注解方式实现数据绑定和数据校验。例如登录方式为:

@ApiOperation(value = "登录以后返回token")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult login(@Validated @RequestBody UmsAdminLoginParam umsAdminLoginParam) {
        String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword());
        if (token == null) {
            return CommonResult.validateFailed("用户名或密码错误");
        }
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);
        return CommonResult.success(tokenMap);
    }

如果数据校验不对数据抛出的异常为MethodArgumentNotValidException,所以我们可以在全局异常处理类中添加对MethodArgumentNotValidException异常的处理声明,就可以实现全局处理数据校验和绑定的异常了,实现如下:

@ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public CommonResult handleValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField()+fieldError.getDefaultMessage();
            }
        }
        return CommonResult.validateFailed(message);
    }

通过上面介绍的未知异常、数据校验和自定义全局异常所有的Controller层的异常处理方式全部都集中到了GlobalExceptionHandler类中,那么我们在Controller类中就不再需要收到记录错误了。

GlobalExceptionHandler全部代码

@ControllerAdvice
public class GlobalExceptionHandler {
    @ResponseBody
    @ExceptionHandler(value = ApiException.class)
    public CommonResult handle(ApiException e) {
        if (e.getErrorCode() != null) {
            return CommonResult.failed(e.getErrorCode());
        }
        return CommonResult.failed(e.getMessage());
    }
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public CommonResult exceptionHandler(HttpServletRequest request, Exception exception) throws Exception {
        Map<String, Object> result = new HashMap<>(3);
        String message =exception.getMessage()+request.getRequestURL().toString();
        return CommonResult.failed(message);
       // return result;
    }
    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public CommonResult handleValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getField()+fieldError.getDefaultMessage();
            }
        }
        return CommonResult.validateFailed(message);
    }
}

总结

今天主要讲解了@ControllerAdvice+@ExceptionHandler进行统一的在Controller层上的全局异常处理。

到此这篇关于SpringBoot实现全局异常处理方法总结的文章就介绍到这了,更多相关SpringBoot全局异常处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java定长队列的实现示例

    java定长队列的实现示例

    定长队列是一种有限容量的队列,对于某些应用场景非常有用,本文主要介绍了java定长队列的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Spring Boot的Profile配置详解

    Spring Boot的Profile配置详解

    本篇文章主要介绍了Spring Boot的Profile配置详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • rabbitmq basicReject/basicNack/basicRecover的区别及说明

    rabbitmq basicReject/basicNack/basicRecover的区别及说明

    这篇文章主要介绍了rabbitmq basicReject/basicNack/basicRecover的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Spring Data JPA例子代码[基于Spring Boot、Mysql]

    Spring Data JPA例子代码[基于Spring Boot、Mysql]

    这篇文章主要介绍了Spring Data JPA例子代码[基于Spring Boot、Mysql],小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • Java 创建动态类和查看方法列表信息的实例

    Java 创建动态类和查看方法列表信息的实例

    这篇文章主要介绍了 Java 创建动态类和查看方法列表信息的实例的相关资料,需要的朋友可以参考下
    2017-06-06
  • Spring的注解配置与XML配置之间的比较

    Spring的注解配置与XML配置之间的比较

    在很多情况下,注释配置比 XML 配置更受欢迎,注释配置有进一步流行的趋势。Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分 XML 配置的功能
    2013-09-09
  • Springboot详解RocketMQ实现广播消息流程

    Springboot详解RocketMQ实现广播消息流程

    RocketMQ作为一款纯java、分布式、队列模型的开源消息中间件,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等,本篇我们了解如何实现广播消息
    2022-06-06
  • SpringBoot整合Spring Boot Admin实现服务监控的方法

    SpringBoot整合Spring Boot Admin实现服务监控的方法

    这篇文章主要介绍了SpringBoot整合Spring Boot Admin实现服务监控,内容包括Server端服务开发,Client端服务开发其中Spring Boot Admin还可以对其监控的服务提供告警功能,如服务宕机时,可以及时以邮件方式通知运维人员,感兴趣的朋友跟随小编一起看看吧
    2022-03-03
  • Java在Excel中创建多级分组、折叠或展开分组的实现

    Java在Excel中创建多级分组、折叠或展开分组的实现

    这篇文章主要介绍了Java在Excel中创建多级分组、折叠或展开分组的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Java中ConcurrentHashMap和Hashtable的区别

    Java中ConcurrentHashMap和Hashtable的区别

    ConcurrentHashMap 和 Hashtable 都是用于在Java中实现线程安全的哈希表数据结构的类,但它们有很多区别,本文就来详细的介绍一下,感兴趣的可以了解一下
    2023-10-10

最新评论