spring aop实现操作日志记录

硅谷探秘者 2982 0 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","jiajiajia");
		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","jiajiajia");
		Map<String,Object> map=new HashMap<>();
		map.put("code", 200);
		map.put("data", "success");
		return map;
	}
}


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


测试

menu.saveimg.savepath20190227171318.jpg


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

menu.saveimg.savepath20190228140816.jpg

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

    4.3.5版本的不会报错

猜你喜欢
框架 1088 1.Log注解importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;//
spring/springmvc 803 "spring在ioc容器中获取aop的受理对象",这句话是什么意思呢?有时候我们会在spring项目中对一下类进行代理,比如我们会用springaop和自定义注解对一些接口访问添加,再比如对
spring/springmvc 1111 bean的什么周期SpringBean的生命周期在整个Spring中占有很重要的位置,从BeanFactory或ApplicationContext取得的例为Singleton,也就是预设为每一个
spring/springmvc 2065 目接着就开始配置spring,springmvc,mybatis等1.首先目结构如下因为上次没有在model-web模块中添加对model-common的依赖,所以这次我们在model-web的pom
spring/springmvc 1670 搭建spring+springmvc+mybatis+maven项目(1)首先在配置好maven仓库的情况下:1.创建父项目file-new-mavenprojectnextgroup为父项目坐标
official 894   BeanPostProcessor是SpringIOC容器给我们提供的一个扩展接口。,他的用主要是如果我们需要在Spring容器完成Bean的例化、配置和其他的初始化前后添加一些自己的逻辑处
数据库 486 MariaDB/MySQL中,主要有5种文件:1.错误(errorlog):mysql服务的启停时正确和错误的信息,还启动、停止、运行过程中的错误信息。2.查询(generallog):
数据库 549 开启和设置二进制切换二进制相关参数二进制恢复数据库上一篇文章介绍了普通查询和慢查询等参考:mysql分析,本篇主要介绍二进制。一、什么是二进制  二进制主要
归档
2018年11月  12 2018年12月  33 2019年01月  28 2019年02月  28 2019年03月  32 2019年04月  27 2019年05月  33 2019年06月  6 2019年07月  12 2019年08月  12 2019年09月  21 2019年10月  8 2019年11月  15 2019年12月  25 2020年01月  9 2020年02月  5 2020年03月  16 2020年04月  4 2020年06月  1 2020年07月  7 2020年08月  13 2020年09月  9 2020年10月  5 2020年12月  3 2021年01月  1 2021年02月  5 2021年03月  7 2021年04月  4 2021年05月  4 2021年06月  1 2021年07月  7 2021年08月  2 2021年09月  8 2021年10月  9 2021年11月  16 2021年12月  14 2022年01月  7 2022年05月  1 2022年08月  3 2022年09月  2 2022年10月  2
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。