目录

注解的介绍

@ControllerAdvice

@ExceptionHandler拦截异常并统一处理

代码实现

自定义异常

统一异常处理

前端返回值类

测试用例

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏哦。


注解的介绍

@ControllerAdvice

@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。

这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:

1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。

2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。

3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。

从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。

针对声明@ExceptionHandler 、 @InitBinder或@ModelAttribute方法的类的@Component @ExceptionHandler , @InitBinder在多个@Controller类之间共享。

使用@ControllerAdvice注解的类可以明确声明为 Spring bean 或通过类路径扫描自动检测。 所有此类 bean 都根据Ordered语义或@Order / @Priority声明进行Ordered , Ordered语义优先于@Order / @Priority声明。 然后在运行时按该顺序应用@ControllerAdvice bean。 但是请注意,实现PriorityOrdered @ControllerAdvice bean 的PriorityOrdered不高于实现Ordered @ControllerAdvice bean。 此外, Ordered不适用于范围内的@ControllerAdvice例如,如果这样的 bean 已被配置为请求范围或会话范围的 bean。 对于处理异常, @ExceptionHandler将在第一个具有匹配异常处理程序方法的通知中被选择。 对于模型的属性和数据绑定初始化, @ModelAttribute和@InitBinder方法将遵循@ControllerAdvice秩序。

注意:对于@ExceptionHandler方法,在特定建议 bean 的处理程序方法中,根异常匹配将优先于仅匹配当前异常的原因。 但是,与较低优先级建议 bean 上的任何匹配(无论是根还是原因级别)相比,更高优先级建议上的原因匹配仍然是首选。 因此,请在具有相应顺序的优先建议 bean 上声明您的主要根异常映射。

默认情况下, @ControllerAdvice ControllerAdvice 中的方法全局应用于所有控制器。 使用诸如annotations 、 basePackageClasses和basePackages (或其别名value )之类的选择器来定义目标控制器的更窄子集。 如果声明了多个选择器,则应用布尔OR逻辑,这意味着所选控制器应至少匹配一个选择器。 请注意,选择器检查是在运行时执行的,因此添加许多选择器可能会对性能产生负面影响并增加复杂性。

@ExceptionHandler拦截异常并统一处理

配合 @ExceptionHandler注解结合使用,当异常抛到controller层时,可以对异常进行统一的处理,规定返回的json格式或者跳转到指定的错误页面等.

@ExceptionHandler的作用主要在于声明一个或多个类型的异常,当符合条件的Controller抛出这些异常之后将会对这些异常进行捕获,然后按照其标注的方法的逻辑进行处理,从而改变返回的视图信息。

用于处理特定处理程序类和/或处理程序方法中的异常的注解。

使用此注解注释的处理程序方法允许具有非常灵活的签名。 它们可能具有以下类型的参数,按任意顺序排列:

异常参数:声明为一般异常或更具体的异常。 如果注解本身没有通过其value()缩小异常类型,这也可用作映射提示

代码实现

自定义异常

/*** 自定义一个异常类,用于处理我们发生的业务异常** @author Promsing(张有博)* @version 1.0.0* @since 2021/11/27 - 20:14*/
public class BizException extends RuntimeException {private static final long serialVersionUID = 1L;/*** 错误码*/protected String errorCode;/*** 错误信息*/protected String errorMsg;public BizException() {super();}public BizException(FrontResult errorInfoInterface) {super(errorInfoInterface.getCode());this.errorCode = errorInfoInterface.getMessage();this.errorMsg = errorInfoInterface.getMessage();}public BizException(FrontResult errorInfoInterface, Throwable cause) {super(errorInfoInterface.getCode(), cause);this.errorCode = errorInfoInterface.getCode();this.errorMsg = errorInfoInterface.getMessage();}public BizException(String errorMsg) {super(errorMsg);this.errorMsg = errorMsg;}public BizException(String errorCode, String errorMsg) {super(errorCode);this.errorCode = errorCode;this.errorMsg = errorMsg;}public BizException(String errorCode, String errorMsg, Throwable cause) {super(errorCode, cause);this.errorCode = errorCode;this.errorMsg = errorMsg;}public String getErrorCode() {return errorCode;}public void setErrorCode(String errorCode) {this.errorCode = errorCode;}public String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}public String getMessage() {return errorMsg;}@Overridepublic Throwable fillInStackTrace() {return this;}}

统一异常处理


import com.tfjy.arbackend.enumtool.ResultCodeEnum;
import com.tfjy.arbackend.enumtool.ResutlMsgEnum;
import com.tfjy.arbackend.util.FrontResult;
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;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.SQLException;/*** 统一异常处理** @author Promsing(张有博)* @version 1.0.0* @since 2021/11/27 - 20:14*/
@ControllerAdvice//使用该注解表示开启了全局异常的捕获
public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);/*** 处理自定义的业务异常* @param req* @param e* @return*/@ExceptionHandler(value = BizException.class)@ResponseBodypublic  FrontResult bizExceptionHandler(HttpServletRequest req, BizException e){logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("发生业务异常!原因是:{}",e.getErrorMsg());return FrontResult.getExceptionResult(e.getErrorCode(),e.getErrorMsg());}/*** 处理空指针的异常* @param req* @param e* @return*/@ExceptionHandler(value =NullPointerException.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, NullPointerException e)  {logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("发生空指针异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}/*** 处理索引越界异常* @param req* @param e* @return*/@ExceptionHandler(value =IndexOutOfBoundsException.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, IndexOutOfBoundsException e){logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("索引越界异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}/*** 处理类未找到异常* @param req* @param e* @return*/@ExceptionHandler(value =ClassNotFoundException.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, ClassNotFoundException e)  {logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("发生类未找到异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}/*** 处理SQL异常* @param req* @param e* @return*/@ExceptionHandler(value = SQLException.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, SQLException e)  {logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("发生SQL异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}/*** 处理IO异常* @param req* @param e* @return*/@ExceptionHandler(value = IOException.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, IOException e)  {logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("发生IO异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}/*** 处理其他异常* @param req* @param e* @return*/@ExceptionHandler(value =Exception.class)@ResponseBodypublic FrontResult exceptionHandler(HttpServletRequest req, Exception e){logger.error("URL : " + req.getRequestURL().toString());logger.error("HTTP_METHOD : " + req.getMethod());logger.error("未知异常!原因是:",e);return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResutlMsgEnum.EXECUTE_FAIL.getMsg());}}

前端返回值类

import com.tfjy.arbackend.enumtool.ResultCodeEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class FrontResult {/*** 结果状态码*/private String code;/*** 响应结果描述*/private String message;/*** 返回数据*/private Object data;/*** 静态方法,返回前端实体结果** @param code    状态码* @param message 消息* @param data    数据* @return 前端实体结果*/public static FrontResult build(String code, String message, Object data) {return new FrontResult(code, message, data);}/*** 返回成功的结果实体** @param message 消息* @param data    数据* @return 实体*/public static FrontResult getSuccessResult(String message, Object data) {FrontResult result = new FrontResult();result.code = ResultCodeEnum.SUCCESS.getCode();result.message = message;result.data = data;return result;}/*** 返回无需data的成功结果实体** @param message 消息内容* @return 返回结果*/public static FrontResult getSuccessResultOnlyMessage(String message) {FrontResult result = new FrontResult();result.code = ResultCodeEnum.SUCCESS.getCode();result.message = message;result.data = null;return result;}/*** 获取一个异常结果** @param code 错误码* @param message 自定义异常信息* @return FrontResult*/public static FrontResult getExceptionResult(String code, String message) {FrontResult result = new FrontResult();result.code = code.isEmpty() ? ResultCodeEnum.CODE_EXCEPTION.getCode() : code;result.message = message.isEmpty() ? ResultCodeEnum.CODE_EXCEPTION.getMsg() : message;return result;}
}
import lombok.AllArgsConstructor;@AllArgsConstructor
public enum ResultCodeEnum {// 请求成功SUCCESS("0000"),// 请求失败FAIL("1111"),// EXCEL 导入失败EXCEL_FAIL("1000"),// userID 为空ID_NULL("1001"),// 前端传的实体为空MODEL_NULL("1002"),// 更新失败UPDATE_FAIL("1011"),// 参数为空PARAM_ERROR("400"),// 代码内部异常CODE_EXCEPTION("500", "代码内部异常");/*** 状态码*/private String code;public String getCode() {return code;}ResultCodeEnum(String code) {this.code = code;}private String msg;public String getMsg() {return msg;}}public enum ResutlMsgEnum {//查询成功FIND_SUCCESS("查询成功!"),//查询失败FIND_FAIL("查询失败!"),//更新成功UPDATE_SUCCESS("更新成功"),//更新失败UPDATE_FAIL("更新成功"),SEND_SUCCESS("发送成功"),SEND_FAIL("发送失败");private String msg;ResutlMsgEnum(String msg) {this.msg = msg;}public String getMsg() {return msg;}
}

测试用例

/*** 测试用例** @author Promsing(张有博)* @version 1.0.0* @since 2021/11/29 - 9:05*/
@Api(tags = {"测试controller"})
@RequestMapping(value = "/testController")
@RestController
public class TestController {@ApiOperation(value = "测试null")@GetMapping(value = "getNull")public FrontResult getNull() {int length = 0;String name=null;length = name.length();return FrontResult.build(ResultCodeEnum.SUCCESS.getCode(),ResutlMsgEnum.EXECUTE_SUCCESS.getMsg(), length);}
}

其他异常同理,也可以捕获。完美,没问题。全局统一异常处理设置成功。

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏哦。

Spring Boot 统一处理全局异常相关推荐

  1. spring boot 四:全局异常捕捉

    spring boot 四:全局异常捕捉 1 前言 希望定制错误,比如一般springboot的500错误展示如下(trace等可以通过配置application.yml来决定隐藏还是具有): app ...

  2. Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json

    需求 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0,   "data": {},   "msg" ...

  3. Spring Boot 工程集成全局唯一ID生成器 Vesta

    2019独角兽企业重金招聘Python工程师标准>>> 本文内容脑图如下: 文章共 760字,阅读大约需要 2分钟 ! 概 述 在前一篇文章 <Spring Boot工程集成全 ...

  4. springboot怎么返回404_Spring Boot2 系列教程(十三)Spring Boot 中的全局异常处理

    在 Spring Boot 项目中 ,异常统一处理,可以使用 Spring 中 @ControllerAdvice 来统一处理,也可以自己来定义异常处理方案.Spring Boot 中,对异常的处理有 ...

  5. Spring Boot 统一功能处理

    Spring Boot 统一功能处理 一.使用 Spring 拦截器来实现登录验证 引入 代码实现 步骤1 自定义拦截器 步骤2 添加拦截器并设置拦截规则 拦截规则 步骤3 创建前后端交互,用于测试 ...

  6. Spring Boot 统一功能处理(用户登录权限效验-拦截器、异常处理、数据格式返回)

    文章目录 1. 统一用户登录权限效验 1.1 最初用户登录权限效验 1.2 Spring AOP 统一用户登录验证 1.3 Spring 拦截器 1.4 练习:登录拦截器 1.5 拦截器实现原理 1. ...

  7. Spring Boot统一异常处理实践

    Spring Boot统一异常处理实践 参考文章: (1)Spring Boot统一异常处理实践 (2)https://www.cnblogs.com/fundebug/p/springboot-ex ...

  8. Spring Boot统一异常处理的拦截指南

    通常我们在Spring Boot中设置的统一异常处理只能处理Controller抛出的异常.有些请求还没到Controller就出异常了,而这些异常不能被统一异常捕获,例如Servlet容器的某些异常 ...

  9. spring boot 搭建 和 全局异常处理

    spring boot 搭建: java -jar -Dserver.port=10000 -Dlogging.path=/var/logs xxx.jar &   -- 默认在/var/lo ...

最新文章

  1. SpringBoot培训教程--史前文明之Spring简介
  2. 面试官:说说什么是Java内存模型?
  3. 服务器装系统无显示屏,服务器系统安装后没有桌面
  4. android XMl 解析神奇xstream 六: 把集合list 转化为 XML文档
  5. 纪录备忘:应用中的脚本应用
  6. 【CSAPP笔记】4. 汇编语言——基础知识
  7. Leetcode 538.二叉树转换为累加树
  8. CSND博客几年没有登录了,终于找回密码来报个到!
  9. GPS精密星历文件下载地址
  10. 2018农行--软开
  11. 《程序员修炼之道--从小工到专家》读书笔记
  12. dnf一天能获得多少黑暗之眼_DNF:想快速积累史诗狗眼?这几个方法可别错过,一天最少四五个...
  13. windows切换桌面的快捷键
  14. 1096 大美数 分数 15
  15. Redis基础——数据类型详解
  16. 643 · 最长绝对文件路径
  17. 什么输入法对计算机英语,电脑怎么把英文输入法设置为默认输入法
  18. pdf大小如何压缩?
  19. pod update --verbose --no-repo-update 和 pod install --verbose --no-repo-update的区别
  20. 对动量守恒定律的质疑

热门文章

  1. EasyExcel快捷导出
  2. Java 计算两个日期相减并转换成月份
  3. 【初等数论】【转载】夜深人静写算法(五) - 初等数论
  4. 关于WIN10装CH340驱动的一些小小的注意事项
  5. 数据结构——图书信息管理系统的顺序表实现
  6. java界面绘制地铁路线_基于 HTML5 Canvas 的交互式地铁线路图
  7. 【力扣周赛】第340场周赛
  8. 记微服务架构实战学习笔记
  9. ZIP压缩包设置了密码怎么办?
  10. 日本最省女孩15年买下3套房的启示