一、配置文件(springMVC-servlet.xml)
<mvc:annotation-driven/>
<!-- 設置使用註解的類所在的包 -->
<context:component-scan base-package="com.mapuni.controller.*"/>
<!-- 註解方式實現aop -->
<aop:aspectj-autoproxy/>
<bean id="systemLogAspect" class="com.mapuni.spring.logaop.SystemLogAspect"></bean>
二、註解
package com.mapuni.spring.logaop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日誌切面註解
* @author chenla
*
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodOperateLog {
/** 要執行的操作類型比如:add操作 **/
public String operationType() default "";
/** 要執行的具體操作比如:添加用戶 **/
public String operationName() default "";
/**操作的模塊**/
public String moduleName() default "";
}
三、切面
package com.mapuni.spring.logaop;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.mapuni.entity.oa.LogManage.XtRzSql;
import com.mapuni.security.user.MapuniUserDetails;
import com.mapuni.service.oa.LogManage.LogService;
import com.mapuni.utils.IpAddressUtil;
import com.mapuni.utils.StringUtil;
/**
* 日誌切面實現
*/
@Component
@Aspect
public class SystemLogAspect {
@Autowired
private LogService logService;
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);
public SystemLogAspect() {
System.out.println("Aop");
}
/**
* Controller層切點
*/
//這種切點是根據註解配在那個方法就對那個方法作用
@Pointcut("@annotation(com.mapuni.spring.logaop.MethodOperateLog)")
//這種切點配置方式是根據方法的名字來決定切點的作用方法
//@Pointcut("execution(* com.mapuni.controller.oa.SystemOperation.*(..))")
public void controllerAspect() { }
/**
* 前置通知,用於攔截Controller層記錄用戶的操作
* @param jp 切點
*/
//@Before("controllerAspect()")
public void doBefore(JoinPoint jp){
System.out.println("==========執行controller前置通知===============");
if(logger.isInfoEnabled()){
logger.info("before " + jp);
}
}
/**
* 配置controller環繞通知,使用在方法aspect()上註冊的切入點
*/
//@Around("controllerAspect()")
public void around(JoinPoint joinPoint){
System.out.println("==========開始執行controller環繞通知===============");
long start = System.currentTimeMillis();
try {
((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
if(logger.isInfoEnabled()){
logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
}
System.out.println("==========結束執行controller環繞通知===============");
} catch (Throwable e) {
long end = System.currentTimeMillis();
if(logger.isInfoEnabled()){
logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
}
}
}
/**
* 後置通知,用於攔截Controller層記錄用戶的操作
* @param joinPoint
*/
@After("controllerAspect()")
public void after(JoinPoint joinPoint){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
Calendar ca = Calendar.getInstance();
String operDate = df.format(ca.getTime());
//得到ip地址
String ip = IpAddressUtil.getIp(request);
try {
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 operationType = "";
String operationName = "";
String moduleName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(MethodOperateLog.class).operationType();
operationName = method.getAnnotation(MethodOperateLog.class).operationName();
moduleName = method.getAnnotation(MethodOperateLog.class).moduleName();
break;
}
}
}
//*================控制檯輸出===============*//
System.out.println("========controller後置通知開始=============");
String packages = joinPoint.getThis().getClass().getName();
// 如果是CGLIB動態生成的類
if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) {
try {
packages = packages.substring(0, packages.indexOf("$$"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
//被監測方法的request對象
HttpServletRequest req = (HttpServletRequest) arguments[0];
//*==============數據庫日誌===========*//
XtRzSql sysLog = new XtRzSql();
//主鍵
sysLog.setPkid(StringUtil.getUUID_32());
//用戶id
sysLog.setUserid(MapuniUserDetails.getCurrentUserId());
//用戶名
String username = MapuniUserDetails.getCurrentUser().getUsername();
sysLog.setUsername(username);
//操作時間
sysLog.setKssj(operDate);
//ip地址
sysLog.setIpaddress(ip);
//方法名
sysLog.setMethodname(packages + "." + methodName);
//操作模塊名字
sysLog.setModulename(moduleName);
/**
* 版本管理模塊
*/
if("刪除操作".equals(operationType)){
sysLog.setOperatingcontent("刪除版本:版本id爲"+req.getParameter("id"));
}
//保存數據庫
logService.saveSysLog(sysLog);
System.out.println("=========controller後置通知結束================");
} catch (Exception e) {
//記錄本地異常日誌
logger.error("===後置通知異常===");
logger.error("異常信息:{}", e.getMessage());
}
}
//配置後置返回通知,使用在方法aspect()上註冊的切入點
//@AfterReturning("controllerAspect()")
public void afterReturn(JoinPoint joinPoint){
System.out.println("=====執行controller後置返回通知======");
if(logger.isInfoEnabled()){
logger.info("afterReturn " + joinPoint);
}
}
/**
* 異常通知 用於攔截記錄異常日誌
* @param joinPoint
* @param e
*/
//@AfterThrowing(pointcut = "controllerAspect()", throwing="e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
Calendar ca = Calendar.getInstance();
String operDate = df.format(ca.getTime());
//得到ip地址
String ip = IpAddressUtil.getIp(request);
//得到用戶id
String userid = MapuniUserDetails.getCurrentUserId();
// String params = "";
// if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
// for ( int i = 0; i < joinPoint.getArgs().length; i++) {
// params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";";
// }
// }
try {
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 operationType = "";
String operationName = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
operationType = method.getAnnotation(MethodOperateLog.class).operationType();
operationName = method.getAnnotation(MethodOperateLog.class).operationName();
break;
}
}
}
String packages = joinPoint.getThis().getClass().getName();
// 如果是CGLIB動態生成的類
if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) {
try {
packages = packages.substring(0, packages.indexOf("$$"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
/*========控制檯輸出=========*/
System.out.println("=====異常通知開始=====");
System.out.println("異常代碼:" + e.getClass().getName());
System.out.println("異常信息:" + e.getMessage());
System.out.println("異常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);
System.out.println("方法描述:" + operationName);
System.out.println("請求人id:" + userid);
System.out.println("請求IP:" + ip);
// System.out.println("請求參數:" + params);
//*==============數據庫日誌===========*//
XtRzSql sysLog = new XtRzSql();
sysLog.setPkid(StringUtil.getUUID_32());
sysLog.setUserid(MapuniUserDetails.getCurrentUserId());
String username = request.getParameter("userName");
sysLog.setUsername(username);
sysLog.setKssj(operDate);
sysLog.setIpaddress(ip);
sysLog.setMethodname(packages + "." + methodName);
//TODO
sysLog.setModulename("");
//保存數據庫
logService.saveSysLog(sysLog);
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);
}
}
四、添加註解的測試
@RequestMapping(value = "/deleteInspection")
@MethodOperateLog(moduleName="設置——>運維管理——>版本管理",operationType="刪除操作",operationName="刪除服務器版本")
public void deleteInspection(HttpServletRequest request, PrintWriter pw) {
try {
String id = request.getParameter("id");
int count = inspectionService.deleteInspection(id);
if (count > 0) {
pw.print(GlobalConstants.RESULT_PRINT_SUCCESS);
} else {
pw.print(GlobalConstants.RESULT_PRINT_ERROR);
}
} catch (Exception e) {
e.printStackTrace();
pw.print(GlobalConstants.RESULT_PRINT_ERROR);
logger.error(e.getMessage());
}
pw.flush();
pw.close();
}