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;
    }
}

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

时间: 2024-07-30 20:55:22

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

Linux 系统添加操作记录--命令审计功能

**Linux 系统添加操作记录审计 1.mkdir -p /usr/local/domob/records/ chmod 777 /usr/local/domob/records/ chmod +t /usr/local/domob/records/ 2.vi /etc/profile 在最后添加下面的代码 if [ ! -d /usr/local/domob/records/${LOGNAME} ] then mkdir -p /usr/local/domob/records/${LOGNA

linux系统添加swap虚拟内存与删除配置方法

兄弟连Linux培训教程 linux系统添加swap虚拟内存与删除配置(www.lampbrother.net) 1.swap概述 Swap分区,即交换区,Swap空间的作用可简单描述为:当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复保存的数据到内存中.这样,系统总是在物理内存不够时,才进行Swap交换. 其实

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

没有接触过的,先了解一下:log4j教程 部分内容来:log4j教程 感谢! 需要导入包: log包:log4j-12.17.jar 第一步:web.xml配置 <!-- log4j配置,文件路径,因为是跟随项目启动 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.xml</param-value>

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

在使用Yii2框架的时候,常常会出现没有sql日志记录的问题.在代码里一句一句的打印sql语句也不现实.所以就要用文件记录起来. 在 config/web.php 里面的 log配置中增加如下配置 [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning','info'], 'logVars'=>[], //表示以yii\db\或者app\models\开头的分类都会写入这个文件 'categories'=>

spring/spirng boot添加fluent日志-aop

此项目以aop的形式添加fluent 日志 sample介绍 spring-mvc-aop-helloworld 为spring mvc aop condition toolcommontest 为spring boot aop condition 0.将项目打包上传maven私服 1.spring boot和spring 添加依赖 <dependency> <groupId>com.taiyue.tool.common</groupId> <artifactId

SSH基于Hibernate eventListener 事件侦听器的操作日志自动保存到数据库

在spring xml配置文件中添加配置,包含:model.listener 在model中增加需要写入数据库对应表的model 在auditLog.xml配置文件中配置自己项目中,需要进行日志记录的model类shortName,以及相关属性. 相关代码如下: 首先spring xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframew

开源 java CMS - FreeCMS2.2 操作日志

原文地址:http://javaz.cn/site/javaz/site_study/info/2015/17793.html 项目地址:http://www.freeteam.cn/ 操作日志 查看系统所有操作日志. 提示:admin可以查看所有日志,非admin用户只可查看自己的操作日志. 从左侧管理菜单点击操作日志进入.

[实战]MVC5+EF6+MySql企业网盘实战(21)——网盘操作日志

写在前面 上篇文章介绍了一个bootstrap的分页插件,这篇将弄一个完整的例子,就以日志分页为例说明如何请求服务端然后进行分页. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企业网盘实战(1) [实战]MVC5+EF6+MySql企业网盘实战(2)——用户注册 [实战]MVC5+EF6+MySql企业网盘实战(3)——验证码 [实战]MVC5+EF6+MySql企业网盘实战(4)——上传头像 [Bootstrap]modal弹出

Spring aop 记录操作日志 Aspect

前几天做系统日志记录的功能,一个操作调一次记录方法,每次还得去收集参数等等,太尼玛烦了.在程序员的世界里,当你的一个功能重复出现多次,就应该想想肯定有更简单的实现方法.于是果断搜索各种资料,终于搞定了,现在上代码 环境: SpringMvc + myBatis jar包 :      (aspect.jar也行,我原来项目中有,便没有替换了) 1.自定义注解类   ArchivesLog.java(获取Controller描述用的) package com.noahwm.uomp.archive