java自定义注解实现操作日志入库

1、定义一个注解类

package com.staryea.annotation.operlog;

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;

/**
 * 操作日志注解
 * @author 韩俊
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {

	// 菜单名称,如数据项
	String name();
	
	// 功能名称,如分页查询
	String desc();

	// 操作类型
	OperLogEnum action();
	
	// 是否插入请求参数
	boolean isAddParam() default true;
}

2、定义一个切面类来实现功能

package com.staryea.annotation.operlog;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
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.app.frame.util.Base64Encrypt;
import com.app.frame.util.IpUtil;
import com.app.frame.util.PageData;
import com.staryea.util.DateUtil;
import com.staryea.util.StringUtil;

/**
 * 操作日志切面
 * @author 韩俊
 */
@Aspect
@Component
public class OperLogAspect {
	
	private static final org.apache.commons.logging.Log logger = LogFactory.getLog(OperLogAspect.class);
	
	@Autowired
	private OperLogMapper operLogMapper;

	// 切点
	@Pointcut("@annotation(com.staryea.annotation.operlog.OperLog)")
	public void log() {
		
	}

	@Before(value = "log()")
	public void logBefore(JoinPoint joinPoint) {
		
		try {
			//获取当前类象
			Class clazz = joinPoint.getTarget().getClass();
			
			// 获取当前类的执行的方法
			MethodSignature signature = (MethodSignature) joinPoint.getSignature();
			Method method = clazz.getMethod(signature.getMethod().getName(), signature.getMethod().getParameterTypes());
			
			// 获取注解里的参数
			OperLog log = method.getAnnotation(OperLog.class);
			
			// 获取请求参数
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			String param = JSON.toJSON(new PageData(request)).toString();
			
			String url = request.getRequestURL().toString();// 获取请求路径
			String name = log.name();// 获取菜单名称
			String desc = log.desc();// 获取功能名称
			String action = log.action().name();// 获取操作类型
			boolean isAddParam = log.isAddParam();// 获取是否插入参数
			param = isAddParam ? param : null;
			String staff = getStaff(request);// 获取操作人
			String ip = IpUtil.getIpAddr(request);
			
			// 入库
			PageData addPd = new PageData();
			addPd.put("id", StringUtil.getUUID());
			addPd.put("url", url);
			addPd.put("name", name);
			addPd.put("desc", desc);
			addPd.put("action", action);
			addPd.put("param", "{}".equals(param) ? null : param);
			addPd.put("ip", ip);
			addPd.put("time",  DateUtil.getDateTime());
			addPd.put("staff", staff);
			operLogMapper.add(addPd);
		}
		catch (Throwable t) {
			logger.error("写入操作日志失败!", t);
		}
	}

	// 从token中获取操作人
	private String getStaff(HttpServletRequest request) {
		try {
			if (request.getHeader("Auth-Token") == null) {
				return null;
			}
			String token = Base64Encrypt.decodeBy3DESAndBase64(request.getHeader("Auth-Token"));
			if (StringUtil.isNull(token)) {
				return null;
			}
			return token.split("_")[0];
		}
		catch (Exception e) {
			return null;
		}
	}
}

3、定义一个枚举类

package com.staryea.annotation.operlog;

/**
 * 操作日志类型
 * @author 韩俊
 */
public enum OperLogEnum {
	add,
	update,
	delete,
	query,
	upload,
	download
}

4、DAO层

package com.staryea.annotation.operlog;

import org.apache.ibatis.annotations.Mapper;

import com.app.frame.util.PageData;

@Mapper
public interface OperLogMapper {
    public int add(PageData pd);
}

5、sql





    
        insert into ts_operation_log(
			id,
			url,
			`name`,
			`desc`,
			action,
			param,
			ip,
			time,
			staff
			)
			values(
			#{id},
			#{url},
			#{name},
			#{desc},
			#{action},
			#{param},
			#{ip},
			#{time},
			#{staff}
			)
    

5、直接在方法上添加自定义注解

6、入库结果

7、表结构

CREATE TABLE `ts_operation_log` (
  `id` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '主键',
  `url` varchar(4000) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '请求地址',
  `name` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '菜单名称,如数据项',
  `desc` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '功能,如分页查询',
  `action` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作类型',
  `param` text COLLATE utf8_unicode_ci COMMENT '参数',
  `ip` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作人ip,可能获取多个,如192.168.4.92,192.168.2.172,因为中间存在nginx,所以除了操作人ip还有中间代理服务器的ip',
  `time` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作时间',
  `staff` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作人',
  PRIMARY KEY (`id`),
  KEY `index_time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

8、PageData其实就是一个继承了map并且增加了一些构造方法的类,这个地方可以随你用什么东西,new PageData(request)是把请求参数put进对象里,这个你们自己实现就好。获取操作人需要跟自己的系统实际情况获取,我这个是通过页面token解析出来的。

你可能感兴趣的:(java,积累篇)