feat: 用户请求日志记录
This commit is contained in:
parent
cd35da82a0
commit
615f6323c5
|
@ -28,6 +28,11 @@
|
|||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- mongodb -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<!-- knife4j -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package cn.bunny.dao.dto.log;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(name = "UserLogin对象", title = "用户登录日志", description = "用户登录日志")
|
||||
public class UserRequestLogDto {
|
||||
|
||||
@Schema(name = "url", title = "请求地址")
|
||||
private String url;
|
||||
|
||||
@Schema(name = "username", title = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(name = "token", title = "登录token")
|
||||
private String token;
|
||||
|
||||
@Schema(name = "ipAddress", title = "登录Ip")
|
||||
private String ipAddress;
|
||||
|
||||
@Schema(name = "ipRegion", title = "登录Ip归属地")
|
||||
private String ipRegion;
|
||||
|
||||
@Schema(name = "userAgent", title = "登录时代理")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(name = "executeTime", title = "执行时间")
|
||||
private String executeTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package cn.bunny.dao.entity.log;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.FieldType;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoId;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户请求日志
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-12-27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Document(collection = "logs_request")
|
||||
@Schema(name = "UserLogin对象", title = "用户登录日志", description = "用户登录日志")
|
||||
public class UserRequestLog {
|
||||
|
||||
@Id
|
||||
@MongoId(targetType = FieldType.STRING)
|
||||
private ObjectId id;
|
||||
|
||||
@Schema(name = "url", title = "请求地址")
|
||||
private String url;
|
||||
|
||||
@Schema(name = "userId", title = "用户Id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(name = "username", title = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(name = "token", title = "登录token")
|
||||
private String token;
|
||||
|
||||
@Schema(name = "ipAddress", title = "登录Ip")
|
||||
private String ipAddress;
|
||||
|
||||
@Schema(name = "ipRegion", title = "登录Ip归属地")
|
||||
private String ipRegion;
|
||||
|
||||
@Schema(name = "userAgent", title = "登录时代理")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
|
||||
private String xRequestedWith;
|
||||
|
||||
@Schema(name = "arg", title = "传入参数")
|
||||
private String arg;
|
||||
|
||||
@Schema(name = "result", title = "执行结果")
|
||||
private String result;
|
||||
|
||||
@Schema(name = "executeTime", title = "执行时间")
|
||||
private String executeTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package cn.bunny.dao.vo.log;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户请求日志
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-12-27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Schema(name = "UserRequestLogVo对象", title = "用户请求日志", description = "用户请求日志")
|
||||
public class UserRequestLogVo {
|
||||
|
||||
@Schema(name = "id", title = "id")
|
||||
private String id;
|
||||
|
||||
@Schema(name = "url", title = "请求地址")
|
||||
private String url;
|
||||
|
||||
@Schema(name = "userId", title = "用户Id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(name = "username", title = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(name = "token", title = "登录token")
|
||||
private String token;
|
||||
|
||||
@Schema(name = "ipAddress", title = "登录Ip")
|
||||
private String ipAddress;
|
||||
|
||||
@Schema(name = "ipRegion", title = "登录Ip归属地")
|
||||
private String ipRegion;
|
||||
|
||||
@Schema(name = "userAgent", title = "登录时代理")
|
||||
private String userAgent;
|
||||
|
||||
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
|
||||
@JsonProperty("xRequestedWith")
|
||||
private String xRequestedWith;
|
||||
|
||||
@Schema(name = "arg", title = "传入参数")
|
||||
private String arg;
|
||||
|
||||
@Schema(name = "result", title = "执行结果")
|
||||
private String result;
|
||||
|
||||
@Schema(name = "executeTime", title = "执行时间")
|
||||
private String executeTime;
|
||||
|
||||
}
|
|
@ -37,11 +37,6 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!-- mongodb -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<!-- admin 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.Map;
|
|||
@Component
|
||||
public class JobExecuteAop {
|
||||
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS);
|
||||
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS);
|
||||
|
||||
@Autowired
|
||||
private ScheduleExecuteLogMapper scheduleExecuteLogMapper;
|
||||
|
@ -41,7 +41,7 @@ public class JobExecuteAop {
|
|||
|
||||
// 格式化时间
|
||||
LocalDateTime startLocalDateTime = LocalDateTime.now();
|
||||
String startExecuteTIme = startLocalDateTime.format(dateTimeFormatter);
|
||||
String startExecuteTime = startLocalDateTime.format(dateTimeFormatter);
|
||||
|
||||
// 获取上下文map集合
|
||||
Map<String, Object> jobDataMap = context.getJobDetail().getJobDataMap().getWrappedMap();
|
||||
|
@ -62,7 +62,7 @@ public class JobExecuteAop {
|
|||
executeLogJson.setResult(JobEnums.UNFINISHED.getType());
|
||||
executeLogJson.setStatus(JobEnums.RUNNING.getType());
|
||||
executeLogJson.setMessage(JobEnums.RUNNING.getSummary());
|
||||
executeLogJson.setOperationTime(startExecuteTIme);
|
||||
executeLogJson.setOperationTime(startExecuteTime);
|
||||
executeLogJson.setExecuteParams(jobDataMap);
|
||||
executeLog.setExecuteResult(JSON.toJSONString(executeLogJson));
|
||||
scheduleExecuteLogMapper.insert(executeLog);
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package cn.bunny.services.aop;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.common.service.utils.ip.IpUtil;
|
||||
import cn.bunny.dao.entity.log.UserRequestLog;
|
||||
import cn.bunny.dao.pojo.constant.LocalDateTimeConstant;
|
||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import cn.bunny.services.repository.UserRequestLogRepository;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
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 java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Aspect
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserRequestLogAop {
|
||||
|
||||
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS);
|
||||
|
||||
@Autowired
|
||||
private UserRequestLogRepository userRequestLogRepository;
|
||||
|
||||
@Around(value = "execution(* cn.bunny.services.controller.*.*.*(..)) && !@annotation(cn.bunny.services.aop.annotation.ExcludeRequestLog)")
|
||||
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
LoginVo loginVo = BaseContext.getLoginVo();
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
// 执行时间
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
String executeTime = localDateTime.format(dateTimeFormatter);
|
||||
|
||||
// 获取IP地址并更新用户登录信息
|
||||
String ipAddr = IpUtil.getCurrentUserIpAddress().getIpAddr();
|
||||
String ipRegion = IpUtil.getCurrentUserIpAddress().getIpRegion();
|
||||
|
||||
// 日期内容
|
||||
UserRequestLog userRequestLog = new UserRequestLog();
|
||||
userRequestLog.setUserId(BaseContext.getUserId());
|
||||
userRequestLog.setUsername(BaseContext.getUsername());
|
||||
userRequestLog.setToken(loginVo != null ? loginVo.getToken() : "");
|
||||
userRequestLog.setIpAddress(ipAddr);
|
||||
userRequestLog.setIpRegion(ipRegion);
|
||||
userRequestLog.setExecuteTime(executeTime);
|
||||
|
||||
|
||||
userRequestLog.setArg(JSON.toJSONString(args));
|
||||
|
||||
// 当前请求request
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request;
|
||||
if (requestAttributes != null) {
|
||||
request = requestAttributes.getRequest();
|
||||
|
||||
// 获取请求URL
|
||||
userRequestLog.setUrl(request.getRequestURI());
|
||||
|
||||
// 获取User-Agent
|
||||
String userAgent = request.getHeader("User-Agent");
|
||||
userRequestLog.setUserAgent(userAgent);
|
||||
|
||||
// 获取X-Requested-With
|
||||
String xRequestedWith = request.getHeader("X-Requested-With");
|
||||
userRequestLog.setXRequestedWith(xRequestedWith);
|
||||
}
|
||||
Object proceed = joinPoint.proceed();
|
||||
|
||||
// 执行结果
|
||||
String result = JSON.toJSONString(proceed);
|
||||
userRequestLog.setResult(result);
|
||||
userRequestLogRepository.insert(userRequestLog);
|
||||
|
||||
return proceed;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package cn.bunny.services.aop.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
public @interface ExcludeRequestLog {
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.controller;
|
||||
package cn.bunny.services.controller.system;
|
||||
|
||||
import cn.bunny.dao.dto.financial.HomeDto;
|
||||
import cn.bunny.dao.pojo.result.Result;
|
|
@ -0,0 +1,56 @@
|
|||
package cn.bunny.services.controller.system;
|
||||
|
||||
import cn.bunny.dao.dto.log.UserRequestLogDto;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.pojo.result.Result;
|
||||
import cn.bunny.dao.vo.log.UserRequestLogVo;
|
||||
import cn.bunny.services.aop.annotation.ExcludeRequestLog;
|
||||
import cn.bunny.services.service.system.UserRequestLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户请求日志表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-10-19 01:01:01
|
||||
*/
|
||||
@Tag(name = "用户登录日志", description = "用户登录日志相关接口")
|
||||
@RestController
|
||||
@RequestMapping("admin/userRequestLog")
|
||||
public class UserRequestLogController {
|
||||
|
||||
@Autowired
|
||||
private UserRequestLogService userRequestLogService;
|
||||
|
||||
@Operation(summary = "分页查询用户请求日志", description = "分页查询用户请求日志")
|
||||
@ExcludeRequestLog
|
||||
@GetMapping("getRequestLogList/{page}/{limit}")
|
||||
public Mono<Result<PageResult<UserRequestLogVo>>> getRequestLogList(
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@PathVariable("page") Integer page,
|
||||
@Parameter(name = "limit", description = "每页记录数", required = true)
|
||||
@PathVariable("limit") Integer limit,
|
||||
UserRequestLogDto dto) {
|
||||
Pageable pageable = PageRequest.of(page, limit);
|
||||
PageResult<UserRequestLogVo> pageResult = userRequestLogService.getRequestLogList(pageable, dto);
|
||||
return Mono.just(Result.success(pageResult));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除用户请求日志", description = "删除用户请求日志")
|
||||
@DeleteMapping("deletedRequestLogByIds")
|
||||
public Mono<Result<String>> deletedRequestLogByIds(@RequestBody List<String> ids) {
|
||||
userRequestLogService.deletedRequestLogByIds(ids);
|
||||
return Mono.just(Result.success());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package cn.bunny.services.repository;
|
||||
|
||||
import cn.bunny.dao.entity.log.UserRequestLog;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
public interface UserRequestLogRepository extends MongoRepository<UserRequestLog, ObjectId> {
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package cn.bunny.services.service.system;
|
||||
|
||||
import cn.bunny.dao.dto.log.UserRequestLogDto;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.vo.log.UserRequestLogVo;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UserRequestLogService {
|
||||
|
||||
/**
|
||||
* 分页查询用户请求日志
|
||||
*
|
||||
* @param pageable 分页
|
||||
* @param dto 表单查询
|
||||
* @return 分页结果
|
||||
*/
|
||||
PageResult<UserRequestLogVo> getRequestLogList(Pageable pageable, UserRequestLogDto dto);
|
||||
|
||||
/**
|
||||
* 删除用户请求日志
|
||||
*
|
||||
* @param ids 删除的Id
|
||||
*/
|
||||
void deletedRequestLogByIds(List<String> ids);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package cn.bunny.services.service.system.impl;
|
||||
|
||||
import cn.bunny.dao.dto.log.UserRequestLogDto;
|
||||
import cn.bunny.dao.entity.log.UserRequestLog;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import cn.bunny.dao.vo.log.UserRequestLogVo;
|
||||
import cn.bunny.services.repository.UserRequestLogRepository;
|
||||
import cn.bunny.services.service.system.UserRequestLogService;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserRequestLogServiceImpl implements UserRequestLogService {
|
||||
|
||||
@Autowired
|
||||
private UserRequestLogRepository userRequestLogRepository;
|
||||
|
||||
/**
|
||||
* 分页查询用户请求日志
|
||||
*
|
||||
* @param pageable 分页
|
||||
* @param dto 表单查询
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Override
|
||||
public PageResult<UserRequestLogVo> getRequestLogList(Pageable pageable, UserRequestLogDto dto) {
|
||||
// 封装条件
|
||||
UserRequestLog userRequestLog = new UserRequestLog();
|
||||
BeanUtils.copyProperties(dto, userRequestLog);
|
||||
|
||||
// 构建条件
|
||||
Example<UserRequestLog> example = Example.of(userRequestLog);
|
||||
Page<UserRequestLog> page = userRequestLogRepository.findAll(example, pageable);
|
||||
List<UserRequestLogVo> content = page.getContent().stream().map(requestLog -> {
|
||||
UserRequestLogVo vo = new UserRequestLogVo();
|
||||
BeanUtils.copyProperties(requestLog, vo);
|
||||
|
||||
String hexString = requestLog.getId().toHexString();
|
||||
vo.setId(hexString);
|
||||
return vo;
|
||||
}).toList();
|
||||
|
||||
return PageResult.<UserRequestLogVo>builder()
|
||||
.list(content)
|
||||
.pageNo((long) page.getNumber())
|
||||
.pageSize((long) page.getSize())
|
||||
.total(page.getTotalElements())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户请求日志
|
||||
*
|
||||
* @param ids 删除的Id
|
||||
*/
|
||||
@Override
|
||||
public void deletedRequestLogByIds(List<String> ids) {
|
||||
List<ObjectId> idList = ids.stream().map(ObjectId::new).toList();
|
||||
userRequestLogRepository.deleteAllById(idList);
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,8 @@ spring:
|
|||
password: ${bunny.mongodb.password}
|
||||
authentication-database: ${bunny.mongodb.authentication-database}
|
||||
additional-hosts: ${bunny.mongodb.additional-hosts}
|
||||
|
||||
field-naming-strategy: org.springframework.data.mapping.model.SnakeCaseFieldNamingStrategy
|
||||
|
||||
redis:
|
||||
host: ${bunny.redis.host}
|
||||
port: ${bunny.redis.port}
|
||||
|
|
Loading…
Reference in New Issue