最近做项目实现操作记录添加日志,由于aop这两种实现方式各有优缺点,所以都实现了一下以后根据具体业务选择。

1实现方式一注入:

1.1首先在xml中开启aop注入,需要引入的包此处省略,可百度自己查找。

<aop:aspectj-autoproxy />

1.2添加链接点

package com.oasis.wyvern.res.service.base.logService;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysSecureServiceLog {
String description() default "";
}

1.3添加切入点,可以添加多个切入点同理也可添加多个链接点

package com.oasis.wyvern.res.service.base.logService;

import com.oasis.wyvern.res.common.biz.enums.base.type.ActionType;
import com.oasis.wyvern.res.common.biz.enums.base.type.ServiceAopType;
import com.oasis.wyvern.res.common.biz.vo.record.oplog.BizOpLogVo;
import com.oasis.wyvern.res.dao.biz.record.oplog.SecureOpLogDao;
import com.oasis.wyvern.res.model.base.context.secure.SecurityContextHolder;
import com.oasis.wyvern.res.model.biz.record.oplog.SecureOpLog;
import com.oasis.wyvern.res.service.base.record.oplog.BizOpLogService;
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 javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Arrays; @Aspect
@Component
public class Aop2Log {
private static final Logger logger = LoggerFactory.getLogger(Aop2Log.class);
@Resource
private BizOpLogService bizOpLogVoService; @Resource
private SecureOpLogDao secureOpLogDao;
/**
* 用户Service层切点
*/
@Pointcut("@annotation(com.oasis.wyvern.res.service.base.logService.ServiceLog)")
public void serviceAspect() {
} /**
* 系统安全层面切入点
*/
@Pointcut("@annotation(com.oasis.wyvern.res.service.base.logService.SysSecureServiceLog)")
public void sysSecureServiceAspect() {
} /**
* 用户service
* @param point
*/
@AfterReturning("serviceAspect()")
public void doAfter2Service(JoinPoint point){
try {
String actor ="";
if(SecurityContextHolder.getContext().getUser()!=null){
actor = SecurityContextHolder.getContext().getUser().getLoginName();
}
String method = point.getSignature().getName();
String entity = point.getTarget().getClass().getSimpleName();
String args = getAvailableArgs(point.getArgs());
BizOpLogVo bizOpLogVo = new BizOpLogVo();
bizOpLogVo.setActor(actor);
bizOpLogVo.setEntityType(entity.replace("ServiceImpl",""));
bizOpLogVo.setAction(methodType(method));
bizOpLogVo.setUdf1(args.length()>200?args.substring(0,200):args);
bizOpLogVo.setUdf2(method);
bizOpLogVo.setUdf3(getServiceMthodDescription(point,"ServiceLog"));
bizOpLogVoService.createBizOpLog(bizOpLogVo);
} catch (Exception e) {
logger.error("日志类异常");
logger.error(e.getMessage());
}
} /**
* 用户操作异常
* @param jp
* @param e
* @throws Exception
*/
@AfterThrowing(pointcut = "serviceAspect()", throwing = "e")
public void afterThrowing2Service(JoinPoint jp,Throwable e) throws Exception{
logger.error("异常:"+jp.getTarget().getClass().getName()+"."+jp.getSignature().getName());
logger.error(e.getMessage());
} /**
* 系统服务层操作
* @param point
*/
@AfterReturning("sysSecureServiceAspect()")
public void doAfter2Sys(JoinPoint point){
try {
String actor ="";
if(SecurityContextHolder.getContext().getUser()!=null){
actor = SecurityContextHolder.getContext().getUser().getLoginName();
}
String method = point.getSignature().getName();
String entity = point.getTarget().getClass().getSimpleName();
String args = getAvailableArgs(point.getArgs());
SecureOpLog secureOpLog = new SecureOpLog();
secureOpLog.setActor(actor);
secureOpLog.setEntityType(entity.replace("ServiceImpl",""));
secureOpLog.setAction(methodType(method));
secureOpLog.setUdf1(args.length()>200?args.substring(0,200):args);
secureOpLog.setUdf2(method);
secureOpLog.setUdf3(getServiceMthodDescription(point,"SysSecureServiceLog"));
secureOpLogDao.insert(secureOpLog);
} catch (Exception e) {
logger.error("日志类异常");
logger.error(e.getMessage());
}
} //在方法抛出异常是拦截
@AfterThrowing(pointcut = "sysSecureServiceAspect()", throwing = "e")
public void afterThrowing2Sys(JoinPoint jp,Throwable e) throws Exception{
logger.error("异常:"+jp.getTarget().getClass().getName()+"."+jp.getSignature().getName());
logger.error(e.getMessage());
} private ActionType methodType(String method){
method = method.toLowerCase();
if(method.contains("create")||method.contains("insert")||method.contains("save")){
return ActionType.CREATE;
}else if(method.contains("delete")){
return ActionType.DELETE;
}else if(method.contains("edit")||method.contains("update")){
return ActionType.UPDATE;
}else if(method.contains("frozen")){
return ActionType.FROZEN;
}else if(method.contains("unfrozen")) {
return ActionType.UNFROZEN;
}
else {
return ActionType.SEARCH;
}
} private String getAvailableArgs(Object [] args){
String strArgs = Arrays.toString(args);
String []params= strArgs.split(",");
String argsStr="";
for (String arg:params){
if(arg.contains("[")&&!arg.endsWith(">")){
argsStr = arg.substring(arg.lastIndexOf("["));
}else if(!arg.contains("[")&&!arg.endsWith(">")){
argsStr+=","+arg;
}
}
return argsStr;
} private String getServiceMthodDescription(JoinPoint joinPoint ,String which)
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) {
if(which.equals(ServiceAopType.ServiceLog.toString())) {
description = method.getAnnotation(ServiceLog.class).description();
}else if(which.equals(ServiceAopType.SysSecureServiceLog.toString())){
description = method.getAnnotation(SysSecureServiceLog.class).description();
}
break;
}
}
}
return description;
}
}

1.4在具体的方法上需要时添加链接点

    @Override
@SysSecureServiceLog(description= "delete user")
public int deleteUser(Long userId){
int res = userDao.delete(userId);
associateDao.deleteByAssoc(AssociateTable.ROLE_USER,userId);
return res;
}

2方式二通过xml声明配置实现:

2.1首先在xml配置如下:因为考虑到日志保存在操作异常或者事务回滚的情况下 操作日志不需要写入数据库,或者也需要回滚,故用了 配置的order顺序来解决。

<!--添加操作日志-->
<bean id = "logs" class="com.oasis.wyvern.res.service.base.logService.Aop2Log"/>
<aop:config >
<aop:aspect ref="logs" order="3">
<!-- 定义切入点 -->
<!-- aop包下的所有以Service结尾的类的方法 -->
<aop:pointcut id="doMethod"
expression="(execution(* com.oasis.wyvern.res.service.biz..*Service.save*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.create*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.insert*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.update*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.change*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.lock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.unLock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.reset*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.delete*(..)) )" />
<aop:after-returning method="doAfter" pointcut-ref="doMethod"/>
</aop:aspect>
</aop:config>
<!--异常时-->
<aop:config>
<aop:aspect ref="logs" order="1">
<aop:pointcut id="throwinglog"
expression="(execution(* com.oasis.wyvern.res.service.biz..*Service.save*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.create*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.insert*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.update*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.change*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.lock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.unLock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.reset*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.delete*(..)) )" />
<aop:after-throwing pointcut-ref="throwinglog" throwing="e" method="afterThrowing"/>
</aop:aspect>
</aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--事务回滚-->
<aop:config>
<aop:pointcut id="serviceMethods"
expression="(execution(* com.oasis.wyvern.res.service.biz..*Service.save*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.create*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.insert*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.update*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.change*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.lock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.unLock*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.reset*(..)) or
execution(* com.oasis.wyvern.res.service.biz..*Service.delete*(..)) )"
/>
<aop:advisor advice-ref="txAdvice"
pointcut-ref="serviceMethods" order="2"/>
</aop:config>

2.2包路径图,别把切入点的类添加到连接点扫描中:execution表达式可百度,根据业务需要配置不同的拦截规则。

2.3切入点代码

package com.oasis.wyvern.res.service.base;

import com.oasis.wyvern.res.common.biz.enums.base.type.ActionType;
import com.oasis.wyvern.res.common.biz.vo.record.oplog.BizOpLogVo;
import com.oasis.wyvern.res.model.base.context.secure.SecurityContextHolder;
import com.oasis.wyvern.res.service.base.record.oplog.BizOpLogService;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import java.util.Arrays; public class Aop2Log {
private static final Logger logger = LoggerFactory.getLogger(Aop2Log.class);
@Autowired
private BizOpLogService bizOpLogVoService;
public void doAfter(JoinPoint point){
String actor ="";
if(SecurityContextHolder.getContext().getUser()!=null){
actor = SecurityContextHolder.getContext().getUser().getLoginName();
}
String method = point.getSignature().getName();
String entity = point.getTarget().getClass().getSimpleName();
String args = getAvailableArgs(Arrays.toString(point.getArgs()));
BizOpLogVo bizOpLogVo = new BizOpLogVo();
bizOpLogVo.setActor(actor);
bizOpLogVo.setEntityType(entity.replace("ServiceImpl",""));
bizOpLogVo.setAction(methodType(method));
bizOpLogVo.setUdf1(args.length()>200?args.substring(0,200):args);
bizOpLogVo.setUdf2(method);
bizOpLogVoService.createBizOpLog(bizOpLogVo);
} //在方法抛出异常是拦截
public void afterThrowing(JoinPoint jp,Throwable e) throws Exception{
logger.error("异常:"+jp.getTarget().getClass().getName()+"."+jp.getSignature().getName());
logger.error(e.getMessage());
} private ActionType methodType(String method){
method = method.toLowerCase();
if(method.contains("create")||method.contains("insert")||method.contains("save")){
return ActionType.CREATE;
}else if(method.contains("delete")){
return ActionType.DELETE;
}else if(method.contains("edit")||method.contains("update")){
return ActionType.UPDATE;
}else if(method.contains("frozen")){
return ActionType.FROZEN;
}else if(method.contains("unfrozen")) {
return ActionType.UNFROZEN;
}
else {
return ActionType.SEARCH;
}
} private String getAvailableArgs(String args){
String []params= args.split(",");
String argsStr="";
for (String arg:params){
if(arg.contains("[")&&!arg.endsWith(">")){
argsStr = arg.substring(arg.lastIndexOf("["));
}else if(!arg.contains("[")&&!arg.endsWith(">")){
argsStr+=","+arg;
}
}
return argsStr;
}
}

好了,到此为止两种方法完全介绍完整。

aop为系统添加操作日志,注入或配置声明的方式来实现的更多相关文章

  1. .NetCore中使用ExceptionLess 添加操作日志

    上一篇文章已经扩展了日志,下面我们在结合下处理操作日志 通常我们想到操作日志 可能想到的参数可能有 模块 方法 参数内容 操作人 操作时间 操作 Ip 下面我们就来结合这些信息添加操作日志 如果要在代 ...

  2. 我使用Spring AOP实现了用户操作日志功能

    我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到的就是在每个 ...

  3. .NetCore 中扩展ExceptionLess 实现链式方法添加操作日志

    在使用ExceptionLess添加日志的时候,发现还是有一些写法上的个人觉得不爽的地方,比如添加Info日志 ExceptionlessClient.Default.CreateLog(source ...

  4. springmvc+log4j操作日志记录,详细配置

    没有接触过的,先了解一下:log4j教程 部分内容来:log4j教程 感谢! 需要导入包: log包:log4j-12.17.jar 第一步:web.xml配置 <!-- log4j配置,文件路 ...

  5. 为table元素添加操作日志

    1.为所有的元素添加函数onchange() <input id="status" value="${status}" onchange="ch ...

  6. spring aop切面编程实现操作日志步骤

    1.在spring-mvc.xml配置文件中打开切面开关: <aop:aspectj-autoproxy proxy-target-class="true"/> 注意: ...

  7. Spring AOP的实现记录操作日志

    适用场景: 记录接口方法的执行情况,记录相关状态到日志中. 注解类:LogTag.java package com.lichmama.spring.annotation; import java.la ...

  8. Yii2如何添加sql日志记录的配置信息

    在使用Yii2框架的时候,常常会出现没有sql日志记录的问题.在代码里一句一句的打印sql语句也不现实.所以就要用文件记录起来. 在 config/web.php 里面的 log配置中增加如下配置 [ ...

  9. 新来的老大,剑走偏锋,干掉AOP做操作日志,实现后我们都惊呆了

    前言 用户在操作我们系统的过程中,针对一些重要的业务数据进行增删改查的时候,我们希望记录一下用户的操作行为,以便发生问题时能及时的找到依据,这种日志就是业务系统的操作日志. 本篇我们来探讨下常见操作日 ...

随机推荐

  1. gof设计模式回顾

    gof23根据讲师学习笔记回顾: 1.gof:Gang of Four;叫grasp更具有针对性,解决具体的问题; ---------------------总共分为三大类: ---------创建型 ...

  2. 手机网站keyup解决方案

    模糊搜索keyup无效,解决方案如下 //手机网站解决keyup的方法 $(function () { $('#repairsearch').bind('focus', filter_time); } ...

  3. 职责链模式实例(C#)

    下面是使用指责链模式的一个具体的实例,可以方便的理解指责链模式. 其实指责链简单的来说,就是把一个指责的流程定义出来,像一条链路一样,每一个结点有自己的处理范围,若不能处理,则传到自己的引用的下一个结 ...

  4. JavaScript插件——弹出框

    (JavaScript插件——弹出框) 前言 阅读之前您也可以到Bootstrap3.0入门学习系列导航中进行查看http://www.cnblogs.com/aehyok/p/3404867.htm ...

  5. Bootstrap3.0学习第六轮(表单)

    Bootstrap3.0学习第六轮(表单) 前言 阅读之前您也可以到Bootstrap3.0入门学习系列导航中进行查看http://www.cnblogs.com/aehyok/p/3404867.h ...

  6. ResolveUrl in ASP.NET - The Perfect Solution

    原文:ResolveUrl in ASP.NET - The Perfect Solution If you are looking for ResolveUrl outside of Page/Co ...

  7. 【Bootstrap】Bootstrap Datepicker使用

    插件:http://url.cn/V4S8w4 1.添加样式和引用JS文件 <link href="CSS/bootstrap-datetimepicker.css" rel ...

  8. [google面试CTCI] 2-0.链表的创建

    创建链表.往链表中插入数据.删除数据等操作,以单链表为例. 1.使用C语言创建一个链表: typedef struct nd{ int data; struct nd* next; } node; / ...

  9. MongoDB学习2

    MongoDB学习(翻译2) C#驱动之LINQ教程 介绍 本教程涵盖了1.8发布版本对linq查询的支持. 开始本教程之前,你应该至少阅读下C#驱动教程关于C#驱动的介绍 快速开始 首先,添加下面命 ...

  10. BizTalk 2010/2013 EDI B2B

    BizTalk 2010/2013 EDI B2B项目实践(1)   BizTalk 2010/2013 EDI B2B项目实践(1) BizTalk开发标准EDI B2B是件非常容易的事情,但对于初 ...