Springmvc记录操作日志到数据库

2023年5月27日09:08:27

数据库字段

Springmvc记录操作日志到数据库

建表语句

CREATE TABLE log_table (
log_id int(11) NOT NULL auto_increment COMMENT ‘主键’,
log_ipAddress varchar(64) default NULL COMMENT ‘请求的IP地址’,
log_createtime varchar(64) default NULL COMMENT ‘时间’,
log_moduleName varchar(128) default NULL COMMENT ‘模块名称’,
log_desc varchar(128) default NULL COMMENT ‘功能’,
log_type varchar(32) default NULL COMMENT ‘操作类型’,
log_methodName varchar(128) default NULL COMMENT ‘请求的方法名’,
log_params varchar(1000) default NULL COMMENT ‘请求的参数’,
log_paramter varchar(2000) default NULL COMMENT ‘请求的参数’,
PRIMARY KEY (log_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=‘操作日志表’;

配置application-aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
	
	<!-- 配置包扫描器,扫描@Service主键的类[此处只扫描后台的包] -->
	<context:component-scan base-package="com.kindergarten.log"></context:component-scan>  

	<!-- 定义操作日志切面 -->
	<bean id="logAspect" class="com.kindergarten.log.LogAopAspect"></bean>
	<!-- 通知Spring使用cglib而不是jdk的来生成代理方法  AOP可以拦截到Controller -->
	<aop:aspectj-autoproxy proxy-target-class="true">
		<aop:include name="logAspect"/>
	</aop:aspectj-autoproxy>

实体类

package com.kindergarten.log;

public class Logentity {
	/**
	 * 主键
	 **/
    private String logId = "";
	/**
	 * 请求的IP地址
	 **/
    private String logIpAddress = "";
	/**
	 * 时间
	 **/
    private String logCreatetime = "";
	/**
	 * 模块名称
	 **/
    private String logModulename = "";
	/**
	 * 功能
	 **/
    private String logDesc = "";
    /**
	 * 操作类型 
	 **/
    private String logType = "";
	/**
	 * 请求的方法名
	 **/
    private String logMethodname = "";
	/**
	 * 请求的参数
	 **/
    private String logParams = "";
   	/**
   	 * 请求的参数
   	 **/
    private String logParamter = "";
    
    
    
    
	public String getLogId() {
		return logId;
	}
	public void setLogId(String logId) {
		this.logId = logId;
	}
	public String getLogIpAddress() {
		return logIpAddress;
	}
	public void setLogIpAddress(String logIpAddress) {
		this.logIpAddress = logIpAddress;
	}
	public String getLogCreatetime() {
		return logCreatetime;
	}
	public void setLogCreatetime(String logCreatetime) {
		this.logCreatetime = logCreatetime;
	}
	public String getLogModulename() {
		return logModulename;
	}
	public void setLogModulename(String logModulename) {
		this.logModulename = logModulename;
	}
	public String getLogDesc() {
		return logDesc;
	}
	public void setLogDesc(String logDesc) {
		this.logDesc = logDesc;
	}
	public String getLogType() {
		return logType;
	}
	public void setLogType(String logType) {
		this.logType = logType;
	}
	public String getLogMethodname() {
		return logMethodname;
	}
	public void setLogMethodname(String logMethodname) {
		this.logMethodname = logMethodname;
	}
	public String getLogParams() {
		return logParams;
	}
	public void setLogParams(String logParams) {
		this.logParams = logParams;
	}
	public String getLogParamter() {
		return logParamter;
	}
	public void setLogParamter(String logParamter) {
		this.logParamter = logParamter;
	}
	
    
}

Service接口

package com.kindergarten.log;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kindergarten.mapper.LogMapper;

@Service
public class LogServiceImpl implements LogService{
	@Autowired
	private LogMapper logMapper;
	/**
	 *add log 
	*/
	@Override
	public void insertlog(Logentity logentity){
		logMapper.insertlog(logentity);
	}
}

Service

package com.kindergarten.log;

public interface LogService {
	/**
	 *add log 
	*/
	public void insertlog(Logentity logentity);
}

日志切面

package com.kindergarten.log;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

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.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.kindergarten.util.DateUtil;
import com.kindergarten.util.IpAddress;

import java.util.HashMap;

@Aspect
@Component
public class LogAopAspect {
	private static final Logger LOGGER = LoggerFactory.getLogger(LogAopAspect.class);
	@Autowired
	private LogService logService;
	
	/**
	 * Controller层切点 
	 */
	@Pointcut("@annotation(com.kindergarten.log.LogAopPointcut)")
	public void aopPoint() {
		
	}
	
	
	/**
	 * 切面 配置通知 
	 */
    @AfterReturning("aopPoint()")
    public void saveSysLog(JoinPoint joinPoint) {
        //保存日志
        Logentity log = new Logentity();
        
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作
        LogAopPointcut logAopPointcut = method.getAnnotation(LogAopPointcut.class);
        //--------------------
        if (logAopPointcut != null) {
        	//模块名称
            log.setLogModulename(logAopPointcut.logModulename());
            //功能
            log.setLogDesc(logAopPointcut.logDesc());
            //操作类型
            String index = logAopPointcut.logType().getIndex();
            String name = logAopPointcut.logType().getLogname();
            log.setLogType(name);
        }
        
        //时间
        log.setLogCreatetime(DateUtil.getDate_YMDHMS_S());
        //--------------------
        //获取请求的方法名
        String methodName = method.getName();
        log.setLogMethodname(methodName);
        //--------------------
        //请求的参数
        Object[] args = joinPoint.getArgs();
        //将参数所在的数组转换成json
        String params = JSON.toJSONString(args);
        log.setLogParams(params);
        //--------------------
        //--------------------
        //创建参数名称实例
        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        String[] paramterNames = discoverer.getParameterNames(method);
        //传递给方法的参数数据
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        for (int i = 0; i < paramterNames.length; i++) {
			Object o = args[i];
			if(o instanceof String || o instanceof String[]) {
				paramsMap.put(paramterNames[i], o);
			}else {
				continue;
			}
		}
        String paramter = JSON.toJSONString(paramsMap);
        log.setLogParamter(paramter);
        //--------------------
        //获取用户ip地址
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        log.setLogIpAddress(IpAddress.getIpAddress(request));
        //--------------------
//        //获取用户名
//        sysLog.setUsername(ShiroUtils.getUserEntity().getUsername());
  

        //调用service保存log实体类到数据库
        logService.insertlog(log);
    }

}

定义操作日志类别

package com.kindergarten.log;

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;

/**
 * 1.CONSTRUCTOR:用于描述构造器
 * 2.FIELD:用于描述域
 * 3.LOCAL_VARIABLE:用于描述局部变量
 * 4.METHOD:用于描述方法
 * 5.PACKAGE:用于描述包
 * 6.PARAMETER:用于描述参数
 * 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
 * */
@Target({ElementType.METHOD})//方法上
/**
 * 1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
 * 2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
 * 3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
 * */
@Retention(RetentionPolicy.RUNTIME)
/**
 * Documented注解表明这个注释是由 javadoc记录的,在默认情况下也有类似的记录工具。
 *  如果一个类型声明被注释了文档化,它的注释成为公共API的一部分
 * */
@Documented
public @interface LogAopPointcut 
{
	public abstract String logModulename();
	public abstract String logDesc();
	public abstract log_Type logType();
	
	public static enum log_Type
	{
		SELECT,ADD,UPDATE,DELETE,EXPORT,IMPORT;
		
		private String logname;
		private String index;
		
		public String getLogname() {
			return this.name();
		}
		public String getIndex() {
			return String.valueOf(this.ordinal()+1);
		}
				
	}
}

在需要记录的方法上使用自定义的@LogAopPointcut

例:

例:@LogAopPointcut(logModulename = “学员模块”,logDesc = “条件查询”,logType = log_Type.SELECT)

@LogAopPointcut(logModulename = “学员模块”,logDesc = “条件删除”,logType = log_Type.SELECT)

/** 条件查询 */
	@RequestMapping(value = "/findStudent", produces = "application/json;charset=UTF-8")
	@ResponseBody
	@LogAopPointcut(logModulename = "学员模块",logDesc = "条件查询",logType = log_Type.SELECT)
	public String findStudent(String starttime, String endtime, String id, String name, String age) {
		List<StudentEntity> list = studentService.findStudent(starttime, endtime, id, name, age);
		String json = JSONArray.toJSONStringWithDateFormat(list, "yyyy-MM-dd HH:mm:ss");
		return json;
	}

数据库记录操作信息

Springmvc记录操作日志到数据库

  • 作者:帅宇Yeah~
  • 原文链接:https://blog.csdn.net/qq_43383907/article/details/104390461
    更新时间:2023年5月27日09:08:27 ,共 8013 字。