Spring使用AOP完成统一结果封装实例demo
Spring使用AOP完成统一结果封装
起因:自己写项目的时候忍受不了每个方法都要写一个retrun Result.success();
和 retrun Result.error();
,同时想到项目运行时异常的统一捕捉处理,于是我就在想有没有一种方法能够快捷有效的实现统一返回结果格式的方法。同时也能够比较方便的设置各种参数方便使用,于是我就想到AOP。
Demo实现
引入依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
自定义注解(NoResult.java 使用此注解的method,将不会封装返回结果)
/** * @interface自定义注解 * @Target: 注解的作用目标 PARAMETER:方法参数 METHOD:方法 TYPE:类、接口 * * @Retention:注解的保留位置 RUNTIME 种类型的Annotations将被JVM保留, * * 能在运行时被JVM或其他使用反射机制的代码所读取和使用 */ @Documented @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface NoResult { }
ResultCode.class 用于定义Reponses返回码
public enum ResultCode { SUCCESS(0, "操作成功", ""), ERROR(1, "操作失败", ""); private final int code; /** * 状态码信息 */ private final String message; /** * 状态码描述(详情) */ private final String description; ResultCode(int code, String message, String description) { this.code = code; this.message = message; this.description = description; } public int getCode() { return code; } public String getMessage() { return message; } public String getDescription() { return description; } }
BaseResponse.java 用于定义统一返回结果结构
/** * 通用返回类 * * @param <T> * @author Chengming.Zhang */ @Data public class BaseResponse<T> implements Serializable { private int code; private T data; private String message; private String description; public BaseResponse(int code, T data, String message, String description) { this.code = code; this.data = data; this.message = message; this.description = description; } public BaseResponse(int code, T data, String message) { this(code, data, message, ""); } public BaseResponse(int code, T data) { this(code, data, "", ""); } public BaseResponse(ResultCode resultCode) { this(resultCode.getCode(), null, resultCode.getMessage(), resultCode.getDescription()); } public BaseResponse(ResultCode resultCode, T data) { this(resultCode.getCode(), data, resultCode.getMessage(), resultCode.getDescription()); } }
切面实现
import com.study.project.annotation.NoResult; import com.study.project.common.BaseResponse; import com.study.project.common.ResultCode; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.*; import java.lang.reflect.Method; /** * @author Chengming.Zhang * @date 2023/2/5 */ @Slf4j @Aspect @Component public class ResulyAspect { @Pointcut("execution(* com.study.project.controller.*..*(..))") public void pointAspect() { } /** * 环绕通知 * * @param joinPoint */ @Around("pointAspect()") public Object doAfter(ProceedingJoinPoint joinPoint) throws Throwable { // 转换为method MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); // 包装结果 return packageResult(joinPoint, method); } public Object packageResult(ProceedingJoinPoint joinPoint, Method method) throws Throwable { Class<?> returnType = method.getReturnType(); Object result = joinPoint.proceed(); // void不需要包装 if (returnType.equals(void.class) || returnType.equals(Void.class)) { return result; } // 设置了不需要包装的接口 NoResult noResult = method.getAnnotation(NoResult.class); if (noResult == null) { noResult = method.getDeclaringClass().getAnnotation(NoResult.class); } if (noResult != null) { return result; } // 非restful风格接口不需要包装 RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); GetMapping getMapping = method.getAnnotation(GetMapping.class); PostMapping postMapping = method.getAnnotation(PostMapping.class); DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class); PutMapping putMapping = method.getAnnotation(PutMapping.class); PatchMapping patchMapping = method.getAnnotation(PatchMapping.class); if (requestMapping != null || getMapping != null || postMapping != null || deleteMapping != null || putMapping != null || patchMapping != null) { if (result == null) { return new BaseResponse(ResultCode.ERROR); } else { if (result instanceof BaseResponse) { BaseResponse baseResponse = (BaseResponse) result; return baseResponse; } else { return new BaseResponse(ResultCode.SUCCESS, result); } } } else { return result; } } }
代码分析
@Pointcut
注解用于定义一个切面,上述代码中的切面表示com.study.project.controller
包及其子包下的所有类和方法@Around(“pointAspect()”)
表示此方法应用于 pointAspect
切面,@Around
表示在切点的前后都执行此方法
这中间其实还有一个小插曲,我本来想用JoinPoint
类,并使用@After
后置通知的方法,结果我发现我在后置通知的JoinPoint
里面无法获取方法的接口result,所以后面就换了ProceedingJoinPoint
类,这个类有一个特殊的方法proceed()
可以直接获取方法的返回值。
Controller实现
import com.study.project.annotation.NoResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Chengming.Zhang * @date 2023/2/4 */ @RestController public class TestController { @RequestMapping("/test1") public Object test1(){ return "test1"; } @NoResult @RequestMapping("/test2") public Object test2(){ return "test2"; } @RequestMapping("/test3") public Object test3(){ return null; } }
结果
到此为止,我们就实现了统一的结果封装。
到此这篇关于Spring使用AOP完成统一结果封装的文章就介绍到这了,更多相关Spring使用AOP统一结果封装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java中 equals 重写时为什么一定也要重写 hashCode
这篇文章主要介绍了Java中 equals 重写时为什么一定也要重写 hashCode,equals 方法和 hashCode 方法是 Object 类中的两个基础方法,它们共同协作来判断两个对象是否相等,所以之间到底有什么联系呢,接下来和小编一起进入文章学习该内容吧2022-05-05AndroidStudio无法新建Java工程的简单解决办法
AS创建java工程是非常麻烦的,AS没有提供直接创建java工程的方法且常常无法新建,这篇文章主要给大家介绍了关于AndroidStudio无法新建Java工程的简单解决办法,需要的朋友可以参考下2024-06-06MyBatisPlus中@TableField注解的基本使用
这篇文章主要介绍了MyBatisPlus中@TableField注解的基本使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2023-07-07java.net.MalformedURLException异常的解决方法
下面小编就为大家带来一篇java.net.MalformedURLException异常的解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-05-05RedisKey的失效监听器KeyExpirationEventMessageListener问题
这篇文章主要介绍了RedisKey的失效监听器KeyExpirationEventMessageListener问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-05-05
最新评论