add
This commit is contained in:
39
qiaoba-modules/qiaoba-module-log/pom.xml
Normal file
39
qiaoba-modules/qiaoba-module-log/pom.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<artifactId>qiaoba-modules</artifactId>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>qiaoba-module-log</artifactId>
|
||||
|
||||
<description>日志模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-api-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-api-log</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-datasource</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-doc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.qiaoba</groupId>
|
||||
<artifactId>qiaoba-common-poi</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,192 @@
|
||||
package com.qiaoba.module.log.aspect;
|
||||
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.qiaoba.api.auth.utils.TokenUtil;
|
||||
import com.qiaoba.api.job.annotation.Log;
|
||||
import com.qiaoba.common.base.enums.BaseEnum;
|
||||
import com.qiaoba.common.web.utils.IpUtil;
|
||||
import com.qiaoba.module.log.entity.SysUseLog;
|
||||
import com.qiaoba.module.log.service.SysUserLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志记录切面
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @date 1/31/23 4:23 PM
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class LogAspect {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
private static final String METHOD_TEMPLATE = "{}.{}()";
|
||||
|
||||
private final SysUserLogService logService;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
|
||||
/**
|
||||
* 处理完请求后执行
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
|
||||
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
|
||||
handleLog(joinPoint, controllerLog, null, jsonResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param e 异常
|
||||
*/
|
||||
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
|
||||
handleLog(joinPoint, controllerLog, e, null);
|
||||
}
|
||||
|
||||
private void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
|
||||
try {
|
||||
// *========数据库日志=========*//
|
||||
SysUseLog sysLog = new SysUseLog();
|
||||
sysLog.setStatus(BaseEnum.NORMAL.getCode());
|
||||
// 请求的地址
|
||||
String ip = ServletUtil.getClientIP(request);
|
||||
sysLog.setIp(ip);
|
||||
sysLog.setOperationLocation(IpUtil.getIpAddr(ip));
|
||||
sysLog.setOperatorName(TokenUtil.analyzeUsername(request));
|
||||
sysLog.setUrl(request.getRequestURI());
|
||||
|
||||
|
||||
if (e != null) {
|
||||
sysLog.setStatus(BaseEnum.NO.getCode());
|
||||
sysLog.setErrorMsg(e.getMessage());
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
sysLog.setMethod(StrUtil.format(METHOD_TEMPLATE, className, methodName));
|
||||
// 设置请求方式
|
||||
sysLog.setRequestMethod(request.getMethod());
|
||||
sysLog.setOperationTime(new Date());
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(joinPoint, controllerLog, sysLog, jsonResult);
|
||||
// 保存数据库
|
||||
logService.insert(sysLog);
|
||||
} catch (Exception exp) {
|
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常==");
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param log 日志
|
||||
* @param sysLog 操作日志
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
private void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysUseLog sysLog, Object jsonResult) throws Exception {
|
||||
// 设置action动作
|
||||
sysLog.setBusinessType(log.businessType().ordinal());
|
||||
// 设置标题
|
||||
sysLog.setTitle(log.title());
|
||||
// 设置操作人类别
|
||||
sysLog.setOperatorType(log.operatorType().ordinal());
|
||||
// 是否需要保存request,参数和值
|
||||
if (log.isSaveRequestData()) {
|
||||
// 获取参数的信息,传入到数据库中。
|
||||
setRequestValue(joinPoint, sysLog);
|
||||
}
|
||||
// 是否需要保存response,参数和值
|
||||
if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) {
|
||||
sysLog.setJsonResult(JSONUtil.toJsonStr(jsonResult));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的参数,放到log中
|
||||
*
|
||||
* @param sysLog 操作日志
|
||||
* @throws Exception 异常
|
||||
*/
|
||||
private void setRequestValue(JoinPoint joinPoint, SysUseLog sysLog) throws Exception {
|
||||
String requestMethod = sysLog.getRequestMethod();
|
||||
if (!HttpMethod.GET.name().equals(requestMethod)) {
|
||||
String params = argsArrayToString(joinPoint.getArgs());
|
||||
sysLog.setOperationParam(params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray) {
|
||||
StringBuilder params = new StringBuilder();
|
||||
if (paramsArray != null && paramsArray.length > 0) {
|
||||
for (Object o : paramsArray) {
|
||||
if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
|
||||
String jsonObj = JSONUtil.toJsonStr(o);
|
||||
params.append(jsonObj).append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
return params.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要过滤的对象。
|
||||
*
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private boolean isFilterObject(final Object o) {
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray()) {
|
||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||
Collection collection = (Collection) o;
|
||||
for (Object value : collection) {
|
||||
return value instanceof MultipartFile;
|
||||
}
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = (Map) o;
|
||||
for (Object value : map.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) value;
|
||||
return entry.getValue() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
||||
|| o instanceof BindingResult;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.qiaoba.module.log.controller;
|
||||
|
||||
import com.qiaoba.api.job.annotation.Log;
|
||||
import com.qiaoba.api.job.enums.BusinessType;
|
||||
import com.qiaoba.common.base.result.AjaxResult;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.common.poi.utils.ExcelUtil;
|
||||
import com.qiaoba.module.log.entity.SysUseLog;
|
||||
import com.qiaoba.module.log.entity.param.SysUseLogParam;
|
||||
import com.qiaoba.module.log.service.SysUserLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 操作日志 web层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2022-09-22 04:20:28
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/use-log")
|
||||
@RequiredArgsConstructor
|
||||
public class SysUseLogController {
|
||||
|
||||
private final SysUserLogService sysUserLogService;
|
||||
|
||||
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SysUseLogParam param, PageQuery pageQuery) {
|
||||
return sysUserLogService.selectPageList(param, pageQuery);
|
||||
}
|
||||
|
||||
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, SysUseLogParam param) {
|
||||
List<SysUseLog> list = sysUserLogService.selectList(param);
|
||||
ExcelUtil.exportExcel(list, SysUseLog.class, "操作日志", response);
|
||||
}
|
||||
|
||||
@Log(title = "操作日志", businessType = BusinessType.CLEAN)
|
||||
@DeleteMapping("/clean")
|
||||
public AjaxResult clean() {
|
||||
sysUserLogService.cleanUseLog();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.qiaoba.module.log.entity;
|
||||
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 使用日志 sys_use_log
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @date 1/31/23 4:23 PM
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_use_log")
|
||||
public class SysUseLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Excel(name = "操作序号")
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "操作模块")
|
||||
private String title;
|
||||
|
||||
@Excel(name = "业务类型", replace = {"其他_0", "新增_1", "修改_2", "删除_3", "授权_4", "导出_5", "导入_6", "强退_7", "生成代码_8", "清空数据_9"})
|
||||
private Integer businessType;
|
||||
|
||||
@Excel(name = "请求方法")
|
||||
private String method;
|
||||
|
||||
@Excel(name = "请求方式")
|
||||
private String requestMethod;
|
||||
|
||||
@Excel(name = "操作类别", replace = {"其他_0", "后台用户_1", "手机端用户_2"})
|
||||
private Integer operatorType;
|
||||
|
||||
@Excel(name = "操作人员")
|
||||
private String operatorName;
|
||||
|
||||
private String deptName;
|
||||
|
||||
@Excel(name = "请求地址")
|
||||
private String url;
|
||||
|
||||
@Excel(name = "操作地址")
|
||||
private String ip;
|
||||
|
||||
@Excel(name = "操作地点")
|
||||
private String operationLocation;
|
||||
|
||||
@Excel(name = "请求参数")
|
||||
private String operationParam;
|
||||
|
||||
@Excel(name = "返回参数")
|
||||
private String jsonResult;
|
||||
|
||||
@Excel(name = "状态", replace = {"正常_0", "异常_1"})
|
||||
private String status;
|
||||
|
||||
@Excel(name = "错误消息")
|
||||
private String errorMsg;
|
||||
|
||||
@Excel(name = "操作时间", format = "yyyy-MM-dd HH:mm:ss", width = 30)
|
||||
private Date operationTime;
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.qiaoba.module.log.entity.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 使用日志 查询参数
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/7/5 14:24
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class SysUseLogParam implements Serializable {
|
||||
|
||||
private String title;
|
||||
|
||||
private String operatorName;
|
||||
|
||||
private Integer businessType;
|
||||
|
||||
private Integer status;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date beginTime;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endTime;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.qiaoba.module.log.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.qiaoba.module.log.entity.SysUseLog;
|
||||
|
||||
/**
|
||||
* 使用日志 数据层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/7/5 13:52
|
||||
*/
|
||||
public interface SysUserLogMapper extends BaseMapper<SysUseLog> {
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.qiaoba.module.log.service;
|
||||
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.module.log.entity.SysUseLog;
|
||||
import com.qiaoba.module.log.entity.param.SysUseLogParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 使用日志 服务层
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/7/5 13:51
|
||||
*/
|
||||
public interface SysUserLogService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param sysUseLog sysUseLog
|
||||
*/
|
||||
void insert(SysUseLog sysUseLog);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @param pageQuery 分页信息
|
||||
* @return list
|
||||
*/
|
||||
TableDataInfo selectPageList(SysUseLogParam param, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return list
|
||||
*/
|
||||
List<SysUseLog> selectList(SysUseLogParam param);
|
||||
|
||||
/**
|
||||
* 清空日志
|
||||
*/
|
||||
void cleanUseLog();
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.qiaoba.module.log.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.qiaoba.common.database.entity.PageQuery;
|
||||
import com.qiaoba.common.database.entity.TableDataInfo;
|
||||
import com.qiaoba.module.log.entity.SysUseLog;
|
||||
import com.qiaoba.module.log.entity.param.SysUseLogParam;
|
||||
import com.qiaoba.module.log.mapper.SysUserLogMapper;
|
||||
import com.qiaoba.module.log.service.SysUserLogService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 使用日志 服务层实现
|
||||
*
|
||||
* @author ailanyin
|
||||
* @version 1.0
|
||||
* @since 2023/7/5 13:51
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SysUserLogServiceImpl implements SysUserLogService {
|
||||
|
||||
private final SysUserLogMapper sysUserLogMapper;
|
||||
|
||||
@Override
|
||||
public void insert(SysUseLog sysUseLog) {
|
||||
sysUserLogMapper.insert(sysUseLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo selectPageList(SysUseLogParam param, PageQuery pageQuery) {
|
||||
return TableDataInfo.build(sysUserLogMapper.selectPage(pageQuery.build(), param2Wrapper(param)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysUseLog> selectList(SysUseLogParam param) {
|
||||
return sysUserLogMapper.selectList(param2Wrapper(param));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUseLog() {
|
||||
sysUserLogMapper.delete(param2Wrapper(new SysUseLogParam()));
|
||||
}
|
||||
|
||||
private QueryWrapper<SysUseLog> param2Wrapper(SysUseLogParam param) {
|
||||
QueryWrapper<SysUseLog> wrapper = new QueryWrapper<>();
|
||||
wrapper.lambda()
|
||||
.orderByDesc(SysUseLog::getOperationTime)
|
||||
.between(ObjectUtil.isNotEmpty(param.getBeginTime()), SysUseLog::getOperationTime, param.getBeginTime(), param.getEndTime())
|
||||
.like(StrUtil.isNotBlank(param.getTitle()), SysUseLog::getTitle, param.getTitle())
|
||||
.like(StrUtil.isNotBlank(param.getOperatorName()), SysUseLog::getOperatorName, param.getOperatorName())
|
||||
.eq(ObjectUtil.isNotEmpty(param.getBusinessType()), SysUseLog::getBusinessType, param.getBusinessType())
|
||||
.eq(ObjectUtil.isNotEmpty(param.getStatus()), SysUseLog::getStatus, param.getStatus());
|
||||
return wrapper;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user