最近做项目实现操作记录添加日志,由于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. 开始DDD

    如何开始DDD(完) 连续写了两篇文章,这一篇我想是序的完结篇了.结合用户注册的例子再将他简单丰富一下.在这里只添加一个简单需求,就是用户注册成功后给用户发一封邮件.补充一下之前的代码 public ...

  2. Tomcat源码学习一

    这段时间工作不太忙,所以抽时间学习了TOMCAT, TOMCAT实际就是负责保持TCP连接传递到部署的项目中.浏览器实质就是TCP发送器.将用户的请求封装成TCP发送请求.当然格式是双方协定的.使用的 ...

  3. Lex Yacc手册

    Python Lex Yacc手册 本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不 ...

  4. [Usaco2007 Dec]宝石手镯[01背包][水]

    Description 贝茜在珠宝店闲逛时,买到了一个中意的手镯.很自然地,她想从她收集的 N(1 <= N <= 3,402)块宝石中选出最好的那些镶在手镯上.对于第i块宝石,它的重量为 ...

  5. PRML 第三章 - 线性回归

    这段时间组里在有计划地学习书籍PRML (Pattern Recognition and Machine Learning),前两天自己做了一个里面第三章linear regression的分享,这里 ...

  6. [转]Top 10 DTrace scripts for Mac OS X

    org link: http://dtrace.org/blogs/brendan/2011/10/10/top-10-dtrace-scripts-for-mac-os-x/ Top 10 DTra ...

  7. Xilinx-Zynq Linux内核源码编译过程

    本文内容依据http://www.wiki.xilinx.com网址编写,编译所用操作系统为ubuntu 14 1.交叉编译环境的安装配置 1)http://www.wiki.xilinx.com/I ...

  8. mac下安装eclipse以及python

    因为前几天刚重装了我的mac osx 系统,从昨天开始我就在安装各种软件,当我安装好破解版的myeclipse后,在我安装pydev插件的时候,虽然现实成功但是在preference中死活找不到pyd ...

  9. (翻译) Android Accounts Api使用指南

    本文翻译自Udinic的文章Write your own Android Authenticator,可能需要FQ才能阅读.这是译者目前能找到的介绍如何使用Android的Accounts Api最好 ...

  10. Bundles

    Bundles 接着在Global.asax文件的Application_Start方法中调用BundleConfig.RegisterBundles方法: protected void Applic ...