aop为系统添加操作日志,注入或配置声明的方式来实现
最近做项目实现操作记录添加日志,由于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为系统添加操作日志,注入或配置声明的方式来实现的更多相关文章
- .NetCore中使用ExceptionLess 添加操作日志
上一篇文章已经扩展了日志,下面我们在结合下处理操作日志 通常我们想到操作日志 可能想到的参数可能有 模块 方法 参数内容 操作人 操作时间 操作 Ip 下面我们就来结合这些信息添加操作日志 如果要在代 ...
- 我使用Spring AOP实现了用户操作日志功能
我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到的就是在每个 ...
- .NetCore 中扩展ExceptionLess 实现链式方法添加操作日志
在使用ExceptionLess添加日志的时候,发现还是有一些写法上的个人觉得不爽的地方,比如添加Info日志 ExceptionlessClient.Default.CreateLog(source ...
- springmvc+log4j操作日志记录,详细配置
没有接触过的,先了解一下:log4j教程 部分内容来:log4j教程 感谢! 需要导入包: log包:log4j-12.17.jar 第一步:web.xml配置 <!-- log4j配置,文件路 ...
- 为table元素添加操作日志
1.为所有的元素添加函数onchange() <input id="status" value="${status}" onchange="ch ...
- spring aop切面编程实现操作日志步骤
1.在spring-mvc.xml配置文件中打开切面开关: <aop:aspectj-autoproxy proxy-target-class="true"/> 注意: ...
- Spring AOP的实现记录操作日志
适用场景: 记录接口方法的执行情况,记录相关状态到日志中. 注解类:LogTag.java package com.lichmama.spring.annotation; import java.la ...
- Yii2如何添加sql日志记录的配置信息
在使用Yii2框架的时候,常常会出现没有sql日志记录的问题.在代码里一句一句的打印sql语句也不现实.所以就要用文件记录起来. 在 config/web.php 里面的 log配置中增加如下配置 [ ...
- 新来的老大,剑走偏锋,干掉AOP做操作日志,实现后我们都惊呆了
前言 用户在操作我们系统的过程中,针对一些重要的业务数据进行增删改查的时候,我们希望记录一下用户的操作行为,以便发生问题时能及时的找到依据,这种日志就是业务系统的操作日志. 本篇我们来探讨下常见操作日 ...
随机推荐
- 10 Super Useful Tools for Web Designers
36个扁平化设计的iphone和ipad应用界面设计案例 http://designwoop.com/2014/04/36-examples-of-flat-iphone-and-ipad-appli ...
- 实用的两款jquery树形tree插件
这里有两款非常实用的jquery tree控件: (1) ------------------------------------------1.(根据一讲师总结) ---zTree: jquery. ...
- String的使用
String的常用方法 方法 说明 Anchor() 创建html锚 Concat() 把字符串连接起来 indexOf() 查找字符出现的位置 lastIndexOf() 查找最后出现字符 char ...
- 如果gen.lib.rus.ec这个电子书下载站上不去了,那就用这个吧
如果著名的gen.lib.rus.ec这个电子书下载站上不去了,那就用这个吧: 万千合集站 http://www.hejizhan.com/ 里面除了镜像索引了gen.lib.rus.ec上的所有英文 ...
- cvs vss svn和git比较
cvs vss svn和git比较 特征 CVS Git Mercurial Subversion 是否原子提交 CVS: 没有. CVS提交不是原子的 Git: 是的. 提交都是原子的 Mercur ...
- linux中的"32位"与"64位"
linux内核学习之三:linux中的"32位"与"64位" 在通用PC领域,不论是windows还是linux界,我们都会经常听到"32位" ...
- 一个快速找第k+1小的算法
public static int randomSelect(int[] A, int k) { return randomSelectDo(A, 0, A.L ...
- UML类图的常见关系1
设计模式之UML类图的常见关系(一) 本篇会讲解在UML类图中,常见几种关系: 泛化(Generalization),依赖(Dependency),关联(Association),聚合(Aggre ...
- Android开发效率的小技巧
提高eclipse使用效率(二) 提高Android开发效率的小技巧 XML文件的代码提示 adt中也有xml文件的代码提示,为了让提示来的更加猛烈,我们还要设置一下 打开eclipse - Wi ...
- 使用brew安装软件
使用brew安装软件 brew 又叫Homebrew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件, 只需要一个命令, 非常方便 brew类似ubuntu系统下的apt- ...