通过 @ControllerAdvice 注解,我们可以在一个地方对所有 @Controller 注解的控制器进行管理。
注解了 @ControllerAdvice 的类的方法可以使用 @ExceptionHandler@InitBinder@ModelAttribute 注解到方法上,这对所有注解了 @RequestMapping 的控制器内的方法都有效。

  1. @ExceptionHandler:用于捕获所有控制器里面的异常,并进行处理。
  2. @InitBinder:用来设置 WebDataBinderWebDataBinder 用来自动绑定前台请求参数到 Model 中。
  3. @ModelAttribute@ModelAttribute 本来的作用是绑定键值对到 Model 里,此处是让全局的@RequestMapping 都能获得在此处设置的键值对。

本文使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理。只要设计得当,就再也不用在 Controller 层进行 try-catch 了!

一、经典案例

需求:希望通过全局统一的异常处理将自定义错误码以json的形式发送给前端。

1、统一返回结果类 ApiResult

首先,定义一个统一结果返回类,最终需要将这个结果类的内容返回给前端。

package com.tao.smp.exception;/*** Api统一的返回结果类*/
public class ApiResult {/*** 结果码*/private String code;/*** 结果码描述*/private String msg;public ApiResult() {}public ApiResult(ResultCode resultCode) {this.code = resultCode.getCode();this.msg = resultCode.getMsg();}/*** 生成一个ApiResult对象, 并返回** @param resultCode* @return*/public static ApiResult of(ResultCode resultCode) {return new ApiResult(resultCode);}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}@Overridepublic String toString() {return "ApiResult{" +"code='" + code + '\'' +", msg='" + msg + '\'' +'}';}
}

2、错误码枚举类 ResultCode

有了 ApiResult ,接下来需要定义一个枚举类, 来包含所有自定义的结果码。

package com.tao.smp.exception;/*** 错误码*/
public enum ResultCode {/*** 成功*/SUCCESS("0", "success"),/*** 未知错误*/UNKNOWN_ERROR("0x10001", "unkonwn error"),/*** 用户名错误或不存在*/USERNAME_ERROR("0x10002", "username error or does not exist"),/*** 密码错误*/PASSWORD_ERROR("0x10003", "password error"),/*** 用户名不能为空*/USERNAME_EMPTY("0x10004", "username can not be empty");/*** 结果码*/private String code;/*** 结果码描述*/private String msg;ResultCode(String code, String msg) {this.code = code;this.msg = msg;}public String getCode() {return code;}public String getMsg() {return msg;}
}

3、自定义业务异常类 BusinessRuntimeException

接下来需要定义我们自己的业务异常类,以后和业务相关的异常通通抛出这个异常类,我们将错误码枚举变量的值存于其中。

package com.tao.smp.exception;/*** 自定义业务异常*/
public class BusinessRuntimeException extends RuntimeException {/*** 结果码*/private String code;/*** 结果码描述*/private String msg;/*** 结果码枚举*/private ResultCode resultCode;public BusinessRuntimeException(ResultCode resultCode) {super(resultCode.getMsg());this.code = resultCode.getCode();this.msg = resultCode.getMsg();this.resultCode = resultCode;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public ResultCode getResultCode() {return resultCode;}public void setResultCode(ResultCode resultCode) {this.resultCode = resultCode;}
}

4、全局异常处理类 GlobalExceptionResolver

最后便是定义全局异常处理类。

  1. 通过 @ControllerAdvice 指定该类为 Controller 增强类。
  2. 通过 @ExceptionHandler 自定捕获的异常类型。
  3. 通过 @ResponseBody 返回 json 到前端。

注意一点:被@ControllerAdvice注解的全局异常处理类也是一个 Controller ,我们需要配置扫描路径,确保能够扫描到这个Controller。

package com.tao.smp.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** 全局Controller层异常处理类*/
@ControllerAdvice
public class GlobalExceptionResolver {private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionResolver.class);/*** 处理所有不可知异常** @param e 异常* @return json结果*/@ExceptionHandler(Exception.class)@ResponseBodypublic ApiResult handleException(Exception e) {// 打印异常堆栈信息LOG.error(e.getMessage(), e);return ApiResult.of(ResultCode.UNKNOWN_ERROR);}/*** 处理所有业务异常** @param e 业务异常* @return json结果*/@ExceptionHandler(BusinessRuntimeException.class)@ResponseBodypublic ApiResult handleOpdRuntimeException(BusinessRuntimeException e) {// 不打印异常堆栈信息LOG.error(e.getMsg());return ApiResult.of(e.getResultCode());}
}

二、测试

1、测试 TestController

package com.tao.smp.controller;import com.tao.smp.exception.BusinessRuntimeException;
import com.tao.smp.exception.ResultCode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;/*** 测试异常的抛出*/
@Controller
@RequestMapping("/")
public class TestController {/*** 测试返回异常信息* @return*/@GetMapping("/exception")public String returnExceptionInfo() {if (1 != 2) {// 用户民错误或不存在异常throw new BusinessRuntimeException(ResultCode.USERNAME_ERROR);}return "success";}
}

SpringMVC实现全局异常处理器相关推荐

  1. SpringMVC构建全局异常处理器

    异常处理器 SpringMVC提供全局异常处理器进行统一的异常处理,一个系统只能有一个异常处理器. 系统的dao.service.controller层出现异常的时候都throws Exception ...

  2. (转)SpringMVC学习(八)——SpringMVC中的异常处理器

    http://blog.csdn.net/yerenyuan_pku/article/details/72511891 SpringMVC在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常 ...

  3. SpringMVC使用HandlerExceptionResolver实现全局异常处理器

    在SpringMVC中,提供了一个全局异常处理器,用于对系统中出现的异常进行统一处理.在一般的系统中,DAO层.Service层及Controller层出现异常都以"throws Excep ...

  4. springboot全局异常处理器

    通过aop监控程序异常,全局异常捕获 定义全局异常处理器: import java.util.HashMap; import java.util.Map; import org.springframe ...

  5. SpringBoot中定义全局异常处理器

    场景 SpringBoot中创建全局异常处理器,使发生异常时能处理. 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/356 ...

  6. spring设置全局异常处理器

    spring设置全局异常处理器 参考文章: (1)spring设置全局异常处理器 (2)https://www.cnblogs.com/gongxijun/p/5824723.html 备忘一下.

  7. SpringBoot 自定义全局异常处理器

    SpringBoot自定义全局异常处理器 一.maven依赖 二.GlobalExceptionHandler.java 三.ResponseStandard.java 四.logback.xml 五 ...

  8. springBoot配置全局异常处理器

    一.自定义自己的异常类MyException.java public class MyException extends RuntimeException {private int code;publ ...

  9. SpringBoot项目中的全局异常处理器 Failed to invoke @ExceptionHandler method

    SpringBoot项目中的全局异常处理器 Failed to invoke @ExceptionHandler method 参考文章: (1)SpringBoot项目中的全局异常处理器 Faile ...

最新文章

  1. C#操作SqlServer数据库的常用对象,及其方法
  2. 清华大学2017计算机录取分数线,2017年清华大学各省各批次录取分数线
  3. 006 技能数组分析和代码编写
  4. Job Processing 工序安排
  5. Vue3过渡动画实现
  6. [Unity] GameFramework 学习记录 4:第三人称控制器
  7. 在Hive查询中如何显示列名
  8. Css、javascript、dom(一)
  9. Android自定义Button按钮显示样式
  10. libxml主要函数说明 (二)
  11. JanusGraph部署方案
  12. WIFI中的关键词,频率,频段,频宽,频带...你晕了没??.
  13. P3369 【模板】普通平衡树
  14. LWIP网络开发从入门到精通
  15. nginx的log_format日志格式和字段介绍
  16. error C4189
  17. 163VIP邮箱哪个用的多?邮件误删恢复怎么操作?
  18. 用 PHP 来刷leetCode 之 四数之和
  19. 并发编程-并发编程的挑战
  20. 二手车电商又多了一只独角兽?

热门文章

  1. 自然语言处理中的迁移学习(上)
  2. GEE计算LST温度反演
  3. java中怎么引用圆周率_Java简单计算圆周率完整示例
  4. Python 常用模块简介
  5. 台式机和台式计算机的区别,台式机和一体机区别是什么
  6. 怎么选择触摸液晶广告机?
  7. Spark jars依赖问题
  8. 如何使用阿里云国际版控制台使用海外云服务器-Unirech
  9. 全球与中国无线门铃对讲设备市场深度研究分析报告
  10. 计算机的cup颗数、核数、线程数