段飞宇
2 years ago
34 changed files with 3278 additions and 443 deletions
@ -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 "功能说明"; |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
} |
@ -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); |
||||
} |
@ -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方法"); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -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(); |
||||
} |
||||
} |
@ -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; |
||||
|
||||
} |
@ -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" }; |
||||
} |
@ -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是否为空, 包含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; |
||||
} |
||||
|
||||
/** |
||||
* 格式化文本, {} 表示占位符<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(); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
||||
|
@ -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("操作日志新增失败"); |
||||
} |
||||
} |
||||
|
@ -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; |
||||
|
||||
|
||||
} |
@ -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> { |
||||
|
||||
} |
@ -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> { |
||||
|
||||
} |
@ -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 { |
||||
|
||||
} |
@ -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 |
@ -0,0 +1,7 @@
|
||||
spring: |
||||
cloud: |
||||
nacos: |
||||
discovery: |
||||
server-addr: 175.6.40.67:10042 |
||||
|
||||
|
@ -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> |
@ -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,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; |
||||
} |
||||
} |
@ -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 ""; |
||||
} |
@ -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; |
||||
} |
Loading…
Reference in new issue