• springBoot 全局异常方式处理自定义异常 @RestControllerAdvice + @ExceptionHandler


    前言

         本文讲解使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,可以处理大部分开发中用到的自自定义业务异常处理了,再也不用在 Controller 层进行 try-catch 了
         代码示例地址(代码里面类名稍微有些不同): https://gitee.com/coderLOL/springboot-demos

    一、处理思路

    1. 思路:在sevice业务逻辑层 try{}catch(){} 捕获抛出,经由contorller 层抛到 自定义全局处理类 中处理自定义异常及系统异常。

         2、实现方式:使用 @RestControllerAdvice + @ExceptionHandler 注解方式实现全局异常处

    二、实现过程

     1、@ControllerAdvice 注解定义全局异常处理类 ,@ExceptionHandler 注解声明异常处        理方法。

         ( 本类方法中用到的 ResponseResultUtil 工具类, ResponseCodeEnum 枚举类,下面步骤中会介绍)

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    /**
     * @author 路飞
     * @date 2018-8-21
     * @description 全局异常处理: 使用 @RestControllerAdvice + @ExceptionHandler 注解方式实现全    
     * 局异常处理
     */
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        private final Logger logger = LogManager.getLogger(GlobalExceptionHandler.class);
    
        /**
         * @author 路飞
         * @date 2018-8-22
         * @param e     异常
         * @description 处理所有不可知的异常
         */
        @ExceptionHandler({Exception.class})    //申明捕获那个异常类
        public ResponseResultVO globalExceptionHandler(Exception e) {
            this.logger.error(e.getMessage(), e);
            return new ResponseResultUtil().error(ResponseCodeEnum.OPERATE_FAIL);
        }
    
         /**
         * @author 路飞
         * @date 2018-8-21
         * @param e 异常
         * @description 处理所有业务异常
         */
        @ExceptionHandler({BaseBusinessException.class})
        public ResponseResultVO BusinessExceptionHandler(BaseBusinessException e) {
            this.logger.error(e);
            return new ResponseResultUtil().error(e.getCode(), e.getMessage());
        }
    
    }

    2、定义一个用于返回页面结果信息的VO对象类:ResponseResultVO

    /**
     * @author 路飞
     * @date 2018-8-21
     * @description 请求响应对象
     */
    public final class ResponseResultVO<T> {
        /**
         * @description 响应码
         */
        private int code;
    
        /**
         * @description 响应消息
         */
        private String message;
    
        /**
         * @description 分页对象 (如果用不到,这个可以不写)
         */
        private PageVO page;
    
        /**
         * @description 数据
         */
        private Object data;
    
        public final int getCode() {
            return this.code;
        }
    
        public final void setCode(int code) {
            this.code = code;
        }
    
        public final String getMessage() {
            return this.message;
        }
    
        public final void setMessage( String message) {
            this.message = message;
        }
    
        public final PageVO getPage() {
            return this.page;
        }
    
        public final void setPage( PageVO page) {
            this.page = page;
        }
    
        public final Object getData() {
            return this.data;
        }
    
        public final void setData(Object data) {
            this.data = data;
        }
    
        public ResponseResultVO(int code, String message, PageVO page, Object data) {
            super();
            this.code = code;
            this.message = message;
            this.page = page;
            this.data = data;
        }
    
    }

    3、 定义一个对步骤2中 返回信息结果处理的工具类:ResponseResultUtil

    /**
     * @author zhangwenlong
     * @date 2018-8-20
     * @description 请求响应工具类
     */
    public final class ResponseResultUtil {
    
        /**
         * @param code      响应码
         * @param message   相应信息
         * @param any       返回的数据
         * @description     请求成功返回对象
         */
        public final ResponseResultVO success(int code, String message, PageVO page, Object any) {
            return new ResponseResultVO(code, message, page, any);
        }
    
        /**
         * @param any   返回的数据
         * @description 请求成功返回对象
         */
        public final ResponseResultVO success(Object any) {
            int code = ResponseCodeEnum.SUCCESS.getCode();
            String message = ResponseCodeEnum.SUCCESS.getMessage();
            return this.success(code, message, null, any);
        }
    
        /**
         * @param any   返回的数据
         * @description 请求成功返回对象
         */
        public final ResponseResultVO success(Object any, PageVO page) {
            int code = ResponseCodeEnum.SUCCESS.getCode();
            String message = ResponseCodeEnum.SUCCESS.getMessage();
            return this.success(code, message, page, any);
        }
    
        /**
         * @description 请求成功返回对象
         */
        public final ResponseResultVO success() {
            return this.success(null);
        }
    
        /**
         * @param responseCode  返回的响应码所对应的枚举类
         * @description         请求失败返回对象
         */
        public final ResponseResultVO error(ResponseCodeEnum responseCode) {
            return new ResponseResultVO(responseCode.getCode(), responseCode.getMessage(), null, null);
        }
    
        /**
         * @param code      响应码
         * @param message   相应信息
         * @description     请求失败返回对象
         */
        public final ResponseResultVO error(int code, String message) {
            return new ResponseResultVO(code, message, null, null);
        }
    }

    4、为方便统一管理异常代码和信息之间的关系,建立枚举类: ResponseCodeEnum

    /**
     * @author 路飞
     * @date 2018-8-20
     * @description     响应码配置枚举
     */
    public enum ResponseCodeEnum {
        // 系统通用
        SUCCESS(200, "操作成功"),
    
        UNLOGIN_ERROR(233, "没有登录"),
    
        OPERATE_FAIL(666, "操作失败"),
    
        // 用户
        SAVE_USER_INFO_FAILED(2001, "保存用户信息失败"),
    
        GET_USER_INFO_FAILED(2002, "保存用户信息失败"),
    
        WECHAT_VALID_FAILED(2003, "微信验证失败"),
    
        GET_USER_AUTH_INFO_FAILED(2004, "根据条件获取用户授权信息失败"),
    
        SAVE_USER_AUTH_INFO_FAILED(2005, "保存用户授权失败");
    
        private Integer code;
        private String message;
    
        ResponseCodeEnum(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    
        public final Integer getCode() {
            return this.code;
        }
    
        public final String getMessage() {
            return this.message;
        }
    
    }

    5、 

    (1)封装一个基础业务异常类(让所有自定义业务异常类 继承此 基础类):BaseBusinessException

    /**
     * @author zhangwenlong
     * @date 2018-8-21
     * @description 价值分析系统所有的 业务异常父类
     */
    public class BaseBusinessException extends RuntimeException {
    
        private Integer code;
    
        // 给子类用的方法
        public BaseBusinessException(ResponseCodeEnum responseCodeEnum) {
            this(responseCodeEnum.getMessage(), responseCodeEnum.getCode());
        }
    
        private BaseBusinessException(String message, Integer code) {
            super(message);
            this.code = code;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    }

    (2)自定义的业务异常类 (例如):

                  自定义用户异常

    /**
     * @author 路费
     * @date 2018-8-21
     * @description  自定义用户异常
     */
    public class UserException extends BaseBusinessException { // 继承继承 业务异常类
        public UserException(ResponseCodeEnum responseCodeEnum) {
            super(responseCodeEnum);
        }
    }

    6、service 层抛出

    /**
     * @author 路飞
     * @date 2018-8-21
     * @description     用户信息业务接口实现类
     */
    @Service("userInfoService")
    public class UserInfoSerimpl implements UserInfoService {
    
        private Logger logger = LoggerFactory.getLogger(UserInfoSerimpl.class);
    
        @Resource
        private UserInfoMapper userInfoMapper; // maybatis通用Mapper插件 
    
    
        /**
         * @author 路飞
         * @date 2018-8-21
         * @param userInfo          用户信息
         * @description             保存用户信息
         */
        @Override
        public void saveUserInfo(UserInfo userInfo) {
            try {
                userInfoMapper.insertSelective(userInfo);
            } catch (Exception e) {
                logger.error("获取用户信息失败", e);
                //抛出自定义异常: ResponseCodeEnum.SAVE_USER_INFO_FAILED 
                throw new UserException(ResponseCodeEnum.SAVE_USER_INFO_FAILED); 
            }
        }
    
    }
  • 相关阅读:
    连接ESP32失败:等待包头 #226超时
    题王网
    高可用架构模式——CAP
    高性能负载均衡
    单服务器高性能模式
    虚拟支付
    高性能架构设计——数据库篇
    MySQL
    shell 命令: MD5
    HTTPS
  • 原文地址:https://www.cnblogs.com/jtlgb/p/10661688.html
Copyright © 2020-2023  润新知