spring aop实现操作日志记录

13 篇文章 0 订阅
10 篇文章 0 订阅

spring aop实现操作日志记录

        此次的目的是实现 对 controller中的方法执行情况进行记录,记录的有方法执行时间,操作人,请求的路径,方法的入参,模块,功能等。并实现利用注解的方式实现对被操作方法的简单注释(模块,功能)

        框架 springmvc+ mybatis

1.Log注解

package com.dzqc.dz.common.aop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /** 方法模块 */
    String title() default "";
    /** 功能 */
    String action() default "";
}

 2.LogAspect切面 (重点)

package com.dzqc.dz.common.aop;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.dzqc.dz.common.dao.LogMapper;
import com.dzqc.dz.common.entity.LogMessage;
/**
 * @author Administrator
 * @Description 日志记录
 */
public class LogAspect {
    @Autowired
    private LogMapper logMapper;//日志 mapper
     
    private String requestPath = null ; // 请求地址  
    private long startTimeMillis = 0; // 开始时间  
    private long endTimeMillis = 0; // 结束时间  
    private String user = null; // 操作人
    private HttpServletRequest request = null;//请求
   /**
    * @param joinPoint
    * @Description 气质通知  方法调用前触发   记录开始时间,从session中获取操作人
    */
    public void before(JoinPoint joinPoint){  
        startTimeMillis = System.currentTimeMillis(); 
    } 
    /**
     * @param joinPoint
     * @Description 获取入参方法参数
     * @return
     */
    public Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
        Map<String, Object> param = new HashMap<>();
        Object[] paramValues = joinPoint.getArgs();
        String[] paramNames = ((CodeSignature)joinPoint.getSignature()).getParameterNames();
        for (int i = 0; i < paramNames.length; i++) {
            if(paramValues[i] instanceof Integer || paramValues[i] instanceof String) {
                param.put(paramNames[i], paramValues[i]);
            }
        }
        return param;
    }
    /**
     * @param joinPoint
     * @Description 后置通知    方法调用后触发   记录结束时间 ,操作人 ,入参等
     */
    public void after(JoinPoint joinPoint) {
        request = getHttpServletRequest();
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class<?> targetClass = null;
        try {
            targetClass = Class.forName(targetName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Method[] methods = targetClass.getMethods();
        String title;
        String action;
        Class<?>[] clazzs;
        for (Method method : methods) {  
            if (method.getName().equals(methodName)) {  
                clazzs = method.getParameterTypes();  
                if (clazzs!=null&&clazzs.length == arguments.length
                &&method.getAnnotation(Log.class)!=null) {  
                    request = getHttpServletRequest();
                    requestPath=request.getServletPath();
                    user = (String) request.getSession().getAttribute("user");
                    title = method.getAnnotation(Log.class).title();
                    action = method.getAnnotation(Log.class).action();
                    endTimeMillis = System.currentTimeMillis();
                    LogMessage log=new LogMessage(user, requestPath, 
                    (endTimeMillis-startTimeMillis)+"ms", 
                    getNameAndValue(joinPoint).toString(), title, action);
                    logMapper.writeLog(log);
                    break;  
                }  
            }  
        }
    }
    /**
     * @Description: 获取request  
     */
    public HttpServletRequest getHttpServletRequest(){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();  
        ServletRequestAttributes sra = (ServletRequestAttributes)ra;  
        HttpServletRequest request = sra.getRequest();
        return request;
    }
    /**
     * @param joinPoint
     * @return 环绕通知
     * @throws Throwable
     */
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {  
        return null;  
    }  
    /**
     * @param joinPoint
     * @Description 异常通知
     */
    public void throwing(JoinPoint joinPoint) {
        System.out.println("异常通知");
    }
}

 3.封装日志信息的实体类

package com.dzqc.dz.common.entity;
 
public class LogMessage {
    private String operationUser;//操作人
    private String path;//请求路径
    private String time;//方法执行时间
    private String parameter;//方法入参
    private String title;//操作方法
    private String action;//方法描述
    public String getOperationUser() {
        return operationUser;
    }
    public LogMessage() {
        super();
        // TODO Auto-generated constructor stub
    }
    public LogMessage(String operationUser, String path, String time, 
    String parameter, String title, String action) {
        super();
        this.operationUser = operationUser;
        this.path = path;
        this.time = time;
        this.parameter = parameter;
        this.title = title;
        this.action = action;
    }
    public void setOperationUser(String operationUser) {
        this.operationUser = operationUser;
    }
    public String getPath() {
        return path;
    }
    public void setPath(String path) {
        this.path = path;
    }
    public String getTime() {
        return time;
    }
    public void setTime(String time) {
        this.time = time;
    }
    public String getParameter() {
        return parameter;
    }
    public void setParameter(String parameter) {
        this.parameter = parameter;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
     
}

 4.Mapper

package com.dzqc.dz.common.dao;
 
import com.dzqc.dz.common.entity.LogMessage;
public interface LogMapper {
    public void writeLog(LogMessage message);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.dzqc.dz.common.dao.LogMapper" >
  <insert id="writeLog" parameterType="com.dzqc.dz.common.entity.LogMessage">
      INSERT into log(operationUser,path,time,parameter,title,action) VALUES(#{operationUser},#{path},#{time},#{parameter},#{title},#{action});
  </insert>
</mapper>

5.spring aop配置文件

<aop:aspectj-autoproxy proxy-target-class="true" />
     
    <!--将日志类注入到bean中。-->
    <bean id="logAspect" class="com.dzqc.dz.common.aop.LogAspect"></bean>   
     
    <aop:config>
          <aop:aspect id="LogAspect" ref="logAspect">
              <aop:pointcut id="log" expression="execution(* com.dzqc.dz.*.controller.*.*(..))"/>  
              <aop:before pointcut-ref="log" method="before"/> 
              <aop:after-throwing pointcut-ref="log" method="throwing" throwing="e"/>
              <aop:after pointcut-ref="log" method="after"/>
          </aop:aspect>
    </aop:config>

 6.测试controller

 

package com.dzqc.dz.common.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dzqc.dz.common.aop.Log;
 
@Controller
@RequestMapping("/test")
public class TestController {
     
    @RequestMapping("/logtest")
    @ResponseBody
    @Log(title="logtest",action="测试log日志")
    public Map<String,Object> logtest(HttpSession session,Integer id,String username) {
        session.setAttribute("user","rjx");
        Map<String,Object> map=new HashMap<>();
        map.put("code", 200);
        map.put("data", "success");
        return map;
    }
     
    @RequestMapping("/test")
    @ResponseBody
    public Map<String,Object> test(HttpSession session,Integer id,String username) {
        session.setAttribute("user","rjx");
        Map<String,Object> map=new HashMap<>();
        map.put("code", 200);
        map.put("data", "success");
        return map;
    }
}

我们在logtest方法中加入Log注解,在调用这个方法的时候 会把一些信息记录进数据库,而没有加Log注解的方法则没有记录,但是根据aop的配置可知,TestController中所有的方法都被植入进了 LogAspect 切面中的逻辑,只是在LogAspect中进行了判断,只有带Log注解的方法执行才会 被记录进数据库。

测试:

注意:如果运行出现如下错误,请换较高版本的spring依赖

 

<spring.version>4.3.5.RELEASE</spring.version>

 

 

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP是一个强大的框架,可以帮助我们实现各种切面,其中包括日志记录。下面是实现日志记录的步骤: 1. 添加Spring AOP依赖 在Maven或Gradle中添加Spring AOP依赖。 2. 创建日志切面 创建一个用于记录日志的切面。这个切面可以拦截所有需要记录日志的方法。在这个切面中,我们需要使用@Aspect注解来声明这是一个切面,并使用@Pointcut注解来定义哪些方法需要被拦截。 ```java @Aspect @Component public class LoggingAspect { @Pointcut("execution(* com.example.demo.service.*.*(..))") public void serviceMethods() {} @Around("serviceMethods()") public Object logServiceMethods(ProceedingJoinPoint joinPoint) throws Throwable { // 获取方法名,参数列表等信息 String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); // 记录日志 System.out.println("Method " + methodName + " is called with args " + Arrays.toString(args)); // 执行方法 Object result = joinPoint.proceed(); // 记录返回值 System.out.println("Method " + methodName + " returns " + result); return result; } } ``` 在上面的代码中,我们使用了@Around注解来定义一个环绕通知,它会在拦截的方法执行前后执行。在方法执行前,我们记录了该方法的名称和参数列表,然后在方法执行后记录了该方法的返回值。 3. 配置AOPSpring的配置文件中配置AOP。首先,我们需要启用AOP: ```xml <aop:aspectj-autoproxy/> ``` 然后,我们需要将创建的日志切面添加到AOP中: ```xml <bean id="loggingAspect" class="com.example.demo.aspect.LoggingAspect"/> <aop:config> <aop:aspect ref="loggingAspect"> <aop:pointcut id="serviceMethods" expression="execution(* com.example.demo.service.*.*(..))"/> <aop:around method="logServiceMethods" pointcut-ref="serviceMethods"/> </aop:aspect> </aop:config> ``` 在上面的代码中,我们将创建的日志切面声明为一个bean,并将其添加到AOP中。我们还定义了一个切入点,并将其与日志切面的方法进行关联。 4. 测试 现在,我们可以测试我们的日志记录功能了。在我们的业务逻辑中,所有匹配切入点的方法都会被拦截,并记录它们的输入和输出。我们可以在控制台中看到这些日志信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值