冷静 专注 集中 努力
自定义注解实现操作日志
在梳理保全中心逻辑的过程中,有业务场景需要记录过程中某些保全的操作日志,打算使用注解加切面的方式实现,此处先做个测试Demo
1.定义操作日志注解@Log
@Retention 表示这是一个运行时注解,即运行起来之后,才获取注解中的相关信息,而不像基本注解@Override 那种不用运行,在编译时eclipse就可以进行相关工作的编译时注解。
@Target指定注解的类型 可以是方法、属性等,如下所示
package com.huida.investment; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.Date; /** * 自定义操作日志注解 * @Author zhanghailang * @Date 2020/10/16 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Log { //操作员 String operator() default "其他"; //保全类型 String edortype() default "其他"; // Date edorAppDate() default new Date("111111") ; //保全阶段 String state(); }
2.定义切面类
注解配合切面使用是一种很常见的做法,也可以使用过滤器的方式,本次只记录切面的方法,过滤器的后以后有时间再整理。。
package com.huida.investment; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; 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 sun.rmi.runtime.NewThreadAction; import java.lang.reflect.Method; /** * 操作日志切面处理 * @Author zhanghailang * @Date 2020/10/16 */ @Aspect//表明这是一个切面类 @Component public class LogAspect { /** * pointcut表示这是一个切点,@annotation表示这个切点切到一个注解上,后面带该注解的全类名 */ @Pointcut("@annotation(com.huida.investment.Log)") public void logPointCut(){}; /** * 环绕通知 */ @AfterReturning("logPointCut()") public void logArround(JoinPoint joinPoint){ //获取方法名称 String methodName = joinPoint.getSignature().getName(); //获取入参 Object[] params = joinPoint.getArgs(); StringBuilder builder = new StringBuilder(); for (Object o : params){ builder.append(o + ";"); } System.out.println("进入方法["+methodName+"],,,参数为:" + builder.toString()); //获得注解 Log testlog = getAnnotationLog(joinPoint); getControllerMethodDescription(testlog); System.out.println(methodName + "方法执行结束"); } /** * 是否存在注解,存在就获取 * @param joinPoint * @return */ private Log getAnnotationLog(JoinPoint joinPoint){ Signature signature =joinPoint.getSignature(); MethodSignature methodSignature =(MethodSignature)signature; Method method =methodSignature.getMethod(); if (method != null){ return method.getAnnotation(Log.class); } return null; } /** * 获取注解中对方法的描述信息 注解Log中的各个参数 * @param testlog */ private void getControllerMethodDescription(Log testlog){ //此处仅用来测试用,实际操作过程中,可能会有日志插表等逻辑 String operator = testlog.operator(); String state = testlog.state(); System.out.println("注解在方法内的参数 operator : " + operator + ", state :" + state); } }
3.测试使用
package com.huida.investment; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; /** * @description: 日志注解测试类 * @author: zhanghailang * @date: 2020-10-16 15:33 */ @RestController public class TestLogController { @Log(state = "测试日志注解") @GetMapping("/testLog/{username}") public String testLog(@PathVariable("username") String username){ return "测试成功"; } }
4.运行效果
zhanghailang