/*
* *************************************************************************
* 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'),
文章中若有不足之处,还望指出。坚持是一种精神,分享是一种快乐!