package com.jie.common;
import java.lang.annotation.*;
/** * @author wuchunjie * @date 2018/2/23 */ @Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取 @Target(ElementType.METHOD)//目标是方法 @Documented//文档生成时,该注解将被包含在javadoc中,可去掉 public @interface OperationLogger { /** * 模块名字 */ String modelName() default "";
1/\*\* 2 \* 操作类型 3 \*/ 4String option();
}
package com.jie.common;
import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method;
/** * @author wuchunjie * @date 2018/2/23 */ @Aspect @Component public class SysLogAspect {
1private static final Logger logger = Logger.getLogger(SysLogAspect.class); 2 3/\*\* 4 \* 定义Pointcut,Pointcut的名称,此方法不能有返回值,该方法只是一个标示 5 \*/ 6@Pointcut("@annotation(com.jie.common.OperationLogger)") 7public void controllerAspect() 8{ 9 System.out.println("我是一个切入点"); 10} 11 12/\*\* 13 \* 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。 14 \* @param joinPoint 15 \*/ 16@Before("controllerAspect()") 17public void doBefore(JoinPoint joinPoint) 18{ 19 System.out.println("=====SysLogAspect前置通知开始====="); 20 //handleLog(joinPoint, null); 21} 22 23/\*\* 24 \* 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。 25 \* @param joinPoint 26 \*/ 27@AfterReturning(pointcut = "controllerAspect()") 28public void doAfter(JoinPoint joinPoint) 29{ 30 System.out.println("=====SysLogAspect后置通知开始====="); 31 //handleLog(joinPoint, null); 32} 33 34/\*\* 35 \* 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。 36 \* @param joinPoint 37 \* @param e 38 \*/ 39@AfterThrowing(value = "controllerAspect()", throwing = "e") 40public void doAfter(JoinPoint joinPoint, Exception e) 41{ 42 System.out.println("=====SysLogAspect异常通知开始====="); 43 //handleLog(joinPoint, e); 44} 45 46/\*\* 47 \* 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。 48 \* @param joinPoint 49 \*/ 50@Around("controllerAspect()") 51public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable 52{ 53 System.out.println("=====SysLogAspect 环绕通知开始====="); 54 //handleLog(joinPoint, null); 55 Object obj= joinPoint.proceed(); 56 System.out.println("=====SysLogAspect 环绕通知结束====="); 57 return obj; 58} 59 60/\*\* 61 \* 日志处理 62 \* 63 \* @param joinPoint 64 \* @param e 65 \*/ 66private void handleLog(JoinPoint joinPoint, Exception e) 67{ 68 try 69 { 70 //获得注解 71 OperationLogger logger = giveController(joinPoint); 72 if (logger == null) 73 { 74 return; 75 } 76 77 String signature = joinPoint.getSignature().toString(); // 获取目标方法签名 78 String methodName = signature.substring(signature.lastIndexOf(".") + 1, 79 signature.indexOf("(")); 80 81 String longTemp = joinPoint.getStaticPart().toLongString(); 82 String classType = joinPoint.getTarget().getClass().getName(); 83 84 Class<?> clazz = Class.forName(classType); 85 86 Method\[\] methods = clazz.getDeclaredMethods(); 87 System.out.println("methodName: " + methodName); 88 89 for (Method method : methods) 90 { 91 if (method.isAnnotationPresent(OperationLogger.class) 92 && method.getName().equals(methodName)) 93 { 94 //OpLogger logger = method.getAnnotation(OpLogger.class); 95 String clazzName = clazz.getName(); 96 System.out.println("clazzName: " + clazzName + ", methodName: " 97 + methodName); 98 } 99 } 100 101 } catch (Exception exp) 102 { 103 logger.error("异常信息:{}", exp); 104 exp.printStackTrace(); 105 } 106} 107 108/\*\* 109 \* 获得注解 110 \* @param joinPoint 111 \* @return 112 \* @throws Exception 113 \*/ 114private static OperationLogger giveController(JoinPoint joinPoint) throws Exception 115{ 116 Signature signature = joinPoint.getSignature(); 117 MethodSignature methodSignature = (MethodSignature) signature; 118 Method method = methodSignature.getMethod(); 119 120 if (method != null) 121 { 122 return method.getAnnotation(OperationLogger.class); 123 } 124 return null; 125}
}
spring-mvc.xml
<!-- 1、配置映射器与适配器 -->mvc:annotation-driven</mvc:annotation-driven>
<!-- aop --><bean id="logService" class="com.jie.common.SysLogAspect"></bean>
<!-- 开启切面编程功能 --><aop:aspectj-autoproxy proxy-target-class="true"/>

切到controller的参数之后,将pojo直接反序列化为参数保存到数据库中即可