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

前言

本文讲解使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,可以处理大部分开发中用到的自自定义业务异常处理了,再也不用在 Controller 层进行 try-catch 了

文章结尾附带项目代码示例下载地址

一、处理思路

  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-27
 * @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-27
 * @description  自定义用户异常
 */
public class UserException extends BaseBusinessException { // 继承继承 业务异常类
    public UserException(ResponseCodeEnum responseCodeEnum) {
        super(responseCodeEnum);
    }
}

6、service 层抛出

/**
 * @author 路飞
 * @date 2018-8-27
 * @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-27
     * @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);
        }
    }

}

后续会提供代码实例及下载地址。。。

原文地址:https://www.cnblogs.com/topfish/p/9573635.html

时间: 2024-10-22 17:52:36

全局异常方式处理自定义异常 @RestControllerAdvice + @ExceptionHandler的相关文章

Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获

https://www.cnblogs.com/goloving/p/9142222.html 一.全局异常 1.首先创建异常处理包和类 2.使用@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获 package com.example.demo.exception; import org.springframework.web.bind.annotation.ControllerAdvice; import org.spri

spring boot2.0+中添加全局异常捕获

1.添加自定义异常,继承RuntimeException,为什么继承RuntimeException呢?是因为我们的事务在RuntimeException异常下会发生回滚. 1 public class BusinessException extends RuntimeException{ 2 3 public BusinessException(String code, String msg){ 4 this.code = code; 5 this.msg = msg; 6 } 7 8 pri

SpringBoot:如何优雅地处理全局异常?

SpringBoot:如何优雅地处理全局异常? 之前用springboot的时候,只知道捕获异常使用try{}catch,一个接口一个try{}catch,这也是大多数开发人员异常处理的常用方式,虽然屡试不爽,但会造成一个问题,就是一个Controller下面,满屏幕的try{}catch,看着一点都不优雅,一点都不符合×××的气质,憋了这么久,×××今天终于决定对所有异常实施统一处理的方案. 开发准备 JDK8.正常的springboot项目 代码编写 通用异常处理 其实Spring系列的项目

Spring-MVC开发之全局异常捕获全面解读(转)

异常,异常.我们一定要捕获一切该死的异常,宁可错杀一千也不能放过一个!产品上线后的异常更要命,一定要屏蔽错误内容,以免暴露敏感信息!在用Spring MVC开发WEB应用时捕获全局异常的方法基本有两种: WEB.XML,就是指定error-code和page到指定地址,这也是最传统和常见的做法 用Spring的全局异常捕获功能,这种相对可操作性更强一些,可根据自己的需要做一后善后处理,比如日志记录等. SO,本文列出Spring-MVC做WEB开发时常用全局异常捕获的几种解决方案抛砖引玉,互相没

Spring-MVC开发之全局异常捕获全面解读

在用Spring MVC开发WEB应用时捕获全局异常的方法基本有两种, WEB.XML,就是指定error-code和page到指定地址,这也是最传统和常见的做法 用Spring的全局异常捕获功能,这种相对可操作性更强一些,可根据自己的需要做一后善后处理,比如日志记录等. SO,本文列出Spring-MVC做WEB开发时常用全局异常捕获的几种解决方案抛砖引玉 互相没有依赖,每个都可单独使用! 定义服务器错误WEB.XML整合Spring MVC web.xml <error-page> <

springBoot(5)---单元测试,全局异常

单元测试,全局异常 一.单元测试 1.基础版 1.引入相关依赖 <!--springboot程序测试依赖,如果是自动创建项目默认添加--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </depen

SpringBoot------全局异常捕获和自定义异常

1.添加Maven依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> &l

SpringBoot(6) SpringBoot配置全局异常

1.全局异常 @ControllerAdvice 如果是返回json数据 则用 RestControllerAdvice,就可以不加 @ResponseBody //捕获全局异常,处理所有不可知的异常 @ExceptionHandler(value=Exception.class) 1 @RestControllerAdvice 2 public class CustomExtHandler { 3 4 private static final Logger LOG = LoggerFactor

Eclipse搭建springboot项目(六)全局异常

知识点: 1.SpringBoot2.x服务端异常和SpringBoot配置全局异常 1).默认异常测试 int i = 1/0,不友好 2).异常注解介绍 @ControllerAdvice 如果是返回json数据 则用 RestControllerAdvice,就可以不加 @ResponseBody //捕获全局异常,处理所有不可知的异常 @ExceptionHandler(value=Exception.class) 2.SpringBoot2.x配置全局异常返回自定义异常和错误页面跳转