日志信息管理:切面-自定义注解
1.自定义注解
@Target注解:指明了修饰这个注解的使用范围,即被描述的注解可以用在哪里
ElementType的取值包含以下几种:
- TYPE :类,接口,枚举
- FIELD:域,包含枚举常量
- METHOD:方法
- PARAMETER:参数
- CONSTRUCTOP:构造方法
- LOCAL_VARIABLE:局部变量
- ANNOTATION_TYPE:注解类型
- PACKAGE:包
@Retention注解:指明修饰的注解的生命周期,即会保留到哪个阶段
RetentionPolicy的取值包含以下三种
- SOURCE:源码级别保留,编译后即丢弃
- CLASS:编译级别保留,编译后的class文件总存在,在jvm运行时丢弃,这是默认值
- RUNTIME:运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用
@Documented注解:指明修饰的注解可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值
@Inherited注解:允许子类继承父类中的注解
1 @Target({ElementType.TYPE,ElementType.METHOD}) 2 @Retention(RetentionPolicy.RUNTIME) 3 @Documented 4 public @interface ControllerLog { 5 6 // 记录操作模块 7 String title() default ""; 8 9 // 记录操作动作 10 String action() default ""; 11 }
2.切面类
1 @Slf4j 2 @Aspect 3 @Component 4 public class ControllerLogAspect { 5 6 @Autowired 7 private SysLogMapper sysLogMapper; 8 9 /** 10 * 配置切入点(以@ControllerLog注解为标志) 11 */ 12 @Pointcut("@annotation(com.philips.dms.common.annotation.ControllerLog)") 13 public void controllerLog(){ 14 } 15 16 /** 17 * 切面处理,添加controller前后日志打印 18 * @param point 19 * @return 20 * @throws Throwable 21 */ 22 @Around(value = "controllerLog()") 23 public Object setControllerLog(ProceedingJoinPoint point) throws Throwable{ 24 MethodSignature methodSignature = (MethodSignature) point.getSignature(); 25 Method method = methodSignature.getMethod(); 26 // 如果使用cglib代理的类可能获取不到注解,由于切点为注解,所以必然可以获取到注解,此处不做判断 27 ControllerLog controllerLog = method.getAnnotation(ControllerLog.class); 28 // 获取请求的方法名 29 String methodName = methodSignature.getName(); 30 // 获取请求的类名 31 String className = point.getTarget().getClass().getSimpleName(); 32 // 获取请求路径 33 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 34 HttpServletRequest request = servletRequestAttributes.getRequest(); 35 String url = request.getRequestURI().toString(); 36 // 请求参数:point.getArgs() 去除 BindingResult; 37 Object[] args = subParams(point.getArgs()); 38 String params = JSONObject.toJSONString(args); 39 log.info("[{}-{}] {}-{} params:{}",className,methodName,controllerLog.title(),controllerLog.action(),params); 40 log.info("[{}-{}] {}-{} url:{}",className,methodName,controllerLog.title(),controllerLog.action(),url); 41 long start = System.currentTimeMillis(); 42 Object object = point.proceed(); 43 long end = System.currentTimeMillis(); 44 if(object != null){ 45 log.info("[{}-{}] {}-{} costTime:{}ms result:{}",className,methodName,controllerLog.title(),controllerLog.action(),end-start,JSONObject.toJSONString(object)); 46 } 47 else{ 48 log.info("[{}-{}] {}-{} costTime:{}ms",className,methodName,controllerLog.title(),controllerLog.action(),end-start); 49 } 50 SysLog sysLog = new SysLog(); 51 sysLog.setId(UUID.randomUUID().toString().replace("-","")); 52 sysLog.setUserId("test"); 53 sysLog.setUserName("test"); 54 sysLog.setRoleName("test"); 55 sysLog.setRequestIp(IPUtil.getIpAddr(request)); 56 sysLog.setActionUrl(url); 57 sysLog.setParams(params); 58 sysLog.setResult(JSONObject.toJSONString(object)); 59 sysLog.setCreateTime(new Date()); 60 sysLogMapper.insert(sysLog); 61 return object; 62 } 63 64 /** 65 * 去除spring校验的BiddingResult参数信息:因为BindingResult没有实现序列化,转换json时会出错 66 * @param args 67 * @return 68 */ 69 public Object[] subParams(Object[] args){ 70 Object[] newArray; 71 if(args != null){ 72 int size = args.length; 73 if(size > 0){ 74 if(args[size - 1] instanceof BindingResult){ 75 newArray = Arrays.copyOfRange(args,0,size - 1); 76 return newArray; 77 } 78 else{ 79 return args; 80 } 81 } 82 } 83 return args; 84 } 85 }
3.在某一Controller上加自定义注解即可:@ControllerLog
1 @RequestMapping("/test") 2 @ControllerLog(title= "测试1",action="测试2") 3 public Result test(@RequestBody String test){ 4 5 }