网站商城前台模板免费下载,做智能网站营销话术,做网站免费吗,苏州市吴中区住房和城乡建设局网站原理
AOP#xff1a;面向切面编程#xff08;spring AOP#xff09; ThreadLocal#xff1a;实现线程范围内的局部变量#xff0c;即ThreadLocal在一个线程中是共享的#xff0c;在不同线程之间是隔离的。ThreadLocal 自定义注解#xff1a;自定义注解
代码实现
自定…
原理
AOP面向切面编程spring AOP ThreadLocal实现线程范围内的局部变量即ThreadLocal在一个线程中是共享的在不同线程之间是隔离的。ThreadLocal 自定义注解自定义注解
代码实现
自定义注解
package com.dd.controller.log;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface LogAnnotation {/*** 日志名称*/String description() default ;/*** 日志操作类型*/String type();}
日志切面
package com.dd.controller.log;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;Aspect
Component
Slf4j
public class LogAspect {private static final ThreadLocalDate beginTimeThreadLocal new NamedThreadLocalDate(ThreadLocal beginTime);/*** Controller层切点,注解方式*/Pointcut(annotation(com.dd.controller.log.LogAnnotation))public void controllerAspect() {}/*** 前置通知 (在方法执行之前返回)用于拦截Controller层记录用户的操作的开始时间** param joinPoint 切点* throws InterruptedException*/Before(controllerAspect())public void doBefore(JoinPoint joinPoint) throws InterruptedException {//线程绑定变量该数据只有当前请求的线程可见Date beginTime new Date();beginTimeThreadLocal.set(beginTime);log.info(前置通知 开始时间 beginTime);}/*** 后置通知(在方法执行之后返回) 用于拦截Controller层操作** param joinPoint 切点*/After(controllerAspect())public void after(JoinPoint joinPoint) {try {Object[] objs joinPoint.getArgs();if (objs ! null objs.length 0) {for (Object object : objs) {if (object instanceof HttpServletRequest) {break;}}}String logName getControllerMethodInfo(joinPoint).get(description).toString();String logType getControllerMethodInfo(joinPoint).get(type).toString();//请求开始时间long beginTime beginTimeThreadLocal.get().getTime();long endTime System.currentTimeMillis();log.info(后置通知结束时间{}, logName:{}, logType:{} , endTime, logName, logType);//请求耗时Long logElapsedTime endTime - beginTime;log.info(接口耗时 endTime);} catch (Exception e) {log.error(AOP后置通知异常, e);}}/*** 获取注解中对方法的描述信息 用于Controller层注解** param joinPoint 切点* return 方法描述* throws Exception*/public static MapString, Object getControllerMethodInfo(JoinPoint joinPoint) throws Exception {MapString, Object map new HashMapString, Object(16);//获取目标类名String targetName joinPoint.getTarget().getClass().getName();//获取方法名String methodName joinPoint.getSignature().getName();//获取相关参数Object[] arguments joinPoint.getArgs();//生成类对象Class targetClass Class.forName(targetName);//获取该类中的方法Method[] methods targetClass.getMethods();String description ;String type null;for (Method method : methods) {if (!method.getName().equals(methodName)) {continue;}Class[] clazzs method.getParameterTypes();if (clazzs.length ! arguments.length) {//比较方法中参数个数与从切点中获取的参数个数是否相同原因是方法可以重载哦continue;}description method.getAnnotation(LogAnnotation.class).description();type method.getAnnotation(LogAnnotation.class).type();map.put(description, description);map.put(type, type);}return map;}}
package com.dd.controller.log;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.core.NamedThreadLocal; import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Date; import java.util.HashMap; import java.util.Map;
Aspect Component Slf4j public class LogAspect {
private static final ThreadLocalDate beginTimeThreadLocal new NamedThreadLocalDate(ThreadLocal beginTime);/*** Controller层切点,注解方式*/
Pointcut(annotation(com.dd.controller.log.LogAnnotation))
public void controllerAspect() {}/*** 前置通知 (在方法执行之前返回)用于拦截Controller层记录用户的操作的开始时间** param joinPoint 切点* throws InterruptedException*/
Before(controllerAspect())
public void doBefore(JoinPoint joinPoint) throws InterruptedException {//线程绑定变量该数据只有当前请求的线程可见Date beginTime new Date();beginTimeThreadLocal.set(beginTime);log.info(前置通知 开始时间 beginTime);
}/*** 后置通知(在方法执行之后返回) 用于拦截Controller层操作** param joinPoint 切点*/
After(controllerAspect())
public void after(JoinPoint joinPoint) {try {Object[] objs joinPoint.getArgs();if (objs ! null objs.length 0) {for (Object object : objs) {if (object instanceof HttpServletRequest) {break;}}}String logName getControllerMethodInfo(joinPoint).get(description).toString();String logType getControllerMethodInfo(joinPoint).get(type).toString();//请求开始时间long beginTime beginTimeThreadLocal.get().getTime();long endTime System.currentTimeMillis();log.info(后置通知结束时间{}, logName:{}, logType:{} , endTime, logName, logType);//请求耗时Long logElapsedTime endTime - beginTime;log.info(接口耗时 endTime);} catch (Exception e) {log.error(AOP后置通知异常, e);}
}/*** 获取注解中对方法的描述信息 用于Controller层注解** param joinPoint 切点* return 方法描述* throws Exception*/
public static MapString, Object getControllerMethodInfo(JoinPoint joinPoint) throws Exception {MapString, Object map new HashMapString, Object(16);//获取目标类名String targetName joinPoint.getTarget().getClass().getName();//获取方法名String methodName joinPoint.getSignature().getName();//获取相关参数Object[] arguments joinPoint.getArgs();//生成类对象Class targetClass Class.forName(targetName);//获取该类中的方法Method[] methods targetClass.getMethods();String description ;String type null;for (Method method : methods) {if (!method.getName().equals(methodName)) {continue;}Class[] clazzs method.getParameterTypes();if (clazzs.length ! arguments.length) {//比较方法中参数个数与从切点中获取的参数个数是否相同原因是方法可以重载哦continue;}description method.getAnnotation(LogAnnotation.class).description();type method.getAnnotation(LogAnnotation.class).type();map.put(description, description);map.put(type, type);}return map;
}} 引用注解
LogAnnotation(description 测试接口, type 测试)GetMapping(/test)public void test() throws Exception {}效果