前言
在写Aurora这个项目之前,我是通过拦截器去记录用户操作日志,而这里讲解如何使用AOP配合自定义注解去实现用户日志记录,使用拦截器的方式,下一章贴出
导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
部分配置文件
spring:datasource:url: jdbc:mysql://localhost:3306/logusername: rootpassword: 123456jpa:hibernate:ddl-auto: update
自定义log注解
定义一个方法级别的@Log注解,用于标注需要监控的方法:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Log {String value() default "";}
创建实体类
@Entity@Data@Table(name = "syslog")public class SysLog implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String operation;private Integer time;private String method;private String params;private String ip;/*** ip地址来源*/private String location;@CreationTimestampprivate Timestamp createTime;}
创建 repository
@Repository
public interface SysLogRepo extends JpaRepository<SysLog,Long>{
}
切面和切点
定义一个LogAspect类,使用@Aspect标注让其成为一个切面,切点为使用@Log注解标注的方法,使用@Around环绕通知,部门工具代码,这里就不贴出了,可以到源码中查看
@Slf4j@Aspect@Componentpublic class LogAspect {@Autowiredprivate SysLogRepo sysLogRepo;@Pointcut("@annotation(me.zhengjie.annotation.Log)")public void pointcut() {}@Around("pointcut()")public Object around(ProceedingJoinPoint point){Object result = null;long beginTime = System.currentTimeMillis();try {// 执行方法result = point.proceed();} catch (Throwable e) {e.printStackTrace();}// 执行时长(毫秒)long time = System.currentTimeMillis() - beginTime;//保存日志saveLog(point, time);return result;}public void saveLog(ProceedingJoinPoint joinPoint, long time){MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();SysLog sysLog = new SysLog();Log logAnnotation = method.getAnnotation(Log.class);if (logAnnotation != null) {// 注解上的描述sysLog.setOperation(logAnnotation.value());}// 请求的方法名String className = joinPoint.getTarget().getClass().getName();String methodName = signature.getName();String username = null;sysLog.setMethod(className + "." + methodName + "()");// 请求的方法参数值Object[] args = joinPoint.getArgs();// 请求的方法参数名称LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paramNames = u.getParameterNames(method);if (args != null && paramNames != null) {String params = "";for (int i = 0; i < args.length; i++) {params += " " + paramNames[i] + ": " + args[i];}sysLog.setParams(params);}// 获取requestHttpServletRequest request = HttpContextUtils.getHttpServletRequest();// 设置IP地址sysLog.setIp(AddressUtils.getIpAddr(request));sysLog.setLocation(AddressUtils.getCityInfo(sysLog.getIp()));//模拟一个用户名sysLog.setUsername("admin");sysLog.setTime((int) time);sysLogRepo.save(sysLog);}}
项目结构如下
测试
编写TestController
@RestControllerpublic class TestController {@Autowiredprivate SysLogRepo sysLogRepo;@Log("记录测试")@GetMapping(value = "/test")public String test1(String test){return test;}@GetMapping(value = "/list")public ModelAndView list(Model model){List<SysLog> sysLogs = sysLogRepo.findAll();model.addAttribute("sysLogs",sysLogs);return new ModelAndView("/index");}}
依次访问:
localhost:8080/test?test=123
localhost:8080/list
项目源码
github:/dqjdda/SpringBoot_All
码云:/hgpt/SpringBoot_All
开源后台管理系统
欢迎体验Aurora
github: /dqjdda/Aurora
码云: /hgpt/Aurora