AOP自定义注解实现项目日志操作管理

本人是spring boot项目,相关注解依赖也已经提前导入OK,下面是实现注解需要的依赖。
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
首先需要创建一个实体类:

`package com.abcd.resdir.system.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.Date;
import com.wondersgroup.resdir.common.annotation.Excel;
import com.wondersgroup.resdir.common.core.domain.BaseEntity;

/**
 * 操作日志记录表 oper_log
 * 
 * @author wondersgroup
 */
public class SysOperLog extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 日志主键 */
    @Excel(name = "操作序号")
    private Long operId;

    /** 操作模块 */
    @Excel(name = "操作模块")
    private String title;

    /** 业务类型(0其它 1新增 2修改 3删除) */
    @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据")
    private Integer businessType;

    /** 业务类型数组 */
    private Integer[] businessTypes;

    /** 请求方法 */
    @Excel(name = "请求方法")
    private String method;

    /** 操作类别(0其它 1后台用户 2手机端用户) */
    @Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户")
    private Integer operatorType;

    /** 操作人员 */
    @Excel(name = "操作人员")
    private String operName;

    /** 部门名称 */
    @Excel(name = "部门名称")
    private String deptName;

    /** 请求url */
    @Excel(name = "请求地址")
    private String operUrl;

    /** 操作地址 */
    @Excel(name = "操作地址")
    private String operIp;

    /** 操作地点 */
    @Excel(name = "操作地点")
    private String operLocation;

    /** 请求参数 */
    @Excel(name = "请求参数")
    private String operParam;

    /** 操作状态(0正常 1异常) */
    @Excel(name = "状态", readConverterExp = "0=正常,1=异常")
    private Integer status;

    /** 错误消息 */
    @Excel(name = "错误消息")
    private String errorMsg;

    /** 操作时间 */
    @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date operTime;

    public Long getOperId()
    {
        return operId;
    }

    public void setOperId(Long operId)
    {
        this.operId = operId;
    }

    public String getTitle()
    {
        return title;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public Integer getBusinessType()
    {
        return businessType;
    }

    public void setBusinessType(Integer businessType)
    {
        this.businessType = businessType;
    }

    public Integer[] getBusinessTypes()
    {
        return businessTypes;
    }

    public void setBusinessTypes(Integer[] businessTypes)
    {
        this.businessTypes = businessTypes;
    }

    public String getMethod()
    {
        return method;
    }

    public void setMethod(String method)
    {
        this.method = method;
    }

    public Integer getOperatorType()
    {
        return operatorType;
    }

    public void setOperatorType(Integer operatorType)
    {
        this.operatorType = operatorType;
    }

    public String getOperName()
    {
        return operName;
    }

    public void setOperName(String operName)
    {
        this.operName = operName;
    }

    public String getDeptName()
    {
        return deptName;
    }

    public void setDeptName(String deptName)
    {
        this.deptName = deptName;
    }

    public String getOperUrl()
    {
        return operUrl;
    }

    public void setOperUrl(String operUrl)
    {
        this.operUrl = operUrl;
    }

    public String getOperIp()
    {
        return operIp;
    }

    public void setOperIp(String operIp)
    {
        this.operIp = operIp;
    }

    public String getOperLocation()
    {
        return operLocation;
    }

    public void setOperLocation(String operLocation)
    {
        this.operLocation = operLocation;
    }

    public String getOperParam()
    {
        return operParam;
    }

    public void setOperParam(String operParam)
    {
        this.operParam = operParam;
    }

    public Integer getStatus()
    {
        return status;
    }

    public void setStatus(Integer status)
    {
        this.status = status;
    }

    public String getErrorMsg()
    {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg)
    {
        this.errorMsg = errorMsg;
    }

    public Date getOperTime()
    {
        return operTime;
    }

    public void setOperTime(Date operTime)
    {
        this.operTime = operTime;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("operId", getOperId())
            .append("title", getTitle())
            .append("businessType", getBusinessType())
            .append("businessTypes", getBusinessTypes())
            .append("method", getMethod())
            .append("operatorType", getOperatorType())
            .append("operName", getOperName())
            .append("deptName", getDeptName())
            .append("operUrl", getOperUrl())
            .append("operIp", getOperIp())
            .append("operLocation", getOperLocation())
            .append("operParam", getOperParam())
            .append("status", getStatus())
            .append("errorMsg", getErrorMsg())
            .append("operTime", getOperTime())
            .toString();
    }
}

这就是要插入到数据库的实体类,用来接收操作的信息。
`下面是自定义的注解类。

package com.abcd.resdir.Annotation;


import java.lang.annotation.*;

/**
 * 自定义日志注解
 * @author liuyazhuang
 *
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
/**
 * 首先是被调用的方法的名称,其默认值是“”
 * @return
 */
String value() default "";

/**
 * 要执行的具体操作比如:菜单名称
 */
    String menuName() default "";

}`

然后就是我们主要的切面类:

package com.abcd.resdir.Annotation;

import com.wondersgroup.resdir.common.core.domain.AjaxResult;
import com.wondersgroup.resdir.framework.bean.CurrentUser;
import com.wondersgroup.resdir.framework.util.ShiroUtils;
import com.wondersgroup.resdir.system.domain.SysOperLog;
import com.wondersgroup.resdir.system.service.ISysOperLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.regex.Pattern;

@Aspect
@Component
public class SystemLogAspect {
    

   @Resource
    private ISysOperLogService systemLogService;

    //Controller层切点
    @Pointcut("@annotation(com.abcd.resdir.Annotation.SysLog)")


      public void controllerAspect() {
    }

    @AfterReturning(returning="ret", pointcut="controllerAspect()")
    public void afterReturn(JoinPoint joinPoint,Object ret) throws Throwable{
        System.out.println("=====执行controller后置返回通知=====");
        //保存日志
        saveSysLog(joinPoint,ret);
    }

    /**\
     * /日志处理方法
     * @param joinPoint
     * @param
     */
    private void saveSysLog(JoinPoint joinPoint,Object ret) {
        try{
        // 获取当前操作的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysOperLog log = new SysOperLog();
        SysLog syslog = method.getAnnotation(SysLog.class);
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        //set方法名
        Object[] args = joinPoint.getArgs();
        String params = "";
        StringBuffer stringBuffer = new StringBuffer();
        if(args.length > 0 ){
            for (int i = 0 ; i < args.length; i++){
                params = args[i].toString();
                stringBuffer.append(params);
            }
        //参数
        log.setOperParam(stringBuffer.toString());
        }
        //方法名
        log.setMethod(methodName + "()");
        Class targetClass = Class.forName(className);
        Method[] methods = targetClass.getMethods();
            for (Method me : methods) {
               if (method.getName().equals(methodName)) {
                    Class[] clazzs = me.getParameterTypes();
                    if (clazzs.length == args.length) {
                        //获取注解上的参数
                        log.setBusinessType(getOperBusinessType(syslog.value()));
                        log.setTitle(syslog.menuName());
                        break;
                    }
               }
            }
        // 获取 ip 地址
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //set地址IP
        log.setOperIp(request.getRemoteAddr());
        //set请求URL
        log.setOperUrl(request.getServletPath());
        CurrentUser user = ShiroUtils.getSysUser();
        if( user != null){
            log.setOperName(user.getUserName());
        }

        AjaxResult ajaxResult = (AjaxResult) ret;
        if(ajaxResult.getCode() == 0){
            log.setStatus(0);
        }else {
            log.setStatus(1);
            log.setErrorMsg(ajaxResult.getMsg());
        }
        log.setOperatorType(0);
        log.setOperTime(new Date());
        // 保存日志
        systemLogService.insertOperlog(log);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public static Integer getOperBusinessType(String content){
        String add = ".*新增.*";
        String update = ".*修改.*";
        String delete = ".*删除.*";

        if(Pattern.matches(add, content)){ return  1; }
        if(Pattern.matches(update, content)){ return  2; }
        if(Pattern.matches(delete, content)){ return  3; }
        else { return  0; }
    }
}

上面只写了一个@AfterReturning注解,他的作用是在使用注解的controller方法在return后才执行,还有其他的@Before,@After之类的都是跟这个差不多的原理,除了@around,方法的参数类型是ProceedingJoinPoint而不是JoinPoint。
接下里只要在controller里的方法使用此注解即可。

`@RequestMapping(value = "/batchSetLevel" ,method = RequestMethod.POST )
    @ResponseBody
    @SysLog(value = "批量修改用户级别",menuName = "用户管理")
    public AjaxResult batchSetLevel(@RequestBody  Map<String ,Object> map){
        return userService.batchSetLevel(map);
    }

    @RequestMapping(value = "/setBatchAuthCode" ,method = RequestMethod.POST )
    @ResponseBody
     @SysLog(value = "批量修改用户授权码",menuName = "用户管理")
public AjaxResult setBatchAuthCode(@RequestBody  Map<String ,Object> map){
    return userService.setBatchAuthCode(map);
}`



本项目使用的是mybatis的ORM框架。所以插入方法在XML中,没有贴出啦。
执行完操作后控制台输出的信息,表示成功插入操作日志:
18:45:43.788 [http-nio-8090-exec-13] DEBUG c.w.r.b.m.A.updateUserStatusZero - [debug,159] - <==    Updates: 5
=====执行controller后置返回通知=====
18:45:43.789 [http-nio-8090-exec-13] DEBUG c.w.r.s.m.S.insertOperlog - [debug,159] - ==>  Preparing: insert into SYS_OPER_LOG (OPER_ID, TITLE, BUSINESS_TYPE, METHOD, OPERATOR_TYPE, OPER_NAME, DEPT_NAME, OPER_URL, OPER_IP, OPER_LOCATION,OPER_PARAM,STATUS,ERROR_MSG,OPER_TIME) values (SEQ_SYS_OPER_LOG.NEXTVAL,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
18:45:43.790 [http-nio-8090-exec-13] DEBUG c.w.r.s.m.S.insertOperlog - [debug,159] - ==> Parameters: 用户管理(String), 1(Integer), getUserListForSys()(String), 0(Integer), 单点测试(String), null, /User/sysUser(String), 127.0.0.1(String), null, null, 0(Integer), null, 2019-08-26 18:45:43.788(Timestamp)
18:45:43.792 [http-nio-8090-exec-13] DEBUG c.w.r.s.m.S.insertOperlog - [debug,159] - <==    Updates: 1
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值