Browse Source

新增操作日志

zhongwei
段飞宇 2 years ago
parent
commit
12858d28e9
  1. 1
      hzims-biz-common/pom.xml
  2. 48
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/annotation/OperationAnnotation.java
  3. 259
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/aop/SysLogAspect.java
  4. 118
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogConsumer.java
  5. 43
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogQueue.java
  6. 33
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessStatus.java
  7. 73
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessType.java
  8. 45
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/OperatorType.java
  9. 29
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/SysLogFeignService.java
  10. 30
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/fallback/SysLogFeignServiceFallback.java
  11. 88
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/CharsetKit.java
  12. 1009
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/Convert.java
  13. 93
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/StrFormatter.java
  14. 145
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/to/SysLogTo.java
  15. 130
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/Constants.java
  16. 567
      hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/StringUtils.java
  17. 21
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/MiddleApplication.java
  18. 104
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/mybatisplus/CodeGenerator.java
  19. 60
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/controller/SysLogController.java
  20. 191
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/entity/SysLog.java
  21. 16
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/mapper/SysLogMapper.java
  22. 16
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/SysLogService.java
  23. 20
      hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/impl/SysLogServiceImpl.java
  24. 38
      hzims-service/hzims-middle/src/main/resources/application.yml
  25. 7
      hzims-service/hzims-middle/src/main/resources/bootstrap.yml
  26. 5
      hzims-service/hzims-middle/src/main/resources/mapper/SysLogMapper.xml
  27. 15
      hzims-service/hzims-middle/src/test/java/com/hnac/hzims/middle/MiddleApplicationTests.java
  28. 1
      hzims-service/pom.xml
  29. 6
      hzims-service/ticket/pom.xml
  30. 4
      hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/TicketApplication.java
  31. 267
      hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/ApiLogAspect.java
  32. 42
      hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/OperationAnnotation.java
  33. 80
      hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/SysLog.java
  34. 117
      hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/processflow/controller/ProcessTypeController.java

1
hzims-biz-common/pom.xml

@ -41,6 +41,7 @@
<artifactId>blade-starter-datascope</artifactId> <artifactId>blade-starter-datascope</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

48
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/annotation/OperationAnnotation.java

@ -0,0 +1,48 @@
package com.hnac.hzims.common.logs.annotation;
import com.hnac.hzims.common.logs.enums.BusinessType;
import com.hnac.hzims.common.logs.enums.OperatorType;
import java.lang.annotation.*;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/3/29 11:38
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER, ElementType.METHOD })
public @interface OperationAnnotation {
/**
* 操作模块
* @return
*/
String title() default "操作模块";
/**
* 系统类型网页端app端
*/
OperatorType operatorType() default OperatorType.OTHER;
/**
* 操作类型
* @return
*/
BusinessType businessType() default BusinessType.OTHER;
/**
* 是否保存响应的参数
*/
public boolean isSaveResponseData() default true;
/**
* 功能说明
* @return
*/
String action() default "功能说明";
}

259
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/aop/SysLogAspect.java

@ -0,0 +1,259 @@
package com.hnac.hzims.common.logs.aop;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.hnac.hzims.common.logs.annotation.OperationAnnotation;
import com.hnac.hzims.common.logs.consumer.SysLogQueue;
import com.hnac.hzims.common.logs.to.SysLogTo;
import com.hnac.hzims.common.logs.enums.BusinessStatus;
import com.hnac.hzims.common.logs.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author dfy
* @date 2023/3/29
* @description: 操作日志切面处理类
*/
@Aspect
@Component
@Slf4j
public class SysLogAspect {
@Autowired
private ServerInfo serverInfo;
@Autowired
private BladeProperties bladeProperties;
@Autowired
private SysLogQueue sysLogQueue;
/**
* 请求地址
*/
private String requestPath = null;
/**
* 操作人
*/
private String userName = null;
/**
* 请求
*/
private HttpServletRequest request = null;
private Long userId = -1L;
private StopWatch stopWatch = new StopWatch();
/**
* 设置操作日志切入点 在注解的位置切入代码
*/
@Pointcut("@annotation(com.hnac.hzims.common.logs.annotation.OperationAnnotation)")
public void logPointCut() {
}
/**
* @param joinPoint
* @Description 前置通知 方法调用前触发 记录开始时间,从session中获取操作人
*/
@Before(value = "logPointCut()")
public void before(JoinPoint joinPoint) {
stopWatch.start();
log.info("前置通知");
}
/**
* @param joinPoint
* @Description 后置通知 方法调用后触发 记录结束时间 ,操作人 ,入参等
*/
@AfterReturning(value = "logPointCut()", returning = "jsonResult")
public void after(JoinPoint joinPoint, Object jsonResult) {
log.info("=========返回通知==============");
request = getHttpServletRequest();
handleLog(joinPoint, jsonResult, null);
}
/**
* @param joinPoint
* @return
* @Description 获取入参方法参数
*/
public Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
Map<String, Object> param = new HashMap<>(16);
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for (int i = 0; i < paramNames.length; i++) {
if (paramValues[i] instanceof Integer || paramValues[i] instanceof String) {
param.put(paramNames[i], paramValues[i]);
}
}
return param;
}
/**
* @Description: 获取request
*/
public HttpServletRequest getHttpServletRequest() {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
return request;
}
/**
* @param joinPoint
* @Description 异常通知
*/
@AfterThrowing(pointcut = "logPointCut()", throwing = "e")
public void throwing(JoinPoint joinPoint, Exception e) {
log.info("=========异常通知==============");
handleLog(joinPoint, null, e);
}
/**
* 转换request 请求参数
*
* @param paramMap request获取的参数数组
*/
public Map<String, String> converMap(Map<String, String[]> paramMap) {
Map<String, String> rtnMap = new HashMap<String, String>();
for (String key : paramMap.keySet()) {
rtnMap.put(key, paramMap.get(key)[0]);
}
return rtnMap;
}
/**
* 转换异常信息为字符串
*
* @param exceptionName 异常名称
* @param exceptionMessage 异常信息
* @param elements 堆栈信息
*/
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
StringBuffer strbuff = new StringBuffer();
for (StackTraceElement stet : elements) {
strbuff.append(stet + "\n");
}
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
return message;
}
/**
* 处理操作日志结果集
*
* @param joinPoint
* @param jsonResult
* @param exception
*/
private void handleLog(JoinPoint joinPoint, Object jsonResult, Exception exception) {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class<?> targetClass = null;
try {
targetClass = Class.forName(targetName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = targetClass.getMethods();
String title;
String action;
String businessType;
String operatorType;
Class<?>[] clazzs;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
clazzs = method.getParameterTypes();
if (clazzs != null && clazzs.length == arguments.length && method.getAnnotation(OperationAnnotation.class) != null) {
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
methodName = className + "." + methodName;
request = getHttpServletRequest();
requestPath = request.getServletPath();
OperationAnnotation annotation = method.getAnnotation(OperationAnnotation.class);
title = annotation.title();
action = annotation.action();
businessType = annotation.businessType().getValue();
operatorType = annotation.operatorType().getValue();
// 获取当前用户信息
userName = AuthUtil.getUserAccount(request);
userId = AuthUtil.getUserId(request);
SysLogTo sysLog = new SysLogTo();
if (StringUtils.isBlank(userName) && userId == -1) {
userName = "当前用户未登录";
}
sysLog.setOperationUserName(userName);
sysLog.setOperationUserId(userId);
sysLog.setTenantId(Func.toStr(AuthUtil.getTenantId(), BladeConstant.ADMIN_TENANT_ID));
sysLog.setLocalIp(WebUtil.getIP(request));// 请求IP
stopWatch.stop();
sysLog.setCostTime(stopWatch.getTotalTimeMillis() + "ms");
sysLog.setPath(requestPath);
sysLog.setTitle(title);
sysLog.setAction(action);
sysLog.setOperatorType(operatorType);
sysLog.setBusinessType(businessType);
sysLog.setParameter(getNameAndValue(joinPoint).toString());
sysLog.setMethodClass(className);
sysLog.setMethodName(methodName);
sysLog.setServerName(bladeProperties.getName());
sysLog.setServerHost(serverInfo.getHostName());
sysLog.setServerIp(serverInfo.getIpWithPort());
sysLog.setEnv(bladeProperties.getEnv());
sysLog.setMethod(request.getMethod());
sysLog.setUserAgent(request.getHeader(WebUtil.USER_AGENT_HEADER));
sysLog.setOperationTime(LocalDateTime.now());
//返回结果集
if (ObjectUtils.isNotEmpty(jsonResult)) {
sysLog.setStatus(BusinessStatus.SUCCESS.getKey());
sysLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
}
//异常结果集
if (exception != null) {
sysLog.setStatus(BusinessStatus.FAIL.getKey());
sysLog.setErrorMsg(StringUtils.substring(exception.getMessage(), 0, 2000));
}
//保存到阻塞队列里
sysLogQueue.add(sysLog);
}
}
}
}
}

118
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogConsumer.java

@ -0,0 +1,118 @@
package com.hnac.hzims.common.logs.consumer;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.hnac.hzims.common.logs.to.SysLogTo;
import com.hnac.hzims.common.logs.fegin.SysLogFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 执行异步线程操作
* @Author dfy
* @Version v1.0
* @Serial 1.0
* @Date 2023/4/3 14:00
*/
@Slf4j
@Component
public class SysLogConsumer implements Runnable {
/**
* 默认16
*/
private static final int DEFAULT_BATCH_SIZE = 16;
@Resource
private SysLogQueue auditLogQueue;
/**
* 批次数
*/
private int batchSize = DEFAULT_BATCH_SIZE;
@Autowired
private SysLogFeignService sysLogFeignService;
/**
* 默认为true
*/
private boolean active = true;
private Thread thread;
/**
* 启动线程
*/
@PostConstruct
public void init() {
thread = new Thread(this);
thread.start();
}
/**
* 使用该注解在项目结束的舒缓关闭
*/
@PreDestroy
public void close() {
active = false;
}
/**
* 执行线程操作
*/
@Override
public void run() {
while (active) {
execute();
}
}
/**
* 执行业务处理操作新增日志记录
*/
public void execute() {
List<SysLogTo> sysLogs = new ArrayList<>();
try {
int size = 0;
while (size < batchSize) {
//从队列中取出一个
SysLogTo sysLog = auditLogQueue.poll();
if (sysLog == null) {
break;
}
sysLogs.add(sysLog);
size++;
}
} catch (InterruptedException e) {
e.printStackTrace();
log.error(e.toString());
}
//如果当前的日志list不为空
if (CollectionUtils.isNotEmpty(sysLogs)) {
log.info("日志操作数据:" + sysLogs);
// TODO: 2023/4/4 添加到数据库
try {
// TODO: 2023/4/4 后期采取mq+elk实现,可以提高效率,操作日志数据越来越大,查询效率变大,提高性能
sysLogFeignService.saveBatch(sysLogs);
} catch (Exception e) {
// TODO: 2023/4/4 出现异常呢,
e.printStackTrace();
}
}
}
}

43
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogQueue.java

@ -0,0 +1,43 @@
package com.hnac.hzims.common.logs.consumer;
import com.hnac.hzims.common.logs.to.SysLogTo;
import org.springframework.stereotype.Component;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 定义队列
* @Author dfy
* @Version v1.0
* @Serial 1.0
* @Date 2023/4/3 14:01
*/
@Component
public class SysLogQueue {
/**
* BlockingDequeue为双端阻塞队列blockingQueue阻塞队列
*/
private BlockingQueue<SysLogTo> blockingQueue = new LinkedBlockingQueue<>();
/**
* 存入数据
* @param auditLog
*/
public void add(SysLogTo auditLog) {
blockingQueue.add(auditLog);
}
/**
* poll从队列的头部获取到信息
* @return
* @throws InterruptedException
*/
public SysLogTo poll() throws InterruptedException {
//每秒钟执行一次
return blockingQueue.poll(1, TimeUnit.SECONDS);
}
}

33
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessStatus.java

@ -0,0 +1,33 @@
package com.hnac.hzims.common.logs.enums;
import lombok.Getter;
/**
* 操作状态
*
* @author ruoyi
*
*/
public enum BusinessStatus
{
/**
* 成功
*/
SUCCESS(0,"执行成功"),
/**
* 异常
*/
FAIL(1,"执行异常");
@Getter
private Integer key;
@Getter
private String value;
BusinessStatus(Integer key,String value){
this.key = key;
this.value = value;
}
}

73
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessType.java

@ -0,0 +1,73 @@
package com.hnac.hzims.common.logs.enums;
import lombok.Getter;
/**
* 业务操作类型
*
* @author ruoyi
*/
public enum BusinessType
{
/**
* 其它
*/
OTHER("OTHER","其他"),
/**
* 新增
*/
INSERT("INSERT","新增"),
/**
* 修改
*/
UPDATE("UPDATE","修改"),
/**
* 删除
*/
DELETE("DELETE","删除"),
/**
* 授权
*/
GRANT("GRANT","授权"),
/**
* 导出
*/
EXPORT("EXPORT","导出"),
/**
* 导入
*/
IMPORT("IMPORT","导入"),
/**
* 强退
*/
FORCE("FORCE","强退"),
/**
* 查询
*/
GENCODE("GENCODE","查询"),
/**
* 清空数据
*/
CLEAN("CLEAN","清空数据");
@Getter
private String key;
@Getter
private String value;
BusinessType(String key,String value){
this.key = key;
this.value = value;
}
}

45
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/OperatorType.java

@ -0,0 +1,45 @@
package com.hnac.hzims.common.logs.enums;
import lombok.Getter;
/**
* 操作人类别
*
* @author ruoyi
*/
public enum OperatorType
{
/**
* 其它
*/
OTHER("OTHER","其它"),
/**
* 后台用户
*/
MANAGE("MANAGE","后台用户"),
/**
* web
*/
MOBILE("MOBILE","web端"),
/**
* app
*/
APPSYSTEMS("APPSYSTEMS","app端");
@Getter
private String key;
@Getter
private String value;
OperatorType(String key,String value){
this.key = key;
this.value = value;
}
}

29
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/SysLogFeignService.java

@ -0,0 +1,29 @@
package com.hnac.hzims.common.logs.fegin;
import com.hnac.hzims.common.logs.to.SysLogTo;
import com.hnac.hzims.common.logs.fegin.fallback.SysLogFeignServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/4/3 13:46
*/
@Repository
@FeignClient(value = "hzims-middle",fallback = SysLogFeignServiceFallback.class)
public interface SysLogFeignService {
/**
* 报存日志操作
*
* @param sysLogs
*/
@PostMapping("/systemlog/sys-log/batchSave")
void saveBatch(@RequestBody List<SysLogTo> sysLogs);
}

30
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/fallback/SysLogFeignServiceFallback.java

@ -0,0 +1,30 @@
package com.hnac.hzims.common.logs.fegin.fallback;
import com.hnac.hzims.common.logs.to.SysLogTo;
import com.hnac.hzims.common.logs.fegin.SysLogFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/4/4 9:45
*/
@Slf4j
@Service
public class SysLogFeignServiceFallback implements SysLogFeignService {
/**
* 报存日志操作
*
* @param sysLogs
*/
@Override
public void saveBatch(List<SysLogTo> sysLogs) {
log.error("报存日志操作异常发生,进入fallback方法");
log.error("获取异常的数据 {}", sysLogs);
throw new IllegalArgumentException("报存日志操作异常发生,进入fallback方法");
}
}

88
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/CharsetKit.java

@ -0,0 +1,88 @@
package com.hnac.hzims.common.logs.text;
import com.hnac.hzims.common.logs.utils.StringUtils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author dfy
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}

1009
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/Convert.java

File diff suppressed because it is too large Load Diff

93
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/StrFormatter.java

@ -0,0 +1,93 @@
package com.hnac.hzims.common.logs.text;
import com.hnac.hzims.common.logs.utils.StringUtils;
/**
* 字符串格式化
*
* @author ruoyi
*/
public class StrFormatter
{
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
// 转义符之前还有一个转义符,占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

145
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/to/SysLogTo.java

@ -0,0 +1,145 @@
package com.hnac.hzims.common.logs.to;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/3/29 13:24
*/
@Data
public class SysLogTo {
private static final long serialVersionUID = 1L;
private Long id;
/**
* 租户ID
*/
private String tenantId;
/**
* 服务器ip
*/
protected String serverIp;
/**
* 服务器地址
*/
protected String serverHost;
/**
* 服务名称
*/
protected String serverName;
/**
* 环境
*/
protected String env;
/**
* 操作人 id
*/
private Long operationUserId;
/**
* 操作人
*/
private String operationUserName;
/**
* 请求路径 操作地址
*/
private String path;
/**
* 用户代理
*/
protected String userAgent;
/**
* 操作方式
*/
protected String method;
/**
* 方法类
*/
protected String methodClass;
/**
* 方法名
*/
protected String methodName;
/**
* 方法执行时间 消耗时间 毫秒
*/
private String costTime;
/**
* 方法入参
*/
private String parameter;
/**
* 操作方法
*/
private String title;
/**
* 方法描述
*/
private String action;
/**
* 系统类型
*/
private String operatorType;
/**
* 操作人类别
*/
private String businessType;
/**
* 返回结果
*
* @param jsonResult
*/
public String jsonResult;
/**
* 请求的Ip
*/
private String localIp;
/**
* 错误消息
*/
private String errorMsg;
/**
* 操作时间
*/
private LocalDateTime operationTime;
/**
* 操作状态0 正常 1 异常
*/
private Integer status;
}

130
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/Constants.java

@ -0,0 +1,130 @@
package com.hnac.hzims.common.logs.utils;
/**
* 通用常量信息
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* www主域
*/
public static final String WWW = "www.";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 成功标记
*/
public static final Integer SUCCESS = 200;
/**
* 失败标记
*/
public static final Integer FAIL = 500;
/**
* 登录成功状态
*/
public static final String LOGIN_SUCCESS_STATUS = "0";
/**
* 登录失败状态
*/
public static final String LOGIN_FAIL_STATUS = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 当前记录起始索引
*/
public static final String PAGE_NUM = "pageNum";
/**
* 每页显示记录数
*/
public static final String PAGE_SIZE = "pageSize";
/**
* 排序列
*/
public static final String ORDER_BY_COLUMN = "orderByColumn";
/**
* 排序的方向 "desc" 或者 "asc".
*/
public static final String IS_ASC = "isAsc";
/**
* 验证码有效期分钟
*/
public static final long CAPTCHA_EXPIRATION = 2;
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加
*/
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.core.utils.file" };
}

567
hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/StringUtils.java

@ -0,0 +1,567 @@
package com.hnac.hzims.common.logs.utils;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/3/31 15:43
*/
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.hnac.hzims.common.logs.text.StrFormatter;
import org.springframework.util.AntPathMatcher;
/**
* 字符串工具类
*
* @author ruoyi
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue)
{
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
** @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects)
{
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects)
{
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object)
{
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object)
{
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
}
if (start < 0)
{
start = str.length() + start;
}
if (start < 0)
{
start = 0;
}
if (start > str.length())
{
return NULLSTR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
}
if (end < 0)
{
end = str.length() + end;
}
if (start < 0)
{
start = str.length() + start;
}
if (end > str.length())
{
end = str.length();
}
if (start > end)
{
return NULLSTR;
}
if (start < 0)
{
start = 0;
}
if (end < 0)
{
end = 0;
}
return str.substring(start, end);
}
/**
* 判断是否为空并且不是空白字符
*
* @param str 要判断的value
* @return 结果
*/
public static boolean hasText(String str)
{
return (str != null && !str.isEmpty() && containsText(str));
}
private static boolean containsText(CharSequence str)
{
int strLen = str.length();
for (int i = 0; i < strLen; i++)
{
if (!Character.isWhitespace(str.charAt(i)))
{
return true;
}
}
return false;
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
return template;
}
return StrFormatter.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
*
* @param array 给定的数组
* @return boolean 结果
*/
public static boolean containsAny(Collection<String> collection, String... array)
{
if (isEmpty(collection) || isEmpty(array))
{
return false;
}
else
{
for (String str : array)
{
if (collection.contains(str))
{
return true;
}
}
return false;
}
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str)
{
if (str == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (i > 0)
{
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
}
else
{
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1))
{
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
{
sb.append(SEPARATOR);
}
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
{
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法
* 例如user_name->userName
*/
public static String toCamelCase(String s)
{
if (s == null)
{
return null;
}
if (s.indexOf(SEPARATOR) == -1)
{
return s;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == SEPARATOR)
{
upperCase = true;
}
else if (upperCase)
{
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
sb.append(c);
}
}
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
return (T) obj;
}
/**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度
*/
public static final String padl(final Number num, final int size)
{
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串由原字符串左补齐或截取得到
*/
public static final String padl(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
}

21
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/MiddleApplication.java

@ -0,0 +1,21 @@
package com.hnac.hzims.middle;
import org.mybatis.spring.annotation.MapperScan;
import org.springblade.core.cloud.feign.EnableBladeFeign;
import org.springblade.core.launch.BladeApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.context.annotation.ComponentScan;
@EnableBladeFeign
@SpringCloudApplication
@MapperScan("com.hnac.hzims.*.**.mapper.**")
@ComponentScan(basePackages = {"com.hnac.*"})
public class MiddleApplication {
public static void main(String[] args) {
BladeApplication.run("hzims-middle", MiddleApplication.class, args);
}
}

104
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/mybatisplus/CodeGenerator.java

@ -0,0 +1,104 @@
package com.hnac.hzims.middle.mybatisplus;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
import java.util.List;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/4/4 9:07
*/
public class CodeGenerator {
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir") + "/hzims-service/hzims-middle";
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("dfy");
gc.setOpen(false);
// gc.setSwagger2(true); 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://192.168.1.20:3576/dev_hzims_middle?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("systemlog");
pc.setParent("com.hnac.hzims.middle");
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
//指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
// templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setEntityBooleanColumnRemoveIsPrefix(true);
strategy.setEntityLombokModel(true);
strategy.setEntitySerialVersionUID(true);
strategy.setChainModel(true);
strategy.setEntityTableFieldAnnotationEnable(true);
// strategy.setFieldPrefix("hzims_");
// 公共父类
// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
// 写于父类中的公共字段
// strategy.setSuperEntityColumns("id");
strategy.setInclude("hzims_sys_log");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("hzims_");
mpg.setStrategy(strategy);
// mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}

60
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/controller/SysLogController.java

@ -0,0 +1,60 @@
package com.hnac.hzims.middle.systemlog.controller;
import com.hnac.hzims.common.logs.to.SysLogTo;
import com.hnac.hzims.middle.systemlog.entity.SysLog;
import com.hnac.hzims.middle.systemlog.service.SysLogService;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 前端控制器
* </p>
*
* @author dfy
* @since 2023-04-04
*/
@Api(tags = "系统日志")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/systemlog/sys-log")
public class SysLogController {
private final SysLogService sysLogService;
/**
* 保存操作日志
* @param sysLogToList
*/
@PostMapping("/batchSave")
public void saveBatch(@RequestBody List<SysLogTo> sysLogToList) {
//数据转换
List<SysLog> collect = sysLogToList.stream().map(item -> {
SysLog sysLog = new SysLog();
BeanUtils.copyProperties(item, sysLog);
return sysLog;
}).collect(Collectors.toList());
//添加到数据库
boolean save = sysLogService.saveBatch(collect);
if (save) {
log.info("操作日志新增成功 ~~~");
return;
}
log.info("操作日志新增失败 ~~~");
throw new IllegalArgumentException("操作日志新增失败");
}
}

191
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/entity/SysLog.java

@ -0,0 +1,191 @@
package com.hnac.hzims.middle.systemlog.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;
import java.sql.Blob;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author dfy
* @since 2023-04-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("hzims_sys_log")
public class SysLog implements Serializable {
private static final long serialVersionUID=1L;
/**
* 操作日志编号
*/
@TableField("id")
private Long id;
/**
* 租户ID
*/
@TableField("tenant_id")
private String tenantId;
/**
* 服务器ip
*/
@TableField("server_ip")
private String serverIp;
/**
* 服务器地址
*/
@TableField("server_host")
private String serverHost;
/**
* 服务名称
*/
@TableField("server_name")
private String serverName;
/**
* 环境
*/
@TableField("env")
private String env;
/**
* 操作人Id
*/
@TableField("operation_user_id")
private Long operationUserId;
/**
* 操作人名称
*/
@TableField("operation_user_name")
private String operationUserName;
/**
* 请求路径 操作地址
*/
@TableField("path")
private String path;
/**
* 用户代理
*/
@TableField("user_agent")
private String userAgent;
/**
* 操作方式
*/
@TableField("method")
private String method;
/**
* 方法类
*/
@TableField("method_class")
private String methodClass;
/**
* 方法名
*/
@TableField("method_name")
private String methodName;
/**
* 方法执行时间 消耗时间 毫秒
*/
@TableField("cost_time")
private String costTime;
/**
* 方法入参
*/
@TableField("parameter")
private String parameter;
/**
* 操作方法
*/
@TableField("title")
private String title;
/**
* 方法描述
*/
@TableField("action")
private String action;
/**
* 系统类型
*/
@TableField("operator_type")
private String operatorType;
/**
* 操作人类别
*/
@TableField("business_type")
private String businessType;
/**
* 返回结果
*/
@TableField("json_result")
private String jsonResult;
/**
* 请求的Ip
*/
@TableField("local_ip")
private String localIp;
/**
* 错误消息
*/
@TableField("error_msg")
private String errorMsg;
/**
* 操作时间
*/
@TableField("operation_time")
private LocalDateTime operationTime;
/**
* 操作状态0 正常 1 异常
*/
@TableField("status")
private Integer status;
/**
* 创建时间
*/
@TableField("create_time")
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField("update_time")
private LocalDateTime updateTime;
/**
* 逻辑删除 0 可用 1 删除
*/
@TableField("is_deleted")
private Integer isDeleted;
}

16
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/mapper/SysLogMapper.java

@ -0,0 +1,16 @@
package com.hnac.hzims.middle.systemlog.mapper;
import com.hnac.hzims.middle.systemlog.entity.SysLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author dfy
* @since 2023-04-04
*/
public interface SysLogMapper extends BaseMapper<SysLog> {
}

16
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/SysLogService.java

@ -0,0 +1,16 @@
package com.hnac.hzims.middle.systemlog.service;
import com.hnac.hzims.middle.systemlog.entity.SysLog;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author dfy
* @since 2023-04-04
*/
public interface SysLogService extends IService<SysLog> {
}

20
hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/impl/SysLogServiceImpl.java

@ -0,0 +1,20 @@
package com.hnac.hzims.middle.systemlog.service.impl;
import com.hnac.hzims.middle.systemlog.entity.SysLog;
import com.hnac.hzims.middle.systemlog.mapper.SysLogMapper;
import com.hnac.hzims.middle.systemlog.service.SysLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author dfy
* @since 2023-04-04
*/
@Service
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements SysLogService {
}

38
hzims-service/hzims-middle/src/main/resources/application.yml

@ -0,0 +1,38 @@
#服务器端口
server:
port: 8400
#数据源配置
spring:
#排除DruidDataSourceAutoConfigure
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
datasource:
url: jdbc:mysql://192.168.1.20:3576/dev_hzims_middle?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
username: root
password: 123
#mybatis-plus配置
mybatis-plus:
mapper-locations:
- classpath:com/hnac/hzims/**/mapper/*Mapper.xml
- classpath:/mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.hnac.hzims.**.entity
#swagger扫描路径配置
swagger:
base-packages:
- org.springbalde
- com.hnac
blade:
data-scope:
enabled: false
lock:
enabled: true
address: redis://192.168.1.20:3577
password: 1qaz2WSX@redis
database: 0
ssl: false

7
hzims-service/hzims-middle/src/main/resources/bootstrap.yml

@ -0,0 +1,7 @@
spring:
cloud:
nacos:
discovery:
server-addr: 175.6.40.67:10042

5
hzims-service/hzims-middle/src/main/resources/mapper/SysLogMapper.xml

@ -0,0 +1,5 @@
<?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.hnac.hzims.middle.systemlog.mapper.SysLogMapper">
</mapper>

15
hzims-service/hzims-middle/src/test/java/com/hnac/hzims/middle/MiddleApplicationTests.java

@ -0,0 +1,15 @@
package com.hnac.hzims.middle;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MiddleApplicationTests {
@Test
void contextLoads() {
System.out.println("1");
}
}

1
hzims-service/pom.xml

@ -26,6 +26,7 @@
<module>message</module> <module>message</module>
<module>ticket</module> <module>ticket</module>
<module>weather</module> <module>weather</module>
<module>hzims-middle</module>
</modules> </modules>
<dependencies> <dependencies>

6
hzims-service/ticket/pom.xml

@ -275,6 +275,12 @@
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-ecs</artifactId>
<version>4.2.0</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>

4
hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/TicketApplication.java

@ -8,6 +8,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -17,8 +18,9 @@ import javax.annotation.Resource;
@EnableBladeFeign @EnableBladeFeign
@SpringCloudApplication @SpringCloudApplication
@MapperScan("com.hnac.hzims.**.mapper.**") @MapperScan("com.hnac.hzims.**.mapper.**")
@ComponentScan(basePackages = {"com.hnac.*"}) @ComponentScan(basePackages = {"com.hnac"})
@Resource @Resource
@EnableAspectJAutoProxy(exposeProxy = true)
public class TicketApplication extends SpringBootServletInitializer { public class TicketApplication extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {

267
hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/ApiLogAspect.java

@ -1,267 +0,0 @@
package com.hnac.hzims.ticket.aop;
import com.alibaba.fastjson.JSON;
import com.hnac.hzims.common.utils.IPUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @author dfy
* @date 2023/3/29
* @description: 操作日志切面处理类
*/
@Aspect
@Component
@Slf4j
public class ApiLogAspect {
/**
* 请求地址
*/
private String requestPath = null;
/**
* 开始时间
*/
private long startTimeMillis = 0;
/**
* 结束时间
*/
private long endTimeMillis = 0;
/**
* 操作人
*/
private String user = null;
/**
* 请求
*/
private HttpServletRequest request = null;
/**
* 设置操作日志切入点 在注解的位置切入代码
*/
@Pointcut("@annotation(com.hnac.hzims.ticket.aop.OperationAnnotation)")
public void logPointCut() {
}
/**
* @param joinPoint
* @Description 前置通知 方法调用前触发 记录开始时间,从session中获取操作人
*/
@Before(value = "logPointCut()")
public void before(JoinPoint joinPoint) {
log.info("前置通知");
startTimeMillis = System.currentTimeMillis();
}
/**
* @param joinPoint
* @Description 后置通知 方法调用后触发 记录结束时间 ,操作人 ,入参等
*/
@AfterReturning(value = "logPointCut()", returning = "keys")
public void after(JoinPoint joinPoint, Object keys) {
log.info("后置通知");
request = getHttpServletRequest();
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class<?> targetClass = null;
try {
targetClass = Class.forName(targetName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = targetClass.getMethods();
String title;
String action;
Integer sysType;
String opType;
Class<?>[] clazzs;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
clazzs = method.getParameterTypes();
if (clazzs != null && clazzs.length == arguments.length && method.getAnnotation(OperationAnnotation.class) != null) {
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
methodName = className + "." + methodName;
request = getHttpServletRequest();
requestPath = request.getServletPath();
HttpSession session = request.getSession();
OperationAnnotation annotation = method.getAnnotation(OperationAnnotation.class);
title = annotation.content();
action = annotation.action();
sysType = annotation.sysType();
opType = annotation.operatingType();
endTimeMillis = System.currentTimeMillis();
if (user == null) {
user = "dfy";
}
SysLog sysLog = new SysLog();
sysLog.setOperRespParam(JSON.toJSONString(keys)); // 返回结果
sysLog.setOperIp(IPUtils.getIpAddress(request)); // 请求IP
sysLog.setOperationUser(user);
sysLog.setTime((endTimeMillis - startTimeMillis) + "ms");
sysLog.setPath(requestPath);
sysLog.setTitle(title);
sysLog.setAction(action);
sysLog.setSysType(sysType);
sysLog.setOperatingType(opType);
sysLog.setParameter(getNameAndValue(joinPoint).toString());
System.out.println("增加参数:" + sysLog);
// logMapper.save(sysLog);
}
}
}
}
/**
* @param joinPoint
* @return
* @Description 获取入参方法参数
*/
public Map<String, Object> getNameAndValue(JoinPoint joinPoint) {
Map<String, Object> param = new HashMap<>(16);
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for (int i = 0; i < paramNames.length; i++) {
if (paramValues[i] instanceof Integer || paramValues[i] instanceof String) {
param.put(paramNames[i], paramValues[i]);
}
}
return param;
}
/**
* @Description: 获取request
*/
public HttpServletRequest getHttpServletRequest() {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
return request;
}
/**
* @param joinPoint
* @return 环绕通知
* @throws Throwable
*/
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("环绕通知");
return null;
}
// /**
// * @param joinPoint
// * @Description 异常通知
// */
// @AfterThrowing(pointcut = "operExceptionLogPoinCut()", throwing = "e")
// public void throwing(JoinPoint joinPoint, Throwable e) {
// log.info("异常通知");
// // 获取RequestAttributes
// RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// // 从获取RequestAttributes中获取HttpServletRequest的信息
// HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//
// SysExceptionLog excepLog = new SysExceptionLog();
// try {
// // 从切面织入点处通过反射机制获取织入点处的方法
// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// // 获取切入点所在的方法
// Method method = signature.getMethod();
// // 获取请求的类名
// String className = joinPoint.getTarget().getClass().getName();
// // 获取请求的方法名
// String methodName = method.getName();
// methodName = className + "." + methodName;
// // 请求的参数
// Map<String, String> rtnMap = converMap(request.getParameterMap());
// // 将参数所在的数组转换成json
// String params = JSON.toJSONString(rtnMap);
// //请求参数
// excepLog.setExcRequParam(params);
// // 请求方法名
// excepLog.setOperMethod(methodName);
// // 异常名称
// excepLog.setExcName(e.getClass().getName());
// // 异常信息
// excepLog.setExcMessage(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace()));
// // 操作员ID
// excepLog.setOperUserId("2L");
// // 操作员名称
// excepLog.setOperUserName("duanfeiyu");
// // 操作URI
// excepLog.setOperUri(request.getRequestURI());
// // 操作员IP
// excepLog.setOperIp(IPUtil.localHostIP());
// // 操作版本号
// excepLog.setOperVer(operVer);
// // 发生异常时间
// excepLog.setOperCreateTime(new Date());
//
//
// sysExceptionLogService.save(excepLog);
//
// } catch (Exception e2) {
// e2.printStackTrace();
// }
// }
/**
* 转换request 请求参数
*
* @param paramMap request获取的参数数组
*/
public Map<String, String> converMap(Map<String, String[]> paramMap) {
Map<String, String> rtnMap = new HashMap<String, String>();
for (String key : paramMap.keySet()) {
rtnMap.put(key, paramMap.get(key)[0]);
}
return rtnMap;
}
/**
* 转换异常信息为字符串
*
* @param exceptionName 异常名称
* @param exceptionMessage 异常信息
* @param elements 堆栈信息
*/
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
StringBuffer strbuff = new StringBuffer();
for (StackTraceElement stet : elements) {
strbuff.append(stet + "\n");
}
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
return message;
}
}

42
hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/OperationAnnotation.java

@ -1,42 +0,0 @@
package com.hnac.hzims.ticket.aop;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/3/29 11:38
*/
@Documented
@Component
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OperationAnnotation {
/**
* 操作模块
* @return
*/
String content();
/**
* 系统类型网页端app端
*/
int sysType() default 0;
/**
* 操作类型
* @return
*/
String operatingType() default "";
/**
* 功能说明
* @return
*/
String action() default "";
}

80
hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/SysLog.java

@ -1,80 +0,0 @@
package com.hnac.hzims.ticket.aop;
import lombok.Data;
/**
* @Author WL
* @Version v1.0
* @Serial 1.0
* @Date 2023/3/29 13:24
*/
@Data
public class SysLog {
private static final long serialVersionUID = 1L;
private Long id;
/**
* 操作人
*/
private String operationUser;
/**
* 请求路径
*/
private String path;
/**
* 服务名称
*/
private String serviceName;
/**
* 方法执行时间
*/
private String time;
/**
* 方法入参
*/
private String parameter;
/**
* 操作方法
*/
private String title;
/**
* 方法描述
*/
private String action;
/**
* 系统类型
*/
private Integer sysType;
/**
* 操作类型
*/
private String operatingType;
/**
* 返回结果
* oper_resp_param
*
* @param toJSONString
*/
public String operRespParam;
/**
* 返回结果
*
* @param toJSONString
*/
public String operIp;
}

117
hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/processflow/controller/ProcessTypeController.java

@ -1,13 +1,17 @@
package com.hnac.hzims.ticket.processflow.controller; package com.hnac.hzims.ticket.processflow.controller;
import com.alibaba.fastjson.JSON;
import com.hnac.hzims.common.logs.annotation.OperationAnnotation;
import com.hnac.hzims.common.logs.enums.BusinessType;
import com.hnac.hzims.common.logs.enums.OperatorType;
import com.hnac.hzims.ticket.processflow.entity.ProcessType; import com.hnac.hzims.ticket.processflow.entity.ProcessType;
import com.hnac.hzims.ticket.processflow.properties.TicketProperties; import com.hnac.hzims.ticket.processflow.properties.TicketProperties;
import com.hnac.hzims.ticket.processflow.properties.WorkTicketProperties; import com.hnac.hzims.ticket.processflow.properties.WorkTicketProperties;
import com.hnac.hzims.ticket.processflow.service.ProcessTypeService; import com.hnac.hzims.ticket.processflow.service.ProcessTypeService;
import com.hnac.hzims.ticket.processflow.strategy.entity.WorkflowQueue; import com.hnac.hzims.ticket.processflow.strategy.entity.WorkflowQueue;
import com.hnac.hzims.ticket.processflow.strategy.service.TicketService; import com.hnac.hzims.ticket.processflow.strategy.service.TicketService;
import org.springblade.core.log.annotation.ApiLog; import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -30,57 +34,64 @@ import java.util.stream.Collectors;
@RequestMapping("/processflow/process-type") @RequestMapping("/processflow/process-type")
public class ProcessTypeController { public class ProcessTypeController {
@Autowired @Autowired
private TicketProperties ticketProperties; private TicketProperties ticketProperties;
@Autowired @Autowired
private ProcessTypeService processTypeService; private ProcessTypeService processTypeService;
@Autowired @Autowired
private List<TicketService> ticketServiceList; private List<TicketService> ticketServiceList;
@Autowired @Autowired
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
@GetMapping("/add")
@GetMapping("/add") public void add() {
public void add() { List<WorkTicketProperties> workTickets = ticketProperties.getWorkTickets();
List<WorkTicketProperties> workTickets = ticketProperties.getWorkTickets(); List<ProcessType> processTypeList = workTickets.stream().map(item -> {
List<ProcessType> processTypeList = workTickets.stream().map(item -> { ProcessType processType = new ProcessType();
ProcessType processType = new ProcessType(); processType.setDeploymentId(item.getFlowId());
processType.setDeploymentId(item.getFlowId()); processType.setDeploymentName(item.getSegment());
processType.setDeploymentName(item.getSegment()); processType.setSegment("新工作票");
processType.setSegment("新工作票"); processType.setSequence(item.getStatus());
processType.setSequence(item.getStatus()); return processType;
return processType; }).collect(Collectors.toList());
}).collect(Collectors.toList()); processTypeService.saveBatch(processTypeList);
processTypeService.saveBatch(processTypeList); }
}
@GetMapping("/list/{key}")
public String list(@PathVariable String key) {
@GetMapping("/list/{key}") //判断执行具体的实现类
public String list(@PathVariable String key) { WorkflowQueue workflowQueue = new WorkflowQueue();
//判断执行具体的实现类 workflowQueue.setDeploymentId(key);
WorkflowQueue workflowQueue = new WorkflowQueue(); TicketService ticketService =
workflowQueue.setDeploymentId(key); ticketServiceList.stream().filter(item -> item.isWorkflowTicket(workflowQueue))
TicketService ticketService = .findFirst().orElse(null);
ticketServiceList.stream().filter(item -> item.isWorkflowTicket(workflowQueue)) String calculate = ticketService.calculate(null);
.findFirst().orElse(null); return calculate;
String calculate = ticketService.calculate(null); }
return calculate;
}
@OperationAnnotation(title = "操作模块", operatorType = OperatorType.MOBILE, businessType = BusinessType.GENCODE,action ="获取redis数据")
@GetMapping("/redis/{value}")
public int opens(@PathVariable String value) {
@ApiLog("hellword") redisTemplate.opsForValue().set("name:hello", JSON.toJSONString(value));
@GetMapping("/redis/{value}") return 0;
public String opens(@PathVariable String value) { }
redisTemplate.opsForValue().set("name:hello",value);
return "成功";
} @OperationAnnotation(title = "工作流审批类型", operatorType = OperatorType.MOBILE, businessType = BusinessType.GENCODE,
action ="查询")
@GetMapping("/list")
public R list() {
List<ProcessType> list = processTypeService.list();
System.out.println(1/0);
return R.data(list);
}
} }

Loading…
Cancel
Save