Spring AOP自定义注解实现系统日志记录管理
2017-05-08 17:44
871 查看
前言
最近有点忙,已经很长时间没写博客,有点惭愧。前几天有个需求:记录管理平台操作的日志(PC端)。今天刚好有时间就整理记录下来,供大家学习探讨。bug
网上很多例子都是大同小异,笔者发现有个坑:譬如说,你的切点是在业务控制层(Controller),那么无论是不是日志自定义注解,都会执行日志处理方法。这也是我为何写这篇博客原因之一。代码
自定义注解类:LogAnnotation.javapackage com.kilomob.powernetwork.managerweb.annotation; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; /** * * @Description * @author fengjk * @date 2017-4-25 下午8:28:45 */ @Target({ ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface LogAnnotation { /** 要执行的具体操作比如:添加用户 **/ public String operationName() default ""; }日志拦截处理类:
package com.kilomob.powernetwork.managerweb.annotation; import java.lang.reflect.Method; import java.net.InetAddress; import java.util.Arrays; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; 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.alibaba.fastjson.JSONObject; import com.kilomob.powernetwork.common.service.permission.SysLogService; /** * * @Description 日志记录 * @author fengjk * @date 2017-5-2 下午3:24:37 */ @Aspect @Component public class SystemLogAspect{ // 注入Service用于把日志保存数据库 @Autowired SysLogService logService; private static final Logger logger = LoggerFactory .getLogger(SystemLogAspect.class); private Date beforeDate; private Date afterDate; /** * * @Description 前置通知 * @author fengjk * @date 2017-5-23 下午6:22:07 */ public void beforePointCut(JoinPoint joinPoint){ beforeDate = new Date(); } /** * * @Description 后置通知,记录用户在Controller操作记录 * @author fengjk * @date 2017-4-26 上午11:26:59 */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void afterPointCut(JoinPoint joinPoint) { try { Class[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes(); Method method = null; String methodName = joinPoint.getSignature().getName(); Class targetClass = joinPoint.getTarget().getClass(); method = targetClass.getMethod(methodName,parameterTypes); boolean hasAnnotation = method.isAnnotationPresent(LogAnnotation.class); if(hasAnnotation){ HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder .getRequestAttributes()).getRequest(); InetAddress inetAddress = InetAddress.getLocalHost(); String ip = inetAddress.getHostAddress(); // 读取session中的用户 HttpSession session = request.getSession(); String loginName = (String) session.getAttribute("loginName"); Long userId = (Long) session.getAttribute("userId"); String operationName = method.getAnnotation(LogAnnotation.class).operationName(); JSONObject paramObject = new JSONObject(); paramObject.put("account", loginName); paramObject.put("userId", userId); paramObject.put("ipAddress", ip); paramObject.put("description", operationName); paramObject.put("time", new Date()); paramObject.put("method", (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); // 前台执行操作传入参数 paramObject.put("remark", Arrays.toString(joinPoint.getArgs())); if(beforeDate != null){ afterDate = new Date(); long poor = afterDate.getTime() - beforeDate.getTime(); long day = poor / (24 * 60 * 60 * 1000); long hour = (poor / (60 * 60 * 1000) - day * 24); long min = ((poor / (60 * 1000)) - day * 24 * 60 - hour * 60); long s = (poor / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); long ms = (poor - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - s * 1000); // 执行方法耗时时间 paramObject.put("consumeTime", ms); } logService.insertSysLog(paramObject); } } catch (Exception e) { // 记录本地异常日志 logger.warn("日志记录异常信息:", e); } } }if语句hasAnnotation判断极为重要,判断拦截方法是否是自定义注解,不然踩坑就是它会拦截到所有注解的方法。SysLogService就是日志插入数据库接口类,这里就不贴代码了。
最后就是配置文件:applicationContext.xml
<!--切面,日志记录 --> <bean id="systemLogAspect" class="com.kilomob.powernetwork.managerweb.annotation.SystemLogAspect"></bean> <aop:config> <aop:aspect ref="systemLogAspect"> <aop:pointcut id="logPointCut" expression="execution(* com.kilomob.powernetwork.managerweb.controller..*.*(..))" /> <aop:before pointcut-ref="logPointCut" method="beforePointCut"/> <aop:after pointcut-ref="logPointCut" method="afterPointCut" /> </aop:aspect> </aop:config>注意:文件method方法名要和拦截类处理方法一致
引用注解,直接在需要记录操作日志(笔者记录的是新增、修改、删除操作),切入层(Controller)方法中添加,譬如:@LogAnnotation(operationName="新增用户")
总结
文章只提供核心代码,不提供Demo。一来是没时间去整理,二来有利于读者自己摸索加深影响。如有笔误,请留言相告,谢谢!欢迎加群探讨学习,QQ群:583138104
相关文章推荐
- Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- spring aop自定义注解实现日志记录
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring Aop自定义注解拦截Controller实现日志管理
- springAOP自定义注解方式实现日志管理
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- Spring AOP实现复杂的日志记录(自定义注解)
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- spring AOP自定义注解方式实现日志管理
- java SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)
- SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)