spring aop實現(使用者操作記錄,一場記錄)
第一步定義兩個註解:
Java程式碼 複製程式碼
package com.annotation;
import java.lang.annotation.*;
/**
*自定義註解 攔截Controller
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {
String description() default "";
}
package com.annotation;
import java.lang.annotation.*;
/**
*自定義註解 攔截service
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog {
String description() default "";
}
第二步建立一個切點類:
Java程式碼 複製程式碼
package com.annotation;
import com.model.Log;
import com.model.User;
import com.service.LogService;
import com.util.DateUtil;
import com.util.JSONUtil;
import com.util.SpringContextHolder;
import com.util.WebConstants;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
/**
-
切點類
-
@author tiangai
-
@since 2014-08-05 Pm 20:35
-
@version 1.0
*/
@Aspect
@Component
public class SystemLogAspect {
//注入Service用於把日誌儲存資料庫
@Resource
private LogService logService;
//本地異常日誌記錄物件
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);//Service層切點
@Pointcut("@annotation(com.annotation.SystemServiceLog)")
public void serviceAspect() {
}//Controller層切點
@Pointcut("@annotation(com.annotation.SystemControllerLog)")
public void controllerAspect() {
}/**
-
前置通知 用於攔截Controller層記錄使用者的操作
-
@param joinPoint 切點
*/
@Before(“controllerAspect()”)
public void doBefore(JoinPoint joinPoint) {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//讀取session中的使用者
User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//請求的IP
String ip = request.getRemoteAddr();
try {
//控制檯輸出=//
System.out.println("=前置通知開始=");
System.out.println(“請求方法:” + (joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
System.out.println(“方法描述:” + getControllerMethodDescription(joinPoint));
System.out.println(“請求人:” + user.getName());
System.out.println(“請求IP:” + ip);
//資料庫日誌=//
Log log = SpringContextHolder.getBean(“logxx”);
log.setDescription(getControllerMethodDescription(joinPoint));
log.setMethod((joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
log.setType(“0”);
log.setRequestIp(ip);
log.setExceptionCode(null);
log.setExceptionDetail(null);
log.setParams(null);
log.setCreateBy(user);
log.setCreateDate(DateUtil.getCurrentDate());
//儲存資料庫
logService.add(log);
System.out.println("=前置通知結束=");
} catch (Exception e) {
//記錄本地異常日誌
logger.error(“前置通知異常”);
logger.error(“異常資訊:{}”, e.getMessage());
}
}
/**
- 異常通知 用於攔截service層記錄異常日誌
- @param joinPoint
- @param e
/
@AfterThrowing(pointcut = “serviceAspect()”, throwing = “e”)
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
//讀取session中的使用者
User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
//獲取請求ip
String ip = request.getRemoteAddr();
//獲取使用者請求方法的引數並序列化為JSON格式字串
String params = “”;
if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
for (int i = 0; i < joinPoint.getArgs().length; i++) {
params += JSONUtil.toJsonString(joinPoint.getArgs()[i]) + “;”;
}
}
try {
/控制檯輸出=/
System.out.println("=異常通知開始=");
System.out.println(“異常程式碼:” + e.getClass().getName());
System.out.println(“異常資訊:” + e.getMessage());
System.out.println(“異常方法:” + (joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
System.out.println(“方法描述:” + getServiceMthodDescription(joinPoint));
System.out.println(“請求人:” + user.getName());
System.out.println(“請求IP:” + ip);
System.out.println(“請求引數:” + params);
/==資料庫日誌=/
Log log = SpringContextHolder.getBean(“logxx”);
log.setDescription(getServiceMthodDescription(joinPoint));
log.setExceptionCode(e.getClass().getName());
log.setType(“1”);
log.setExceptionDetail(e.getMessage());
log.setMethod((joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
log.setParams(params);
log.setCreateBy(user);
log.setCreateDate(DateUtil.getCurrentDate());
log.setRequestIp(ip);
//儲存資料庫
logService.add(log);
System.out.println("=異常通知結束=");
} catch (Exception ex) {
//記錄本地異常日誌
logger.error(“異常通知異常”);
logger.error(“異常資訊:{}”, ex.getMessage());
}
/記錄本地異常日誌*/
logger.error(“異常方法:{}異常程式碼:{}異常資訊:{}引數:{}”, joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
}
/**
- 獲取註解中對方法的描述資訊 用於service層註解
- @param joinPoint 切點
- @return 方法描述
- @throws Exception
*/
public static String getServiceMthodDescription(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) {
description = method.getAnnotation(SystemServiceLog.class).description();
break;
}
}
}
return description;
}
/**
- 獲取註解中對方法的描述資訊 用於Controller層註解
- @param joinPoint 切點
- @return 方法描述
- @throws Exception
*/
public static String getControllerMethodDescription(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) {
description = method.getAnnotation(SystemControllerLog.class).description();
break;
}
}
}
return description;
}
}
第三步把Controller的代理權交給cglib
-
在例項化ApplicationContext的時候需要加上
Xml程式碼 複製程式碼
aop:aspectj-autoproxy/
在呼叫Controller的時候AOP發揮作用所以在SpringMVC的配置檔案里加上
Xml程式碼 複製程式碼