一、配置文件(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();
}