日志切面功能整合
This commit is contained in:
parent
cde964492c
commit
8d8e338da8
|
|
@ -19,6 +19,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-log</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>account-service</artifactId>
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ spring:
|
|||
|
||||
data:
|
||||
redis:
|
||||
host: 101.37.12.135
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: 111111
|
||||
timeout: 1000
|
||||
password:
|
||||
timeout: 5000
|
||||
database: 1
|
||||
|
||||
cloud:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-log</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>order-service</artifactId>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-log</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>product-service</artifactId>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package com.czg.controller;
|
|||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import com.czg.annotation.LogOperation;
|
||||
import com.czg.annotation.SaAdminCheckPermission;
|
||||
import com.czg.log.annotation.LogOperation;
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.service.ProductService;
|
||||
import com.czg.resp.CzgResult;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package com.czg.controller;
|
|||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import com.czg.annotation.LogOperation;
|
||||
import com.czg.annotation.SaAdminCheckPermission;
|
||||
import com.czg.log.annotation.LogOperation;
|
||||
import com.czg.product.dto.ShopProdCategoryDTO;
|
||||
import com.czg.product.service.ShopProdCategoryService;
|
||||
import com.czg.resp.CzgResult;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.czg.controller;
|
||||
|
||||
import com.czg.annotation.LogOperation;
|
||||
import com.czg.annotation.SaAdminCheckPermission;
|
||||
import com.czg.log.annotation.LogOperation;
|
||||
import com.czg.product.dto.ShopProdUnitDTO;
|
||||
import com.czg.product.service.ShopProdUnitService;
|
||||
import com.czg.resp.CzgResult;
|
||||
|
|
@ -27,10 +27,13 @@ import java.util.List;
|
|||
@RestController
|
||||
@RequestMapping("/admin/prod/unit")
|
||||
public class ShopProdUnitController {
|
||||
|
||||
public static final String LOG_PREFIX = "商品单位管理-";
|
||||
|
||||
private final ShopProdUnitService shopProdUnitService;
|
||||
|
||||
@GetMapping("page")
|
||||
@LogOperation("分页")
|
||||
@LogOperation(LOG_PREFIX+"分页")
|
||||
//@SaAdminCheckPermission("prod:unit:all")
|
||||
public CzgResult<Page<ShopProdUnitDTO>> page(ShopProdUnitDTO param) {
|
||||
Page<ShopProdUnitDTO> data = shopProdUnitService.page(param);
|
||||
|
|
@ -40,7 +43,7 @@ public class ShopProdUnitController {
|
|||
@GetMapping("list")
|
||||
@LogOperation("列表")
|
||||
@SaAdminCheckPermission("prod:unit:all")
|
||||
public CzgResult<List<ShopProdUnitDTO>> list(@RequestParam ShopProdUnitDTO param) {
|
||||
public CzgResult<List<ShopProdUnitDTO>> list(ShopProdUnitDTO param) {
|
||||
List<ShopProdUnitDTO> data = shopProdUnitService.list(param);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ spring:
|
|||
|
||||
data:
|
||||
redis:
|
||||
host: 101.37.12.135
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: 111111
|
||||
timeout: 1000
|
||||
password:
|
||||
timeout: 5000
|
||||
database: 1
|
||||
lettuce:
|
||||
pool:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-log</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>system-service</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>cash-common-log</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-tools</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-redis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-common-sa-token</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.czg.log;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.czg.config.RedisCst;
|
||||
import com.czg.service.RedisService;
|
||||
import com.mybatisflex.core.row.Db;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* 从Redis队列中获取Log,保存到DB
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LogConsumer implements CommandLineRunner {
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
private final ScheduledExecutorService scheduledService = new ScheduledThreadPoolExecutor(1,
|
||||
new BasicThreadFactory.Builder().namingPattern("log-consumer-schedule-pool-%d").daemon(true).build());
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
//上次任务结束后,等待10秒钟,再执行下次任务
|
||||
scheduledService.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
receiveQueue();
|
||||
} catch (Exception e) {
|
||||
log.error("LogConsumer Error:" + ExceptionUtil.stacktraceToString(e));
|
||||
}
|
||||
}, 1, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void receiveQueue() {
|
||||
String key = RedisCst.SYS_LOG_KEY;
|
||||
//每次插入100条
|
||||
int count = 100;
|
||||
for (int i = 0; i < count; i++) {
|
||||
String log = (String) redisService.rightPop(key);
|
||||
if (log == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 操作日志入库
|
||||
Row row = JSON.parseObject(log, Row.class);
|
||||
Db.insert("operation_log",row);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
package com.czg.annotation;
|
||||
package com.czg.log.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.czg.log.aspect;
|
||||
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.log.annotation.LogOperation;
|
||||
import com.czg.log.enums.LogTypeEnum;
|
||||
import com.czg.log.enums.OperationStatusEnum;
|
||||
import com.czg.log.producer.LogProducer;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.utils.AddressUtil;
|
||||
import com.czg.utils.HttpContextUtil;
|
||||
import com.mybatisflex.core.keygen.impl.SnowFlakeIDKeyGenerator;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志,切面处理类
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogOperationAspect {
|
||||
|
||||
@Resource
|
||||
private LogProducer logProducer;
|
||||
|
||||
@Pointcut("@annotation(com.czg.log.annotation.LogOperation)")
|
||||
public void logPointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long beginTime = System.currentTimeMillis();
|
||||
try {
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
//保存日志
|
||||
saveLog(point, time, OperationStatusEnum.SUCCESS.value());
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
String errorInfo = ExceptionUtil.stacktraceToString(e);
|
||||
//保存日志
|
||||
saveLog(point, time, OperationStatusEnum.FAIL.value(), errorInfo);
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status) {
|
||||
saveLog(joinPoint, time, status, null);
|
||||
}
|
||||
|
||||
|
||||
private void saveLog(ProceedingJoinPoint joinPoint, long time, Integer status, String errorInfo) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
Row log = new Row();
|
||||
LogOperation annotation = method.getAnnotation(LogOperation.class);
|
||||
if (annotation != null) {
|
||||
//注解上的描述
|
||||
log.set("operation", annotation.value());
|
||||
}
|
||||
|
||||
//登录用户信息
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
Long createUserId = StpKit.USER.getLoginIdAsLong();
|
||||
//TODO SA-TOKEN 暂未整合当前登录人信息,此处仅为临时账号
|
||||
String createUserName = "temp-account";
|
||||
|
||||
log.set("createUserId", createUserId);
|
||||
log.set("createUserName", createUserName);
|
||||
log.set("shopId", shopId);
|
||||
|
||||
log.set("type", LogTypeEnum.INFO.value());
|
||||
if(StrUtil.isNotBlank(errorInfo)){
|
||||
log.set("type", LogTypeEnum.ERROR.value());
|
||||
}
|
||||
log.set("status", status);
|
||||
log.set("requestTime", (int) time);
|
||||
log.set("createTime", LocalDateTime.now());
|
||||
|
||||
//请求相关信息
|
||||
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
|
||||
String ip = JakartaServletUtil.getClientIP(request);
|
||||
log.set("ip", ip);
|
||||
log.set("location", AddressUtil.getRealAddressByIp(ip));
|
||||
log.set("userAgent", request.getHeader(HttpHeaders.USER_AGENT));
|
||||
log.set("requestUri", request.getRequestURI());
|
||||
log.set("requestMethod", request.getMethod());
|
||||
log.set("errorInfo", errorInfo);
|
||||
//请求参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
Map<String, String> param = JakartaServletUtil.getParamMap(request);
|
||||
try {
|
||||
String params = JSON.toJSONString(args[0]);
|
||||
log.set("requestParams", params);
|
||||
boolean isJsonObject = JSONUtil.isTypeJSONObject(params);
|
||||
if(isJsonObject){
|
||||
JSONObject reqData = JSON.parseObject(params);
|
||||
param.forEach(reqData::putIfAbsent);
|
||||
log.set("requestParams", reqData.toJSONString());
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
log.set("id", new SnowFlakeIDKeyGenerator().nextId());
|
||||
//保存到Redis队列里
|
||||
logProducer.saveLog(JSON.toJSONString(log.toUnderlineKeysMap()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.czg.log.enums;
|
||||
|
||||
/**
|
||||
* 日志类型枚举
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public enum LogTypeEnum {
|
||||
/**
|
||||
* INFO
|
||||
*/
|
||||
INFO("info"),
|
||||
/**
|
||||
* ERROR
|
||||
*/
|
||||
ERROR("error");
|
||||
|
||||
private final String value;
|
||||
|
||||
LogTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.czg.log.enums;
|
||||
|
||||
/**
|
||||
* 操作状态枚举
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public enum OperationStatusEnum {
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
FAIL(0),
|
||||
/**
|
||||
* 成功
|
||||
*/
|
||||
SUCCESS(1);
|
||||
|
||||
private final int value;
|
||||
|
||||
OperationStatusEnum(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.czg.log.producer;
|
||||
|
||||
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||
import com.czg.config.RedisCst;
|
||||
import com.czg.service.RedisService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* 日志通过redis队列,异步保存到数据库
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Component
|
||||
public class LogProducer {
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
|
||||
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNamePrefix("log-producer-pool").build();
|
||||
|
||||
ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
|
||||
|
||||
/**
|
||||
* 保存Log到Redis消息队列
|
||||
*/
|
||||
public void saveLog(String log) {
|
||||
String key = RedisCst.SYS_LOG_KEY;
|
||||
|
||||
//异步保存到队列
|
||||
pool.execute(() -> redisService.leftPush(key, log, RedisService.NOT_EXPIRE));
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ package com.czg.config;
|
|||
*/
|
||||
public interface RedisCst {
|
||||
String LOGIN_CODE = "login:code:";
|
||||
String SYS_LOG_KEY = "sys:log:";
|
||||
|
||||
|
||||
|
||||
String SMS_CODE = "sms:code:";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,16 @@ import java.util.concurrent.TimeUnit;
|
|||
@Component
|
||||
public class RedisService {
|
||||
|
||||
/**
|
||||
* 默认过期时长为24小时,单位:秒
|
||||
*/
|
||||
public final static long DEFAULT_EXPIRE = 60 * 60 * 24L;
|
||||
|
||||
/**
|
||||
* 不设置过期时长
|
||||
*/
|
||||
public final static long NOT_EXPIRE = -1L;
|
||||
|
||||
@Autowired
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
|
|
@ -554,4 +564,20 @@ public class RedisService {
|
|||
}
|
||||
}
|
||||
|
||||
public void leftPush(String key, Object value) {
|
||||
leftPush(key, value, DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
public void leftPush(String key, Object value, long expire) {
|
||||
redisTemplate.opsForList().leftPush(key, value);
|
||||
|
||||
if (expire != NOT_EXPIRE) {
|
||||
expire(key, expire);
|
||||
}
|
||||
}
|
||||
|
||||
public Object rightPop(String key) {
|
||||
return redisTemplate.opsForList().rightPop(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
package com.czg.system.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-02-12 11:21
|
||||
*/
|
||||
@Data
|
||||
public class OperationLogDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 日志类型 info-正常日志 error-异常日志
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 用户操作
|
||||
*/
|
||||
private String operation;
|
||||
/**
|
||||
* 请求URI
|
||||
*/
|
||||
private String requestUri;
|
||||
/**
|
||||
* 请求方式
|
||||
*/
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private String requestParams;
|
||||
/**
|
||||
* 请求时长(毫秒)
|
||||
*/
|
||||
private Integer requestTime;
|
||||
/**
|
||||
* 用户代理
|
||||
*/
|
||||
private String userAgent;
|
||||
/**
|
||||
* 操作IP
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 操作地点
|
||||
*/
|
||||
private String location;
|
||||
/**
|
||||
* 状态 0:失败 1:成功
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String errorInfo;
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private Long createUserId;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String createUserName;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime beginTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.czg.system.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.keygen.KeyGenerators;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
*
|
||||
* @author tankaikai
|
||||
* @since 2025-02-12 11:21
|
||||
*/
|
||||
@Data
|
||||
@Table("operation_log")
|
||||
public class OperationLog implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@Id(keyType = KeyType.Generator, value = KeyGenerators.snowFlakeId)
|
||||
private Long id;
|
||||
/**
|
||||
* 日志类型 info-正常日志 error-异常日志
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 用户操作
|
||||
*/
|
||||
private String operation;
|
||||
/**
|
||||
* 请求URI
|
||||
*/
|
||||
private String requestUri;
|
||||
/**
|
||||
* 请求方式
|
||||
*/
|
||||
private String requestMethod;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private String requestParams;
|
||||
/**
|
||||
* 请求时长(毫秒)
|
||||
*/
|
||||
private Integer requestTime;
|
||||
/**
|
||||
* 用户代理
|
||||
*/
|
||||
private String userAgent;
|
||||
/**
|
||||
* 操作IP
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 操作地点
|
||||
*/
|
||||
private String location;
|
||||
/**
|
||||
* 状态 0:失败 1:成功
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private String errorInfo;
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private Long createUserId;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String createUserName;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.czg.system.service;
|
||||
|
||||
import com.czg.system.dto.OperationLogDTO;
|
||||
import com.czg.system.entity.OperationLog;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
* @author tankaikai
|
||||
* @since 2025-02-12 11:35
|
||||
*/
|
||||
public interface OperationLogService extends IService<OperationLog> {
|
||||
|
||||
Page<OperationLogDTO> page(OperationLogDTO param);
|
||||
|
||||
List<OperationLogDTO> list(OperationLogDTO param);
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.czg.utils;
|
||||
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 获取地址类
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@UtilityClass
|
||||
@Slf4j
|
||||
public class AddressUtil {
|
||||
/**
|
||||
* IP地址查询
|
||||
*/
|
||||
public final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
|
||||
/**
|
||||
* 未知地址
|
||||
*/
|
||||
public final String UNKNOWN = "未知";
|
||||
|
||||
public static String getRealAddressByIp(String ip) {
|
||||
// 内网不查询
|
||||
if (NetUtil.isInnerIP(ip)) {
|
||||
return "内网IP";
|
||||
}
|
||||
try {
|
||||
Map<String, Object> paramMap = new HashMap<>(16);
|
||||
paramMap.put("ip", ip);
|
||||
paramMap.put("json", "true");
|
||||
String rspStr = HttpUtil.createGet(IP_URL).header("User-Agent","Apifox/1.0.0 (https://apifox.com)").form(paramMap).timeout(1000*5).execute().body();
|
||||
if (StrUtil.isEmpty(rspStr)) {
|
||||
log.error("获取地理位置异常 {}", ip);
|
||||
return UNKNOWN;
|
||||
}
|
||||
JSONObject obj = JSONUtil.parseObj(rspStr);
|
||||
String region = obj.getStr("pro");
|
||||
String city = obj.getStr("city");
|
||||
return String.format("%s %s", region, city);
|
||||
} catch (Exception e) {
|
||||
log.error("获取地理位置异常 {}", ip);
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
|
||||
package com.czg.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http工具类
|
||||
*
|
||||
* @author admin admin@cashier.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class HttpContextUtil {
|
||||
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
if (requestAttributes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
}
|
||||
|
||||
public static Map<String, String> getParameterMap(HttpServletRequest request) {
|
||||
Enumeration<String> parameters = request.getParameterNames();
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
while (parameters.hasMoreElements()) {
|
||||
String parameter = parameters.nextElement();
|
||||
String value = request.getParameter(parameter);
|
||||
if (StrUtil.isNotBlank(value)) {
|
||||
params.put(parameter, value);
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
public static String getOrigin() {
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
return request.getHeader(HttpHeaders.ORIGIN);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
<module>cash-common-redis</module>
|
||||
<module>cash-common-api-config</module>
|
||||
<module>cash-common-service</module>
|
||||
<module>cash-common-log</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import com.czg.account.dto.auth.UserAuthorizationLoginDTO;
|
|||
import com.czg.account.dto.auth.WechatRawDataDTO;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.account.service.UserAuthorizationService;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
import com.czg.enums.StatusEnum;
|
||||
import com.czg.enums.UserAuthSourceEnum;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.account.service.UserInfoService;
|
||||
import com.czg.service.account.util.AlipayUtil;
|
||||
import com.czg.service.account.util.WechatAuthUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -24,9 +24,9 @@ import javax.annotation.Resource;
|
|||
*/
|
||||
@Service
|
||||
public class UserAuthorizationServiceImpl implements UserAuthorizationService {
|
||||
@Resource
|
||||
//@Resource
|
||||
private WechatAuthUtil wechatAuthUtil;
|
||||
@Resource
|
||||
//@Resource
|
||||
private AlipayUtil alipayUtil;
|
||||
@Resource
|
||||
private UserInfoService userInfoService;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.czg.service.system.mapper;
|
||||
|
||||
import com.czg.system.entity.OperationLog;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
* @author tankaikai
|
||||
* @since 2025-02-12 11:39
|
||||
*/
|
||||
@Mapper
|
||||
public interface OperationLogMapper extends BaseMapper<OperationLog> {
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package com.czg.service.system.service.impl;
|
||||
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.product.entity.ShopProdUnit;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.system.mapper.OperationLogMapper;
|
||||
import com.czg.system.dto.OperationLogDTO;
|
||||
import com.czg.system.entity.OperationLog;
|
||||
import com.czg.system.service.OperationLogService;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Service
|
||||
public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, OperationLog> implements OperationLogService {
|
||||
|
||||
private QueryWrapper buildQueryWrapper(OperationLogDTO param) {
|
||||
QueryWrapper queryWrapper = PageUtil.buildPageQueryWrapper();
|
||||
if (StrUtil.isNotEmpty(param.getOperation())) {
|
||||
queryWrapper.like(OperationLog::getOperation, param.getOperation());
|
||||
}
|
||||
if (param.getBeginTime() != null) {
|
||||
queryWrapper.ge(OperationLog::getCreateTime, param.getBeginTime());
|
||||
}
|
||||
if (param.getEndTime() != null) {
|
||||
queryWrapper.le(OperationLog::getCreateTime, param.getEndTime());
|
||||
}
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
queryWrapper.eq(ShopProdUnit::getShopId, shopId);
|
||||
queryWrapper.orderBy(ShopProdUnit::getId, false);
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<OperationLogDTO> page(OperationLogDTO param) {
|
||||
QueryWrapper queryWrapper = buildQueryWrapper(param);
|
||||
return super.pageAs(PageUtil.buildPage(), queryWrapper, OperationLogDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OperationLogDTO> list(OperationLogDTO param) {
|
||||
QueryWrapper queryWrapper = buildQueryWrapper(param);
|
||||
return super.listAs(queryWrapper, OperationLogDTO.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.system.mapper.OperationLogMapper">
|
||||
|
||||
</mapper>
|
||||
4
pom.xml
4
pom.xml
|
|
@ -71,6 +71,10 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.minidev</groupId>
|
||||
<artifactId>json-smart</artifactId>
|
||||
|
|
|
|||
Loading…
Reference in New Issue