1、简介

用处:统一结果处理与异常拦截。

2、配置步骤

2.1、创建一个spring boot项目(idea)

完整项目结构!

2.2、导入依赖(需要使用到简化环境搭建)

<!-- SpringBoot Aop -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><!--    阿里JSON处理器 -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version>
</dependency><!--常用工具类 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions>
</dependency>

2.3、yml

注意:我们这个测试不需要yml(写上来防止你们疑惑!)

spring:application:name: springboot-day02-aop-exception    #服务名称(项目名)

2.4、需要使用的工具类

注意:直接复制使用,工具类方法太多所以直接抽取几个用到的方法(不是重点)。

1、StringUtils

/*** @author cms* @version 1.0.0.0* @Date: 2022/5/21 20:10*/
public class StringUtils extends org.apache.commons.lang3.StringUtils
{public static boolean isEmpty(String str){return isNull(str) || "".equals(str.trim());}public static boolean isNotEmpty(String str){return !isEmpty(str);}public static boolean isNull(Object object){return object == null;}public static boolean isNotNull(Object object){return !isNull(object);}}

2、ServletUtils

/*** @author cms* @version 1.0.0.0* @Date: 2022/5/21 20:10*/
public class ServletUtils
{/*** 响应字符串* @param response 响应* @param string 内容* @return 结果*/public static String parseString(HttpServletResponse response, String string){try{response.setStatus(200);response.setContentType("application/json");response.setCharacterEncoding("utf-8");response.getWriter().print(string);}catch (IOException e){e.printStackTrace();}return null;}}

2.5、需要使用的枚举以及状态

1、ErrorEnum

/*** @author cms* @version 1.0.0.0* @Date: 2022/3/16 13:17*/
public enum ErrorEnum {/* 参数错误P0100 - P0200 */P_ERROR_NULL("P0100", "参数%s不能为空"),P_NOT_EXIST("P0101", "%s不存在"),P_FORMAT_ERROR("P0102", "%s格式不正确"),/* 系统内部错误S0100 - Sxxx */S_CATCH_AUTH("S0104", "%s"),S_TOKEN_EXPIRED("S0104", "Token过期"),S_ERROR("S0105","系统异常 练习管理员!佳佳吖!"),;private String code;private String message;ErrorEnum() {}ErrorEnum(String code, String message) {this.code = code;this.message = message;}public String getCode() {return code;}public String getMessage() {return message;}/*** @param message 填充内容* @return 结果*/public String getMessage(String message) {if (StringUtils.isNotEmpty(message)) {return String.format(this.message, message);}return "";}public void setCode(String code) {this.code = code;}public void setMessage(String message) {this.message = message;}}

2、状态码常量类

/*** 返回状态码* * @author cms* @version 1.0.0.0* @Date: 2022/5/21 20:05*/
public class HttpStatus
{/*** 操作成功*/public static final int SUCCESS = 200;/*** 不允许的http方法*/public static final int BAD_METHOD = 405;/*** 系统内部错误*/public static final int ERROR = 500;}

2.6、统一结果返回格式对象

/*** 统一结果格式返回控制类** @author cms* @version 1.0.0.0* @Date: 2022/5/21 19:23*/
public class ResultReturn extends LinkedHashMap<String, Object>
{public static final Date newDateTime = new Date();public static final String CODE = "code";public static final String MSG = "message";public static final String DATE_TIME = "datetime";public static final String DATA = "data";public ResultReturn() {}public ResultReturn(Object code, String msg, Date datetime, Object data){super.put(CODE, code);super.put(MSG, msg);super.put(DATE_TIME, datetime.getTime());if (StringUtils.isNotNull(data)){super.put(DATA, data);}}/*** 成功状态码统一:200** @return 返回结果*/public static Object success(Object data){return new ResultReturn(200, "success", newDateTime, data);}public static Object success(){return ResultReturn.success(null);}/*** 错误返回** @param errorEnum 错误枚举信息* @return 返回结果*/public static Object error(ErrorEnum errorEnum){return new ResultReturn(errorEnum.getCode(), errorEnum.getMessage(), new Date(), null);}public static Object error(Object code, String errorMsg){return new ResultReturn(code, errorMsg, newDateTime, null);}public static ResultReturn error(RuanjiaExceptionHandler e){return new ResultReturn(e.getCode(), e.getMessage(), newDateTime, null);}
}

2.7、Controller统一返回结果(AOP)

1、自定义注解

作用:如果有不想被Aop拦截的controller方法,就是用该注解标识。

/*** 默认返回结果** @author cms* @version 1.0.0.0* @Date: 2022/5/21 19:17*/
@Target({ ElementType.TYPE, ElementType.METHOD }) //用于方法上
@Retention(RetentionPolicy.RUNTIME) //保留政策:运行时
@Documented
public @interface OriginalReturn
{}

2、统一结果拦截类(AOP切面类)

作用(重点):使用Aop实现统一结果拦截。

/*** 使用Aop拦截统一结果** @author cms* @version 1.0.0.0* @Date: 2022/5/21 19:15*/
@Aspect
@Slf4j
@Component
public class ResultAspectj
{@Pointcut("execution(public * com.ruanjia.controller..*.*(..))")public void result() {};/** AOP拦截所有Controller控制器结果 */@Around("result()")public Object afterReturningMethod(ProceedingJoinPoint point) throws Throwable {Object proceed = point.proceed();/* 模型和视图 -> 直接放行 */if (proceed instanceof ModelAndView || proceed instanceof View) {return proceed;}Method method = ((MethodSignature) point.getSignature()).getMethod();/* 方法上标志@OriginalReturn -> 直接放行 */if (method.isAnnotationPresent(OriginalReturn.class)) {return proceed;}return ResultReturn.success(proceed);}}

2.8、全局异常拦截

1、自定义异常类

作用:处理系统业务异常(这里还可以细写,可以根据自己需要增加自定义异常!)

/*** 自定义异常** @author cms* @version 1.0.0.0* @Date: 2022/5/21 20:02*/
@Data
public class RuanjiaExceptionHandler extends RuntimeException
{private Object code;private String message;public RuanjiaExceptionHandler(ErrorEnum errorCodeEnum){this.code = errorCodeEnum.getCode();this.message = errorCodeEnum.getMessage();}/*** @param errorCodeEnum 枚举* @param message 替换字符串*/public RuanjiaExceptionHandler(ErrorEnum errorCodeEnum, String message){super(errorCodeEnum.getMessage(message));if (StringUtils.isNotEmpty(message)) {this.message = errorCodeEnum.getMessage(message);} else {this.message = errorCodeEnum.getMessage();}this.code = errorCodeEnum.getCode();}/*** @param message 异常提示信息*/public RuanjiaExceptionHandler(String message){this.code = HttpStatus.ERROR;this.message = message;}}

2、全局异常类

作用:拦截所有Controller异常

/*** 全局异常捕获:*     @ControllerAdvice 包含@Component,可以被扫描到。统一处理异常。*     @ExceptionHandler(Exception.class) 用在方法上面表示遇到这个异常就执行以下方法。** @author cms* @version 1.0.0.0* @Date: 2022/5/21 19:15*/
@Slf4j
@ControllerAdvice
public class SystemGlobalExceptionHandler
{/*** 自定义异常** @param e 算术异常* @param response  响应结果*/@ExceptionHandler(RuanjiaExceptionHandler.class)public void ruanjiaExceptionHandler(RuanjiaExceptionHandler e, HttpServletResponse response){log.error("===========RuanjiaExceptionHandler(自定义异常)==========");e.printStackTrace();ServletUtils.parseString(response, JSON.toJSONString(ResultReturn.error(e.getCode(), e.getMessage())));}/*** 算术异常** @param e         异常对象* @param response  响应结果*/@ExceptionHandler(ArithmeticException.class)public void handlerArithmeticException(ArithmeticException e, HttpServletResponse response){log.error("===========ArithmeticException(算术异常)==========");e.printStackTrace();ServletUtils.parseString(response, JSON.toJSONString(ResultReturn.error(HttpStatus.ERROR, e.getMessage())));}/*** GET/POST不支持异常** @param e         异常对象* @param request   请求* @param response  响应结果*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public void handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request, HttpServletResponse response){log.error("===========HttpRequestMethodNotSupportedException(GET/POST 不支持异常)==========");String requestURI = request.getRequestURI();log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());e.printStackTrace();ServletUtils.parseString(response, JSON.toJSONString(ResultReturn.error(HttpStatus.BAD_REQUEST,"请求地址【"+requestURI+"】,不支持【"+e.getMethod()+"】请求")));}}

此致!配置完成,进入测试环节!

2.9、编写Controller测试类

/*** @author cms* @version 1.0.0.0* @Date: 2022/5/21 19:11*/
@RestController
public class TestController
{/*** 统一结果返回测试* * @return 结果*/@GetMapping("/result")public Object result(){return "同意结果返回测试!";}/*** 算术异常(全局异常处理程序拦截)* * @return 结果*/@GetMapping("/error1")public Object error(){int a = 10/0;return a;}/*** 自定义异常拦截(全局异常处理程序拦截)* * @param username 用户名* @return 返回结果*/@GetMapping("/error2")public Object error2(String username){if (StringUtils.isEmpty(username)){throw new RuanjiaExceptionHandler(ErrorEnum.S_CATCH_AUTH, "用户名不能为空!");}return username;}}

效果图:

1、统一结果返回测试

2、系统算术异常拦截

3、自定义异常拦截

结束语:不要半途而废!

Spring Boot【定制化】~ AOP统一结果处理以及异常拦截相关推荐

  1. Spring Boot中使用AOP统一处理Web请求日志

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  2. 在Spring Boot中使用切面统一处理自定义的异常

    最近我们将项目的一个单独模块提取了一个微服务,这个微服务主要负责其他系统的接入.目的是发布主项目的时候不会影响到其他系统接入.在提取出的微服务中,需要定义一个正常返回的报文和异常返回的报文.正常返回报 ...

  3. Spring Boot定制启动图案

    转载自 Spring Boot定制启动图案 启动图案 Spring Boot在启动的时候会显示一个默认的Spring的图案,对应的类为SpringBootBanner. .   ____       ...

  4. Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置

    Spring Boot + Mybatis 配合 AOP 和注解实现动态数据源切换配置 前言: 1. 数据库准备: 2. 环境准备: 3.代码部分 4. 测试: 5.等等 6.配合注解实现 7 .测试 ...

  5. Spring boot定制错误数据携带出去

    定制错误数据 Spring boot出现错误以后,会来到/error请求 会被BasicErrorController处理,自适应返回 浏览器访问,返回页面 客户端访问,返回json getError ...

  6. Spring Boot笔记-404错误统一管理

    这里有一点要注意: spring boot错误的页面都会到error的请求中,所以可以用如下的方式统一管理 package com.xxxxx.apc.controller;import com.ap ...

  7. Spring boot中使用aop详解

    aop是spring的两大功能模块之一,功能非常强大,为解耦提供了非常优秀的解决方案. 现在就以springboot中aop的使用来了解一下aop. 一:使用aop来完成全局请求日志处理 创建一个sp ...

  8. Spring Boot 定制横幅banner与关闭banner

    点此查看全部文字教程.视频教程.源代码 本文目录 1. 啥是banner 2. 定制banner 3. 关闭banner 1. 啥是banner banner者,横幅也,即Spring Boot项目启 ...

  9. Spring boot定制个性化banner(七彩佛祖版)

    1.在项目的src/main/resources目录下创建banner,txt文件 2.创建完成banner.txt文件后,即可以在文件中放入需要自定义的任意字符图案,本次以佛祖图案为例(代码直接复制 ...

最新文章

  1. Go Pro 半小时上手指南
  2. 找父节点和子节点个数(Poj1634)
  3. MacOS常用快捷键
  4. dynamic和var的区别
  5. 集合里面的 E是泛型 暂且认为是object
  6. Linux与C++11多线程编程(学习笔记)
  7. css3 transform文字,CSS3 transform 字体模糊问题
  8. 交叉熵损失函数原理详解,KL散度
  9. 修改 Mac 版 Safari、Chrome、FireFox、Opera 的 User-Agent
  10. java jsp网页计算器_JSP实现计算器功能(网页版)
  11. 【github系列】解决Github上README无法显示图片
  12. python pymysql模块 链接mysql 遍历查询结果的方法 详解
  13. 机器视觉:HDR技术
  14. mysql案例~非常规操作汇总
  15. 简要介绍随机森林原理
  16. HTML页面分享微博、QQ、微信功能
  17. RedHat 8 dnf源配置
  18. 木纹标识lisp_lisp:关于标识符:原子和列表初步
  19. 怎么压缩word文档大小?
  20. 开源python-向tensorflow-addons学习

热门文章

  1. 病毒木马查杀实战第024篇:MBR病毒之编程解析引导区
  2. 服务器不能读取无线网卡,无线网卡无法获得IP地址的解决方案
  3. 医疗器械软件测试相关
  4. 国外创业者分享之一个iOS游戏赚了多少钱?普通 iOS 应用的收入能否养活自己
  5. 3DSMAX中英文对照大全(从A-Z分类)
  6. MQTT学习笔记(4)报文分析之PUBLISH
  7. python青蛙跳台阶_Python之青蛙跳台阶
  8. 在 vi 编辑器中的命令模式下,删除当前光标处的字符使用 __ 命 令。
  9. 根据 Excel 中的数据批量修改文件的扩展名
  10. Apache HBase