首页 > 代码库 > 用aspectJ 做了一次日志
用aspectJ 做了一次日志
1、
Java代码
<aspectj.version>1.7.4.RELEASE</aspectj.version>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
注意:如果JDK1.7的 必须这里也是1.7+
2、
Java代码
<aop:config proxy-target-class="true"></aop:config>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<aop:aspectj-autoproxy proxy-target-class="true"/>
注意:下载 必须在spring-mvc.xml里面,且有两个aop配置,下面那个是必须的,上面那个可能不是必须的(上面那个应该是spring aop的,如果有aspectJ了,可以不需要)
3、AOP类
Java代码
package com.kingen.aop;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.kingen.bean.Log;
import com.kingen.bean.User;
import com.kingen.service.log.LogService;
import com.kingen.util.Constants;
import com.kingen.util.DateUtils;
import com.kingen.util.SpringContextHolder;
import com.kingen.util.StringUtils;
import com.kingen.util.UserUtils;
/**
* 日志AOP
*
* @author wj
* @date 2016-11-16
*
*/
@Aspect
@Component
public class LogAOP {
private static LogService logService = SpringContextHolder.getBean(LogService.class);
下载
// 本地异常日志记录对象
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 在所有标注@LogAnnotation的地方切入
*
* @param joinPoint
*/
@Pointcut("@annotation(com.kingen.aop.LogAnnotation)")
public void logAspect() {
}
// @Around(value = "aApplogic() && @annotation(annotation) &&args(object,..)
// ", argNames = "annotation,object")
// public Object around(ProceedingJoinPoint pj,
// LogAnnotation annotation, Object object) throws Throwable {
// System.out.println("moduleName:"+annotation.moduleName());
// System.out.println("option:"+annotation.option());
// pj.proceed();
// return object;
// }
/**
* 前置通知 用于拦截Controller层记录用户的操作
*
* @param joinPoint
* 切点
* @throws Exception
*/
// @Around(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "annotation,object")
// public void doAround(ProceedingJoinPoint joinPoint, LogAnnotation annotation, Object object) {
//用@Around 会导致controller不执行,不返回页面
// @After(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "annotation,object")
// public void doAfter(JoinPoint joinPoint, LogAnnotation annotation, Object object) {
@AfterReturning(value = "logAspect() && @annotation(annotation) &&args(object,..) ", argNames = "", returning = "retVal")
public void doAfterReturning(JoinPoint joinPoint, LogAnnotation annotation, Object object, String retVal) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
try {
// String title = getAnnotationValue(joinPoint);
String title = getAnnotationValue(annotation);
saveLog(request, title);
} catch (Exception e) {
e.printStackTrace();
// 记录本地异常日志
logger.error("==异常通知异常==");
logger.error("异常信息:{}", e.getMessage());
}
}
/**
* 异常通知 用于拦截service层记录异常日志
*
* @param joinPoint
* @param e
*/
// 方法 catch住异常的话,这里执行不到
// @AfterThrowing(pointcut = "logAspect()", throwing = "e")
@AfterThrowing(value = "logAspect() && @annotation(annotation) &&args(..) " , throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, LogAnnotation annotation, Exception e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
try {
// String title = getAnnotationValue(joinPoint);
String title = getAnnotationValue(annotation);
saveLog(request, title, e);
} catch (Exception ex) {
// 记录本地异常日志
logger.error("==异常通知异常==");
logger.error("异常信息:{}", ex.getMessage());
}
}
下载
public static void saveLog(HttpServletRequest request, String title) {
saveLog(request, title, null);
}
/**
* 保存日志
*/
@Transactional
public static void saveLog(HttpServletRequest request, String title, Exception ex) {
User user = UserUtils.getCurrentUser();
if (user != null && user.getUserId() != null) {
Log log = new Log();
log.setCreateDate(DateUtils.getDateTime());
log.setTitle(title);
log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
log.setRemoteAddr(StringUtils.getRemoteAddr(request));
log.setUserAgent(user.getUsername());
// log.setUserAgent(request.getHeader("user-agent"));
log.setRequestUri(request.getRequestURI());
log.setParams(request.getParameterMap());
// 如果有异常,设置异常信息
log.setException(ex == null ? null : ex.getMessage());
// log.setException(ex == null ? null : Exceptions.getStackTraceAsString(ex));
log.setStatus(ex == null ? Constants.StatusEnum.Success.getIndex() : Constants.StatusEnum.Fail.getIndex());
// log.setMethod(request.getMethod());
// 异步保存日志
// new SaveLogThread(log, handler, ex).start();
logService.saveLog(log);
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint
* 切点
* @return 方法描述
* @throws Exception
*/
@Deprecated
public static String getAnnotationValue(JoinPoint joinPoint) throws Exception {
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 = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
String moduleName = method.getAnnotation(LogAnnotation.class).moduleName();
String option = method.getAnnotation(LogAnnotation.class).option();
Assert.hasText(moduleName, "模块名字不应为空");
Assert.hasText(option, "操作名字不应为空");
description = moduleName + "-" + option;
break;
}
}
}
return description;
}
public static String getAnnotationValue(LogAnnotation anno) throws Exception {
String moduleName = anno.moduleName();
String option = anno.option();
Assert.hasText(moduleName, "模块名字不应为空");
Assert.hasText(option, "操作名字不应为空");
String description = moduleName + "-" + option;
return description;
}
}
注意这里 @After和 @AfterReturning的区别,总的来说,就是 @After 是无论如何都会执行的,不管有没有异常抛出(这样会导致,在有异常的时候,记录两次日志,after一次、throwing一次);@AfterReturning 在有异常的情况下,不会执行到,因为没有renturn,在retrun之前就throw了。
用aspectJ 做了一次日志