diff --git a/hzims-biz-common/pom.xml b/hzims-biz-common/pom.xml index b3927d9..5255f48 100644 --- a/hzims-biz-common/pom.xml +++ b/hzims-biz-common/pom.xml @@ -41,6 +41,7 @@ blade-starter-datascope + diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/annotation/OperationAnnotation.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/annotation/OperationAnnotation.java new file mode 100644 index 0000000..f67c14b --- /dev/null +++ b/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 "功能说明"; +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/aop/SysLogAspect.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/aop/SysLogAspect.java new file mode 100644 index 0000000..1a23612 --- /dev/null +++ b/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 getNameAndValue(JoinPoint joinPoint) { + Map 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 converMap(Map paramMap) { + Map rtnMap = new HashMap(); + 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); + } + } + } + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogConsumer.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogConsumer.java new file mode 100644 index 0000000..5601b3c --- /dev/null +++ b/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 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(); + } + + } + } + + + + +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogQueue.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/consumer/SysLogQueue.java new file mode 100644 index 0000000..1424a74 --- /dev/null +++ b/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 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); + } + +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessStatus.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessStatus.java new file mode 100644 index 0000000..90cfa91 --- /dev/null +++ b/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; + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessType.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/BusinessType.java new file mode 100644 index 0000000..6556577 --- /dev/null +++ b/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; + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/OperatorType.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/enums/OperatorType.java new file mode 100644 index 0000000..6ba76cd --- /dev/null +++ b/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; + } + + +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/SysLogFeignService.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/SysLogFeignService.java new file mode 100644 index 0000000..5523cae --- /dev/null +++ b/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 sysLogs); +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/fallback/SysLogFeignServiceFallback.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/fegin/fallback/SysLogFeignServiceFallback.java new file mode 100644 index 0000000..2035023 --- /dev/null +++ b/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 sysLogs) { + log.error("报存日志操作异常发生,进入fallback方法"); + log.error("获取异常的数据 {}", sysLogs); + throw new IllegalArgumentException("报存日志操作异常发生,进入fallback方法"); + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/CharsetKit.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/CharsetKit.java new file mode 100644 index 0000000..ca91975 --- /dev/null +++ b/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(); + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/Convert.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/Convert.java new file mode 100644 index 0000000..1d6b420 --- /dev/null +++ b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/Convert.java @@ -0,0 +1,1009 @@ +package com.hnac.hzims.common.logs.text; + + + +import com.hnac.hzims.common.logs.utils.StringUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author ruoyi + */ +public class Convert +{ + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[] || obj instanceof Byte[]) + { + if (obj instanceof byte[]) + { + return str((byte[]) obj, charset); + } + else + { + Byte[] bytes = (Byte[]) obj; + int length = bytes.length; + byte[] dest = new byte[length]; + for (int i = 0; i < length; i++) + { + dest[i] = bytes[i]; + } + return str(dest, charset); + } + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + return new String(c); + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "角", "分" }; + String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; + String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) + { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/StrFormatter.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/text/StrFormatter.java new file mode 100644 index 0000000..2d805ea --- /dev/null +++ b/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 = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @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(); + } +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/to/SysLogTo.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/to/SysLogTo.java new file mode 100644 index 0000000..930ebf9 --- /dev/null +++ b/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; + +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/Constants.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/Constants.java new file mode 100644 index 0000000..2abbd51 --- /dev/null +++ b/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" }; +} diff --git a/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/StringUtils.java b/hzims-biz-common/src/main/java/com/hnac/hzims/common/logs/utils/StringUtils.java new file mode 100644 index 0000000..c0da05b --- /dev/null +++ b/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 nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @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; + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @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 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 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 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(); + } +} diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/MiddleApplication.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/MiddleApplication.java new file mode 100644 index 0000000..4b48c6c --- /dev/null +++ b/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); + } + +} diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/mybatisplus/CodeGenerator.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/mybatisplus/CodeGenerator.java new file mode 100644 index 0000000..b3d63f6 --- /dev/null +++ b/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 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(); + } + +} + diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/controller/SysLogController.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/controller/SysLogController.java new file mode 100644 index 0000000..b40b640 --- /dev/null +++ b/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; + +/** + *

+ * 前端控制器 + *

+ * + * @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 sysLogToList) { + //数据转换 + List 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("操作日志新增失败"); + } +} + diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/entity/SysLog.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/entity/SysLog.java new file mode 100644 index 0000000..7c8c262 --- /dev/null +++ b/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; + +/** + *

+ * + *

+ * + * @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; + + +} diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/mapper/SysLogMapper.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/mapper/SysLogMapper.java new file mode 100644 index 0000000..009f3a1 --- /dev/null +++ b/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; + +/** + *

+ * Mapper 接口 + *

+ * + * @author dfy + * @since 2023-04-04 + */ +public interface SysLogMapper extends BaseMapper { + +} diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/SysLogService.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/SysLogService.java new file mode 100644 index 0000000..e409a1e --- /dev/null +++ b/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; + +/** + *

+ * 服务类 + *

+ * + * @author dfy + * @since 2023-04-04 + */ +public interface SysLogService extends IService { + +} diff --git a/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/impl/SysLogServiceImpl.java b/hzims-service/hzims-middle/src/main/java/com/hnac/hzims/middle/systemlog/service/impl/SysLogServiceImpl.java new file mode 100644 index 0000000..a889cce --- /dev/null +++ b/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; + +/** + *

+ * 服务实现类 + *

+ * + * @author dfy + * @since 2023-04-04 + */ +@Service +public class SysLogServiceImpl extends ServiceImpl implements SysLogService { + +} diff --git a/hzims-service/hzims-middle/src/main/resources/application.yml b/hzims-service/hzims-middle/src/main/resources/application.yml new file mode 100644 index 0000000..6e69e09 --- /dev/null +++ b/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 diff --git a/hzims-service/hzims-middle/src/main/resources/bootstrap.yml b/hzims-service/hzims-middle/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..0abf99a --- /dev/null +++ b/hzims-service/hzims-middle/src/main/resources/bootstrap.yml @@ -0,0 +1,7 @@ +spring: + cloud: + nacos: + discovery: + server-addr: 175.6.40.67:10042 + + diff --git a/hzims-service/hzims-middle/src/main/resources/mapper/SysLogMapper.xml b/hzims-service/hzims-middle/src/main/resources/mapper/SysLogMapper.xml new file mode 100644 index 0000000..698fb08 --- /dev/null +++ b/hzims-service/hzims-middle/src/main/resources/mapper/SysLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/hzims-service/hzims-middle/src/test/java/com/hnac/hzims/middle/MiddleApplicationTests.java b/hzims-service/hzims-middle/src/test/java/com/hnac/hzims/middle/MiddleApplicationTests.java new file mode 100644 index 0000000..ad2db3e --- /dev/null +++ b/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"); + } + +} diff --git a/hzims-service/pom.xml b/hzims-service/pom.xml index 9cfd5d3..cdace60 100644 --- a/hzims-service/pom.xml +++ b/hzims-service/pom.xml @@ -26,6 +26,7 @@ message ticket weather + hzims-middle diff --git a/hzims-service/ticket/pom.xml b/hzims-service/ticket/pom.xml index 57d9837..de7d2cc 100644 --- a/hzims-service/ticket/pom.xml +++ b/hzims-service/ticket/pom.xml @@ -275,6 +275,12 @@ redis.clients jedis + + com.aliyun + aliyun-java-sdk-ecs + 4.2.0 + compile + diff --git a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/TicketApplication.java b/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/TicketApplication.java index 5f99b44..6a636a8 100644 --- a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/TicketApplication.java +++ b/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.cloud.client.SpringCloudApplication; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import javax.annotation.Resource; @@ -17,8 +18,9 @@ import javax.annotation.Resource; @EnableBladeFeign @SpringCloudApplication @MapperScan("com.hnac.hzims.**.mapper.**") -@ComponentScan(basePackages = {"com.hnac.*"}) +@ComponentScan(basePackages = {"com.hnac"}) @Resource +@EnableAspectJAutoProxy(exposeProxy = true) public class TicketApplication extends SpringBootServletInitializer { public static void main(String[] args) { diff --git a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/ApiLogAspect.java b/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/ApiLogAspect.java deleted file mode 100644 index 67ff905..0000000 --- a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/ApiLogAspect.java +++ /dev/null @@ -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 getNameAndValue(JoinPoint joinPoint) { - Map 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 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 converMap(Map paramMap) { - Map rtnMap = new HashMap(); - 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; - } -} diff --git a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/OperationAnnotation.java b/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/OperationAnnotation.java deleted file mode 100644 index c0f7bf1..0000000 --- a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/OperationAnnotation.java +++ /dev/null @@ -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 ""; -} diff --git a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/SysLog.java b/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/SysLog.java deleted file mode 100644 index b138a3e..0000000 --- a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/aop/SysLog.java +++ /dev/null @@ -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; -} diff --git a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/processflow/controller/ProcessTypeController.java b/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/processflow/controller/ProcessTypeController.java index e06a007..0f7d119 100644 --- a/hzims-service/ticket/src/main/java/com/hnac/hzims/ticket/processflow/controller/ProcessTypeController.java +++ b/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; +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.properties.TicketProperties; import com.hnac.hzims.ticket.processflow.properties.WorkTicketProperties; import com.hnac.hzims.ticket.processflow.service.ProcessTypeService; import com.hnac.hzims.ticket.processflow.strategy.entity.WorkflowQueue; 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.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.GetMapping; @@ -30,57 +34,64 @@ import java.util.stream.Collectors; @RequestMapping("/processflow/process-type") public class ProcessTypeController { - @Autowired - private TicketProperties ticketProperties; - - - @Autowired - private ProcessTypeService processTypeService; - - - @Autowired - private List ticketServiceList; - - @Autowired - private RedisTemplate redisTemplate; - - - - @GetMapping("/add") - public void add() { - List workTickets = ticketProperties.getWorkTickets(); - List processTypeList = workTickets.stream().map(item -> { - ProcessType processType = new ProcessType(); - processType.setDeploymentId(item.getFlowId()); - processType.setDeploymentName(item.getSegment()); - processType.setSegment("新工作票"); - processType.setSequence(item.getStatus()); - return processType; - }).collect(Collectors.toList()); - processTypeService.saveBatch(processTypeList); - } - - - - @GetMapping("/list/{key}") - public String list(@PathVariable String key) { - //判断执行具体的实现类 - WorkflowQueue workflowQueue = new WorkflowQueue(); - workflowQueue.setDeploymentId(key); - TicketService ticketService = - ticketServiceList.stream().filter(item -> item.isWorkflowTicket(workflowQueue)) - .findFirst().orElse(null); - String calculate = ticketService.calculate(null); - return calculate; - } - - - - @ApiLog("hellword") - @GetMapping("/redis/{value}") - public String opens(@PathVariable String value) { - redisTemplate.opsForValue().set("name:hello",value); - return "成功"; - } + @Autowired + private TicketProperties ticketProperties; + + + @Autowired + private ProcessTypeService processTypeService; + + + @Autowired + private List ticketServiceList; + + @Autowired + private RedisTemplate redisTemplate; + + + @GetMapping("/add") + public void add() { + List workTickets = ticketProperties.getWorkTickets(); + List processTypeList = workTickets.stream().map(item -> { + ProcessType processType = new ProcessType(); + processType.setDeploymentId(item.getFlowId()); + processType.setDeploymentName(item.getSegment()); + processType.setSegment("新工作票"); + processType.setSequence(item.getStatus()); + return processType; + }).collect(Collectors.toList()); + processTypeService.saveBatch(processTypeList); + } + + + @GetMapping("/list/{key}") + public String list(@PathVariable String key) { + //判断执行具体的实现类 + WorkflowQueue workflowQueue = new WorkflowQueue(); + workflowQueue.setDeploymentId(key); + TicketService ticketService = + ticketServiceList.stream().filter(item -> item.isWorkflowTicket(workflowQueue)) + .findFirst().orElse(null); + 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) { + redisTemplate.opsForValue().set("name:hello", JSON.toJSONString(value)); + return 0; + } + + + @OperationAnnotation(title = "工作流审批类型", operatorType = OperatorType.MOBILE, businessType = BusinessType.GENCODE, + action ="查询") + @GetMapping("/list") + public R list() { + List list = processTypeService.list(); + System.out.println(1/0); + return R.data(list); + } }