update 优化 使用spring事件发布机制 重构登录日志与操作日志

This commit is contained in:
疯狂的狮子li 2022-12-07 20:32:57 +08:00
parent 6e017c35f7
commit 4c8137daf2
10 changed files with 107 additions and 72 deletions

View File

@ -0,0 +1,44 @@
package com.ruoyi.common.core.domain.event;
import lombok.Data;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
/**
* 登录事件
*
* @author Lion Li
*/
@Data
public class LogininforEvent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户账号
*/
private String username;
/**
* 登录状态 0成功 1失败
*/
private String status;
/**
* 提示消息
*/
private String message;
/**
* 请求体
*/
private HttpServletRequest request;
/**
* 其他参数
*/
private Object[] args;
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.core.domain.dto; package com.ruoyi.common.core.domain.event;
import lombok.Data; import lombok.Data;
@ -6,13 +6,13 @@ import java.io.Serializable;
import java.util.Date; import java.util.Date;
/** /**
* 通用操作日志实体 * 操作日志事件
* *
* @author Lion Li * @author Lion Li
*/ */
@Data @Data
public class OperLogDTO implements Serializable { public class OperLogEvent implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -1,14 +0,0 @@
package com.ruoyi.common.core.service;
import javax.servlet.http.HttpServletRequest;
/**
* 通用 系统访问日志
*
* @author Lion Li
*/
public interface LogininforService {
void recordLogininfor(String username, String status, String message,
HttpServletRequest request, Object... args);
}

View File

@ -1,15 +0,0 @@
package com.ruoyi.common.core.service;
import com.ruoyi.common.core.domain.dto.OperLogDTO;
import org.springframework.scheduling.annotation.Async;
/**
* 通用 操作日志
*
* @author Lion Li
*/
public interface OperLogService {
@Async
void recordOper(OperLogDTO operLogDTO);
}

View File

@ -4,8 +4,7 @@ import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.dto.OperLogDTO; import com.ruoyi.common.core.domain.event.OperLogEvent;
import com.ruoyi.common.core.service.OperLogService;
import com.ruoyi.common.enums.BusinessStatus; import com.ruoyi.common.enums.BusinessStatus;
import com.ruoyi.common.enums.HttpMethod; import com.ruoyi.common.enums.HttpMethod;
import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.helper.LoginHelper;
@ -67,7 +66,7 @@ public class LogAspect {
try { try {
// *========数据库日志=========*// // *========数据库日志=========*//
OperLogDTO operLog = new OperLogDTO(); OperLogEvent operLog = new OperLogEvent();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址 // 请求的地址
String ip = ServletUtils.getClientIP(); String ip = ServletUtils.getClientIP();
@ -87,8 +86,8 @@ public class LogAspect {
operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// 处理设置注解上的参数 // 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
// 保存数据库 // 发布事件保存数据库
SpringUtils.getBean(OperLogService.class).recordOper(operLog); SpringUtils.context().publishEvent(operLog);
} catch (Exception exp) { } catch (Exception exp) {
// 记录本地异常日志 // 记录本地异常日志
log.error("异常信息:{}", exp.getMessage()); log.error("异常信息:{}", exp.getMessage());
@ -103,7 +102,7 @@ public class LogAspect {
* @param operLog 操作日志 * @param operLog 操作日志
* @throws Exception * @throws Exception
*/ */
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogDTO operLog, Object jsonResult) throws Exception { public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception {
// 设置action动作 // 设置action动作
operLog.setBusinessType(log.businessType().ordinal()); operLog.setBusinessType(log.businessType().ordinal());
// 设置标题 // 设置标题
@ -127,7 +126,7 @@ public class LogAspect {
* @param operLog 操作日志 * @param operLog 操作日志
* @throws Exception 异常 * @throws Exception 异常
*/ */
private void setRequestValue(JoinPoint joinPoint, OperLogDTO operLog) throws Exception { private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception {
String requestMethod = operLog.getRequestMethod(); String requestMethod = operLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
String params = argsArrayToString(joinPoint.getArgs()); String params = argsArrayToString(joinPoint.getArgs());

View File

@ -18,7 +18,7 @@ import java.util.concurrent.ScheduledExecutorService;
* *
* @author Lion Li * @author Lion Li
*/ */
@EnableAsync @EnableAsync(proxyTargetClass = true)
@Configuration @Configuration
public class AsyncConfig extends AsyncConfigurerSupport { public class AsyncConfig extends AsyncConfigurerSupport {

View File

@ -7,11 +7,11 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.event.LogininforEvent;
import com.ruoyi.common.core.domain.dto.RoleDTO; import com.ruoyi.common.core.domain.dto.RoleDTO;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.XcxLoginUser; import com.ruoyi.common.core.domain.model.XcxLoginUser;
import com.ruoyi.common.core.service.LogininforService;
import com.ruoyi.common.enums.DeviceType; import com.ruoyi.common.enums.DeviceType;
import com.ruoyi.common.enums.LoginType; import com.ruoyi.common.enums.LoginType;
import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.enums.UserStatus;
@ -24,6 +24,7 @@ import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -46,7 +47,6 @@ public class SysLoginService {
private final ISysUserService userService; private final ISysUserService userService;
private final ISysConfigService configService; private final ISysConfigService configService;
private final LogininforService asyncService;
private final SysPermissionService permissionService; private final SysPermissionService permissionService;
@Value("${user.password.maxRetryCount}") @Value("${user.password.maxRetryCount}")
@ -141,7 +141,12 @@ public class SysLoginService {
* @return * @return
*/ */
private void recordLogininfor(String username, String status, String message) { private void recordLogininfor(String username, String status, String message) {
asyncService.recordLogininfor(username, status, message, ServletUtils.getRequest()); LogininforEvent logininforDTO = new LogininforEvent();
logininforDTO.setUsername(username);
logininforDTO.setStatus(status);
logininforDTO.setMessage(message);
logininforDTO.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforDTO);
} }
/** /**

View File

@ -4,9 +4,9 @@ import cn.dev33.satoken.secure.BCrypt;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.event.LogininforEvent;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody; import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.service.LogininforService;
import com.ruoyi.common.enums.UserType; import com.ruoyi.common.enums.UserType;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.CaptchaExpireException;
@ -15,6 +15,7 @@ import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -31,7 +32,6 @@ public class SysRegisterService {
private final ISysUserService userService; private final ISysUserService userService;
private final ISysConfigService configService; private final ISysConfigService configService;
private final LogininforService asyncService;
/** /**
* 注册 * 注册
@ -61,7 +61,7 @@ public class SysRegisterService {
if (!regFlag) { if (!regFlag) {
throw new UserException("user.register.error"); throw new UserException("user.register.error");
} }
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"), request); recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
} }
/** /**
@ -77,12 +77,30 @@ public class SysRegisterService {
String captcha = RedisUtils.getCacheObject(verifyKey); String captcha = RedisUtils.getCacheObject(verifyKey);
RedisUtils.deleteObject(verifyKey); RedisUtils.deleteObject(verifyKey);
if (captcha == null) { if (captcha == null) {
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"), request); recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException(); throw new CaptchaExpireException();
} }
if (!code.equalsIgnoreCase(captcha)) { if (!code.equalsIgnoreCase(captcha)) {
asyncService.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"), request); recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
throw new CaptchaException(); throw new CaptchaException();
} }
} }
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
private void recordLogininfor(String username, String status, String message) {
LogininforEvent logininforDTO = new LogininforEvent();
logininforDTO.setUsername(username);
logininforDTO.setStatus(status);
logininforDTO.setMessage(message);
logininforDTO.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(logininforDTO);
}
} }

View File

@ -6,8 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.event.LogininforEvent;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.LogininforService;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.AddressUtils;
@ -16,6 +16,7 @@ import com.ruoyi.system.mapper.SysLogininforMapper;
import com.ruoyi.system.service.ISysLogininforService; import com.ruoyi.system.service.ISysLogininforService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -33,22 +34,19 @@ import java.util.Map;
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j @Slf4j
@Service @Service
public class SysLogininforServiceImpl implements ISysLogininforService, LogininforService { public class SysLogininforServiceImpl implements ISysLogininforService {
private final SysLogininforMapper baseMapper; private final SysLogininforMapper baseMapper;
/** /**
* 记录登录信息 * 记录登录信息
* *
* @param username 用户名 * @param logininforEvent 登录事件
* @param status 状态
* @param message 消息
* @param args 列表
*/ */
@Async @Async
@Override @EventListener
public void recordLogininfor(final String username, final String status, final String message, public void recordLogininfor(LogininforEvent logininforEvent) {
HttpServletRequest request, final Object... args) { HttpServletRequest request = logininforEvent.getRequest();
final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
final String ip = ServletUtils.getClientIP(request); final String ip = ServletUtils.getClientIP(request);
@ -56,27 +54,27 @@ public class SysLogininforServiceImpl implements ISysLogininforService, Logininf
StringBuilder s = new StringBuilder(); StringBuilder s = new StringBuilder();
s.append(getBlock(ip)); s.append(getBlock(ip));
s.append(address); s.append(address);
s.append(getBlock(username)); s.append(getBlock(logininforEvent.getUsername()));
s.append(getBlock(status)); s.append(getBlock(logininforEvent.getStatus()));
s.append(getBlock(message)); s.append(getBlock(logininforEvent.getMessage()));
// 打印信息到日志 // 打印信息到日志
log.info(s.toString(), args); log.info(s.toString(), logininforEvent.getArgs());
// 获取客户端操作系统 // 获取客户端操作系统
String os = userAgent.getOs().getName(); String os = userAgent.getOs().getName();
// 获取客户端浏览器 // 获取客户端浏览器
String browser = userAgent.getBrowser().getName(); String browser = userAgent.getBrowser().getName();
// 封装对象 // 封装对象
SysLogininfor logininfor = new SysLogininfor(); SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username); logininfor.setUserName(logininforEvent.getUsername());
logininfor.setIpaddr(ip); logininfor.setIpaddr(ip);
logininfor.setLoginLocation(address); logininfor.setLoginLocation(address);
logininfor.setBrowser(browser); logininfor.setBrowser(browser);
logininfor.setOs(os); logininfor.setOs(os);
logininfor.setMsg(message); logininfor.setMsg(logininforEvent.getMessage());
// 日志状态 // 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) { if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.SUCCESS); logininfor.setStatus(Constants.SUCCESS);
} else if (Constants.LOGIN_FAIL.equals(status)) { } else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) {
logininfor.setStatus(Constants.FAIL); logininfor.setStatus(Constants.FAIL);
} }
// 插入数据 // 插入数据

View File

@ -5,15 +5,15 @@ import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.dto.OperLogDTO; import com.ruoyi.common.core.domain.event.OperLogEvent;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.service.OperLogService;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.mapper.SysOperLogMapper; import com.ruoyi.system.mapper.SysOperLogMapper;
import com.ruoyi.system.service.ISysOperLogService; import com.ruoyi.system.service.ISysOperLogService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -29,19 +29,19 @@ import java.util.Map;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class SysOperLogServiceImpl implements ISysOperLogService, OperLogService { public class SysOperLogServiceImpl implements ISysOperLogService {
private final SysOperLogMapper baseMapper; private final SysOperLogMapper baseMapper;
/** /**
* 操作日志记录 * 操作日志记录
* *
* @param operLogDTO 操作日志信息 * @param operLogEvent 操作日志事件
*/ */
@Async @Async
@Override @EventListener
public void recordOper(final OperLogDTO operLogDTO) { public void recordOper(OperLogEvent operLogEvent) {
SysOperLog operLog = BeanUtil.toBean(operLogDTO, SysOperLog.class); SysOperLog operLog = BeanUtil.toBean(operLogEvent, SysOperLog.class);
// 远程查询操作地点 // 远程查询操作地点
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
insertOperlog(operLog); insertOperlog(operLog);