观察者模式系统日志

作者: Ian | 2019-03-31 | 阅读
/*
 * *************************************************************************
 *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the dreamlu.net developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: chunmeng.lu (qq596392912@gmail.com)
 * *************************************************************************
 */

import java.lang.annotation.*;

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

	/**
	 * 描述
	 * @return {String}
	 */
	String value();
}

import lombok.extern.slf4j.Slf4j;
import net.dreamlu.boot.annotation.SysLog;
import net.dreamlu.tool.util.SpringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 操作日志使用spring event异步入库
 */
@Aspect
@Order
@Slf4j
@Component
public class SysLogAspect {

	@Around("@annotation(sysLog)")
	public Object aroundWxApi(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
		String strClassName = point.getTarget().getClass().getName();
		String strMethodName = point.getSignature().getName();
		log.info("[类名]:{},[方法]:{}", strClassName, strMethodName);

		SysLogDTO sysLogDTO = SysLogUtils.getSysLogDTO();
		sysLogDTO.setOperation(sysLog.value());
		sysLogDTO.setClassMethod(strClassName + "." + strMethodName + "();");

		// 发送异步日志事件
		// publishEvent: 通知应用所有已注册且匹配的监听器
		SpringUtils.publishEvent(new SysLogEvent(sysLogDTO));

		return point.proceed();
	}

}
/*
 * *************************************************************************
 *   Copyright (c) 2018-2025, dreamlu.net All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the dreamlu.net developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: chunmeng.lu (qq596392912@gmail.com)
 * *************************************************************************
 */

import net.dreamlu.tool.lang.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;

/**
 * spring 工具类
 */
public class SpringUtils implements ApplicationContextAware {
	@Nullable
	private static ApplicationContext context;

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		SpringUtils.context = context;
	}

	@Nullable
	public static <T> T getBean(Class<T> clazz){
		if (context == null) { return null; }
		return context.getBean(clazz);
	}

	@Nullable
	public static <T> T getBean(String beanName, Class<T> clazz) {
		if (context == null) { return null; }
		return (T) context.getBean(beanName, clazz);
	}

	@Nullable
	public static ApplicationContext getContext(){
		return context;
	}

//////
	public static void publishEvent(ApplicationEvent event) {
		if (context == null) { return ; }
		context.publishEvent(event);
	}

}

import lombok.Getter;
import lombok.Setter;

/**
 * SysLog数据承载
 */
@Getter
@Setter
public class SysLogDTO {
	/**
	 * 登陆名
	 */
	private String username;
	/**
	 * 角色名
	 */
	private String roleName;
	/**
	 * 操作
	 */
	private String operation;
	/**
	 * 类-方法
	 */
	private String classMethod;
	/**
	 * 内容
	 */
	private String content;
	/**
	 * 客户端ip
	 */
	private String clientIp;
}

import org.springframework.context.ApplicationEvent;

/**
 * 系统日志事件(自定义事件)
 *
 */
public class SysLogEvent extends ApplicationEvent {

	public SysLogEvent(SysLogDTO source) {
		super(source);
	}
}

import lombok.AllArgsConstructor;
import net.dreamlu.system.service.ISysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
@AllArgsConstructor
public class SysLogListener {
	private final ISysLogService sysLogService;
	/**
	 * @EventListener + @Async 异步事件处理
	 *
	 * @param event
	 */
	@Async
	@Order
	@EventListener(SysLogEvent.class)
	public void saveSysLog(SysLogEvent event) {
		SysLogDTO sysLogDTO = (SysLogDTO) event.getSource();
		sysLogService.saveSysLog(sysLogDTO);
	}
}

import net.dreamlu.config.DreamConstants;
import net.dreamlu.secrity.SecurityUtils;
import net.dreamlu.secrity.auth.AuthUser;
import net.dreamlu.tool.util.StringUtils;
import net.dreamlu.tool.util.WebUtils;
import org.springframework.security.core.GrantedAuthority;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 系统日志工具类
 */
public class SysLogUtils {

	String SECURITY_ROLE_PREFIX = "ROLE_";

	public static SysLogDTO getSysLogDTO() {
		SysLogDTO sysLogDTO = new SysLogDTO();
		HttpServletRequest request = WebUtils.getRequest();
		StringBuilder params = new StringBuilder();
		request.getParameterMap().forEach((key, values) -> {
			params.append(key).append("=");
			if ("password".equalsIgnoreCase(key)) {
				params.append("******");
			} else {
				params.append(StringUtils.join(values));
			}
			params.append("&");
		});
		sysLogDTO.setContent(params.toString());
		sysLogDTO.setClientIp(WebUtils.getIP());
		AuthUser authUser = SecurityUtils.getUser();
		if (authUser != null) {
			sysLogDTO.setUsername(authUser.getUsername());
			List<String> roles = authUser.getAuthorities()
				.stream()
				.map(GrantedAuthority::getAuthority)
				.filter(x -> x.startsWith(DreamConstants.SECURITY_ROLE_PREFIX))
				.map(x -> x.replace(DreamConstants.SECURITY_ROLE_PREFIX, ""))
				.collect(Collectors.toList());
			sysLogDTO.setRoleName(StringUtils.join(roles));
		}
		return sysLogDTO;
	}

}

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
import net.dreamlu.tool.util.DateUtils;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 * 系统日志
 * </p>
 */
@Getter
@Setter
@TableName("t_sys_log")
public class SysLog implements Serializable {
	private static final long serialVersionUID = 1L;
	/**
	 * 主键id
	 */
	@TableId(value = "id", type = IdType.AUTO)
	private Integer id;
	/**
	 * 登陆名
	 */
	private String username;
	/**
	 * 角色名
	 */
	@TableField("role_name")
	private String roleName;
	/**
	 * 操作
	 */
	private String operation;
	/**
	 * 类-方法
	 */
	@TableField("class_method")
	private String classMethod;
	/**
	 * 内容
	 */
	private String content;
	/**
	 * 客户端ip
	 */
	@TableField("client_ip")
	private String clientIp;
	/**
	 * 创建时间
	 */
	@TableField("create_time")
	@DateTimeFormat(pattern = DateUtils.PATTERN_DATETIME)
	@JsonFormat(pattern = DateUtils.PATTERN_DATETIME)
	private LocalDateTime createTime;

}
CREATE TABLE `t_sys_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `username` varchar(20) DEFAULT NULL COMMENT '登陆名',
  `role_name` varchar(255) DEFAULT NULL COMMENT '角色名',
  `operation` varchar(64) DEFAULT NULL COMMENT '操作',
  `class_method` varchar(100) NOT NULL COMMENT '类-方法',
  `content` varchar(2000) DEFAULT NULL COMMENT '内容',
  `client_ip` varchar(255) NOT NULL DEFAULT '' COMMENT '客户端ip',
  `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COMMENT='系统日志';

INSERT INTO `t_sys_log` VALUES (1,'admin','admin,de,pm,test','编辑角色','net.dreamlu.system.web.RoleController.edit();','name=admin&description=超级管理员&id=1&iconCls=glyphicon-lock &seq=0&status=1&','0:0:0:0:0:0:0:1','2018-04-14 16:32:35'),(7,'admin','admin,de,pm,test','编辑用户','net.dreamlu.system.web.AdminController.edit();','sex=0&organizationId=6&password=******&roleIds=8&phone=&name=测试&id=2&userType=1&locked=0&email=596392912@qq.com&age=0&username=test&status=1&','0:0:0:0:0:0:0:1','2018-04-14 23:16:43'),(8,'test','test','登录成功','net.dreamlu.secrity.auth.DreamAuthHandler.onAuthenticationSuccess();','password=******&code=s87u&remember-me=true&username=test&','0:0:0:0:0:0:0:1','2018-04-14 23:17:12'),

文章中若有不足之处,还望指出。坚持是一种精神,分享是一种快乐!


版权声明:本文由 Ian 在 2019年03月31日发表。本文采用CC BY-NC-SA 4.0许可协议,非商业转载请注明出处,不得用于商业目的。
文章题目及链接:《观察者模式系统日志》




  相关文章:


留言区:

TOP