Springboot项目使用AOP与自定义注解记录请求日志方式
目录
- 添加Mavenjavascript依赖
- 日志实python体类
- 自定义注解
- AOP切面类
- 测试Controller
- 返回实体类
- 用户实体类
- 总结
添加Maven依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.46</version> </dependency>
日志实体类
package com.baidu.entity; import lombok.Data; @Data public class RequestLog { /** * 主键 */ private int id; /** * 操作方式 * * 1:查询 */ private Integer operateType; /** * 查询内容 */ private String operateContent; /** * 请求内容 */ private String request; /** * 访问IP */ private String ip; /** * 请求结果 * * 1:成功 -1:失败 */ private String resultCode; /** * 错误信息 */ private String errorMessage; /** * 操作时间 */ private Long time; /** * 备注,预留字段 */ private String remark; }
自定义注解
package com.baidu.annotation; import Java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogOperation { /** * 操作类型 */ public int operateType() default 1; /** * 操作内容 */ public String operateContent(); /** * 备注 */ public String remark(); }
AOP切面类
package com.baidu.ASPect; import java.util.Arrays; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.an编程客栈notation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; 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.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSON; import com.baidu.annotation.LogOperation; import com.baidu.entity.RequestLog; import com.baidu.entity.Result; import com.baidu.entity.UserEntity; import lombok.extern.slf4j.Slf4j; @Aspect @Component @Slf4j public class RequestLogAspect { @Autowired private HttpServletRequest request; /** * 这边由于我只需自定义注解,所以Poincut表达式这里写注解的全路径, * 若想在某个包下面切入,就写那个包路径,例如,com.baidu.controller,这样会切入整个controller包下面的类 * Poincut表达式不多说,大家可以去百度一下 */ @Pointcut("@annotation(com.baidu.annotation.LogOperation)" ) public void pointcut(){} @Around("pointcut()") public Object process(ProceedingJoinPoint point) throws Throwable { Object returnValue = point.proceed(); return returnValue; } /** * 返回增强,目标方法正常执行完毕时执行 * @param point * @phpparam returnValue */ @AfterReturning(pointcut="pointcut()", returning="returnValue") public void afterReturningMethod(JoinPoint point, Object returnValue) { log.info("@AfterReturning:查询成功"); addRequestLog(point, returnValue); } /** * 异常抛出增强,目标方法发生异常的时候执行 * @param point * @param e */ @AfterThrowing(value = "pointcut()", throwing = "e") public void afterThorwingMethod(JoinPoint point, Exception e) { log.info("@AfterThrowing:查询失败"); addRequestLog(point, null); } //编程省略了@After、@Before private void addRequestLog(JoinPoint point, Object returnValue) { MethodSignature signature = (MethodSignature)point.getSignature(); LogOperation logOperation = signature.getMethod().getAnnotation(LogOperation.class); if(logOperation == null) { return; } Result result = transform(returnValue, Result.class); if(result==null) { result = new Result(); } Object[] objs = point.getArgs();//这是请求参数,是个数组 UserEntity user = transform(objs[0], UserEntity.class); String id = String.valueOf(objs[1]); log.info("id={},user={}", id, user.toString()); RequestLog requestLog = new RequestLog(); requestLog.setIp(request.getRemoteAddr()); requestLog.setOperateContent(logOperation.operateContent()); requestLog.setOperateType(logOperation.operateType()); requestLog.setRemark(""); requestLog.setRequest(Arrays.toString(point.getArgs()));//这是请求参数,是个数组 requestLog.setResultCode(result.getResultCode()); requestLog.setTime(new Date().getTime()); log.info("插入日志requestLog={}", requestLog.toString()); //插入数据库 懒得写了 } private <T> T transform(Object obj, Class<T> clazz) { return JSON.parseobject(JSON.toJSONString(obj), clazz); } }
测试Controller
package com.baidu.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.baidu.annotation.LogOperation; import com.baidu.entity.Result; import com.baidu.entity.UserEntity; @RestController @RequestMapping("/user") public class RequeatLogTest { @LogOperation(operateType= 1, operateContent = "查找用户列表", remark = "暂无备注") @PostMapping("/select") public Result selectUserList(UserEntity user, String id) { return new Result("1","成功","", "成功啦"); } }
返回实体类
package com.baidu.entity; import java.io.Serializable; import lombok.Data; @Data public class Result implements Serializable{ /** * */ private static final long serialVersionUID = 6103309328749274117L; public Result() { } public Result(String resultCode, String message, String errorMessage, Object result) { this.resultCode = resultCode; this.message = message; this.errorMessage = errorMessage; this.result = result; } /** * 错误码 */ private String resultCode; /** * 提示信息 */ private String message; /** * 错误信息 */ private String errorMessage; /** * 返回数据 */ private Object result; }
用户实体类
package com.baidu.entity; import java.io.Serializable; import lombok.Data; @Data public class UserEntity implements Serializable { /** * */ private static final long serialVersionUID = 4477284653938772276L; private String name; private int age; private String gender; }
用Postman调用返回成功
就这样吧!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论