使用自定义注解+SpringAop实现操作日志记录,记录内容包括请求参数、请求方法、请求响应时间等的记录。
一、在pom文件中,引入依赖包和插件。
1<dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-aop</artifactId> 4</dependency> 5 6<!-- lombok --> 7<dependency> 8 <groupId>org.projectlombok</groupId> 9 <artifactId>lombok</artifactId> 10 <optional>true</optional> 11</dependency>
lombok还需安装插件。我这里只是主要的包引入,还有其他的需要自行引入。
二、自定义注解
1import java.lang.annotation.Documented; 2import java.lang.annotation.ElementType; 3import java.lang.annotation.Retention; 4import java.lang.annotation.RetentionPolicy; 5import java.lang.annotation.Target; 6 7/** 8 * 定义系统日志注解 9 */ 10@Target(ElementType.METHOD) 11@Retention(RetentionPolicy.RUNTIME) 12@Documented 13public @interface SysLog { 14 15 String value() default ""; 16 17}
三、编写AOP切面类
1import com.google.gson.Gson; 2import com.piao.annotation.SysLog; 3import com.piao.sys.sysconfig.bo.SysLogBo; 4import com.piao.sys.sysconfig.service.SysLogService; 5import com.power.common.util.DateTimeUtil; 6import lombok.AllArgsConstructor; 7import lombok.SneakyThrows; 8import org.aspectj.lang.ProceedingJoinPoint; 9import org.aspectj.lang.annotation.Around; 10import org.aspectj.lang.annotation.Aspect; 11import org.aspectj.lang.annotation.Pointcut; 12import org.aspectj.lang.reflect.MethodSignature; 13import org.springframework.stereotype.Component; 14 15import java.lang.reflect.Method; 16import java.util.ArrayList; 17import java.util.List; 18 19/** 20 * 系统日志切面 21 */ 22@Aspect 23@Component 24@AllArgsConstructor 25public class SysLogAspect { 26 27 private final SysLogService sysLogService; 28 29 /** 30 * 这里我们使用注解的形式 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method 切点表达式: 31 * execution(...) 32 */ 33 @Pointcut("@annotation(com.piao.annotation.SysLog)") 34 public void logPointCut() {} 35 36 /** 37 * 环绕通知 @Around , 当然也可以使用 @Before (前置通知) @After (后置通知) 38 * 39 * @param point 40 * @return 41 * @throws Throwable 42 */ 43 @SneakyThrows 44 @Around("logPointCut()") 45 public Object around(ProceedingJoinPoint point) { 46 long beginTime = System.currentTimeMillis(); 47 Object result = point.proceed(); 48 long time = System.currentTimeMillis() - beginTime; 49 SysLogBo sysLog = getLog(point, time); 50 sysLogService.addSysLog(sysLog); 51 52 return result; 53 } 54 55 /** 56 * 获取日志信息 57 * 58 * @param joinPoint 59 * @param time 60 */ 61 private SysLogBo getLog(ProceedingJoinPoint joinPoint, long time) { 62 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 63 Method method = signature.getMethod(); 64 SysLogBo sysLogBO = new SysLogBo(); 65 sysLogBO.setExeuTime(time); 66 sysLogBO.setCreateDate(DateTimeUtil.nowStrTime()); 67 SysLog sysLog = method.getAnnotation(SysLog.class); 68 if (sysLog != null) { 69 // 注解上的描述 70 sysLogBO.setRemark(sysLog.value()); 71 } 72 // 请求的 类名、方法名 73 String className = joinPoint.getTarget().getClass().getName(); 74 String methodName = signature.getName(); 75 sysLogBO.setClassName(className); 76 sysLogBO.setMethodName(methodName); 77 // 请求的参数 78 Object[] args = joinPoint.getArgs(); 79 List<String> list = new ArrayList(args.length); 80 for (Object o : args) { 81 list.add(new Gson().toJson(o)); 82 } 83 sysLogBO.setParams(list.toString()); 84 85 return sysLogBO; 86 } 87 88}
四、编写日志业务实体
1import lombok.Data; 2import lombok.ToString; 3 4@Data 5@ToString 6public class SysLogBo { 7 8 private long exeuTime; 9 10 private String createDate; 11 12 private String className; 13 14 private String methodName; 15 16 private String params; 17 18 private String remark; 19 20}
五、编写日志业务服务和实现
1import com.baomidou.mybatisplus.extension.api.R; 2import com.piao.sys.sysconfig.bo.SysLogBo; 3 4/** 5 * 系统日志服务 6 */ 7public interface SysLogService { 8 9 R addSysLog(SysLogBo sysLog); 10 11} 12 13import com.baomidou.mybatisplus.extension.api.R; 14import com.piao.sys.sysconfig.bo.SysLogBo; 15import com.piao.sys.sysconfig.service.SysLogService; 16import lombok.extern.slf4j.Slf4j; 17import org.springframework.scheduling.annotation.Async; 18import org.springframework.stereotype.Service; 19 20/** 21 * 系统日志服务实现 22 */ 23@Slf4j 24@Service 25public class SysLogServiceImpl implements SysLogService { 26 27 @Async 28 @Override 29 public R addSysLog(SysLogBo sysLog) { 30 //这里可以编写存入数据库,es或者进行其他持久化 31 log.info(sysLog.toString()); 32 return R.ok(sysLog); 33 } 34 35}
我这里实现类只是记录到日志里面去了,大家可以根据自己的需求去持久化记录。
六、使用自定义注解验证效果。
1import com.piao.annotation.SysLog; 2import lombok.extern.slf4j.Slf4j; 3import org.springframework.web.bind.annotation.*; 4 5@RestController 6@RequestMapping(value = "/user") 7public class UserController { 8 9 @SysLog(value = "获取一个例子") 10 @GetMapping(value = "/getDemo") 11 public String getDemo(){ 12 String str = "this is a zhirong user"; 13 return str; 14 } 15 16}
我们通过swagger文档来调用添加了自定义注解的接口,也可以通过浏览器调用。

下面我们看控制台输出的日志,已经成功调用了日志服务,并输出了日志信息。
