Commit 372b9739 authored by ZWT's avatar ZWT

feat(零碳): 长庆演示系统新增功能

1.新建油田配置表同时生成相关代码及mapper文件,修改部分第三方数据抽取定时任务,增加针对不同井场开关控制逻辑,同时修改首页页面展示逻辑,通过油田配置功能区分不同首页展示功能;
2.新建定时任务配置表同时生成相关代码及mapper文件,定时任务模块增加mybatis配置,用以操作数据库,修改部分第三方数据抽取定时任务,修改使用方式使其脱离框架方便动态控制;

BREAKING CHANGE: 无

Closes 无

[skip ci]
parent efd7bba6
package pps.core.common.job;
import cn.hutool.core.text.CharSequenceUtil;
import pps.core.common.utils.*;
import xstartup.base.XStartup;
import xstartup.base.util.XJsonUtils;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
public class CounterJob5S {
public static final String CLUSTER_GLOBAL_COUNTER = "counter.cluster_global_counter";
public static final String CLUSTER_GLOBAL_COUNTER_LOCK = "counter.cluster_global_counter_lock";
public static final TimeSpanChecker publishChecker = new TimeSpanChecker(15, true);
public static boolean EnableJob = false;
private static AtomicBoolean master = new AtomicBoolean(false);
public static void executeJob() {
if (!EnableJob) {
return;
}
if (!publishChecker.checkNow()) {
return;
}
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-Timer");
CounterBuilder.globalCounterBuilder.setFieldValue("CounterJob-Timer-LatestTime", DateUtil.getCurrentDateTime());
CounterBuilder.globalCounterBuilder.setFieldValue("__IPS__", IpUtils.getHostIPs(true));
CounterBuilder.globalCounterBuilder.setFieldValue("__TASKS_RUNNING__", GlobalExecutorService.INSTANCE.getRunningTasksCount() + "");
CounterBuilder.globalCounterBuilder.setFieldValue("__TASKS_DONE__", GlobalExecutorService.INSTANCE.getTasksCount() + "");
CounterBuilder.globalCounterBuilder.setFieldValue("__TASKS_RUNNING(SCADA)___", ScadaExecutorService.INSTANCE.getRunningTasksCount() + "");
CounterBuilder.globalCounterBuilder.setFieldValue("__TASKS_DONE(SCADA)__", ScadaExecutorService.INSTANCE.getTasksCount() + "");
CounterBuilder.globalCounterBuilder.setFieldValue("__TRACEBUILDERS__", TraceHelper.getTraceBuildersCount() + "");
DynObj dynObj = CounterBuilder.globalCounterBuilder.toDynObj();
dynObj.put(CounterBuilder.COUNTER_NAME_INSTANCE, CounterBuilder.globalCounterBuilder.counterId);
dynObj.put("__LATEST_TIMER_TIME__", DateUtil.getCurrentDateTime());
dynObj.put("__PUBLISH_TIME__", DateUtil.getCurrentDateTime());
dynObj.put("__THREADS__", ThreadHelper.buildThreadsSimpleInfos(null));
long publishStart = System.currentTimeMillis();
publish(dynObj);
long publishEnd = System.currentTimeMillis();
CounterBuilder.globalCounterBuilder.setFieldValue("CounterJob-Publish-UsedSecnods", (publishEnd - publishStart) / 1000 + "");
}
public static String getAppClusterName() {
String appName = XStartup.getApplication().getName();
String env = XStartup.getApplication().getEnv().name();
String appClusterName = CLUSTER_GLOBAL_COUNTER + "_" + env + "_" + appName;
return appClusterName;
}
public static String getAppClusterLockName() {
String appName = XStartup.getApplication().getName();
String env = XStartup.getApplication().getEnv().name();
String appClusterLockName = CLUSTER_GLOBAL_COUNTER_LOCK + "_" + env + "_" + appName;
return appClusterLockName;
}
private static void publish(DynObj dynObj) {
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-publish-begin");
try {
String myNodeKey = String.format("counter.%s.%s", dynObj.getString(CounterBuilder.DEPLOY_KEY, "UnknownDeploy"), CounterBuilder.globalCounterBuilder.counterId);
dynObj.put(CounterBuilder.COUNTER_NAME_OWNER, myNodeKey);
String cacheType = XStartup.getCurrent().getProperty("x.cache.type");
String appClusterName = getAppClusterName();
String appClusterLockName = getAppClusterLockName();
if ("redis-cluster".equals(cacheType)) {
JedisHelper.consumeDefalutJedisCluster((jedis) -> {
// 记录到集群中
jedis.sadd(appClusterName, myNodeKey);
// 集群3分钟过期
jedis.expire(appClusterName, 3 * 20);
boolean isMaster = false;
long success = jedis.setnx(appClusterLockName, myNodeKey);
if (success != 0) {
jedis.expire(appClusterLockName, 40);
isMaster = true;
}
String lockKey = jedis.get(appClusterLockName);
if (myNodeKey.equals(lockKey)) {
jedis.expire(appClusterLockName, 40);
isMaster = true;
}
master.set(isMaster);
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER__", isMaster + "");
if (isMaster) {
if (CharSequenceUtil.isBlank(CounterBuilder.globalCounterBuilder.getFieldValue("__MASTER-TIME__"))) {
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER-TIME__", DateUtil.getCurrentDateTime());
CounterBuilder.globalCounterBuilder.addCounter("__MASTER-TIMES__");
}
} else {
if (CharSequenceUtil.isNotBlank(CounterBuilder.globalCounterBuilder.getFieldValue("__MASTER-TIME__"))) {
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER-TIME__", "");
}
// onlineNodes.clear();
}
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-PublishToRedis");
CounterBuilder.globalCounterBuilder.setFieldValue("CounterJob-PublishToRedis-TIME", DateUtil.getCurrentDateTime());
// 记录到redis ,3 * 30s过期
jedis.setex(myNodeKey, 3 * 20, XJsonUtils.toJson(dynObj));
if (isMaster) {
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-Timer-MASTER");
Set<String> nodeKeys = jedis.smembers(appClusterName);
nodeKeys.forEach(k -> {
if (!jedis.exists(k)) {
jedis.srem(appClusterName, k);
CounterBuilder.globalCounterBuilder.addCounter("Remove-Node");
} else {
}
});
} else {
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-Timer-NOTMASTER");
}
});
} else {
JedisHelper.consumeDefalutJedis((jedis) -> {
// 记录到集群中
jedis.sadd(appClusterName, myNodeKey);
// 集群3分钟过期
jedis.expire(appClusterName, 3 * 20);
boolean isMaster = false;
long success = jedis.setnx(appClusterLockName, myNodeKey);
if (success != 0) {
jedis.expire(appClusterLockName, 40);
isMaster = true;
}
String lockKey = jedis.get(appClusterLockName);
if (myNodeKey.equals(lockKey)) {
jedis.expire(appClusterLockName, 40);
isMaster = true;
}
master.set(isMaster);
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER__", isMaster + "");
if (isMaster) {
if (CharSequenceUtil.isBlank(CounterBuilder.globalCounterBuilder.getFieldValue("__MASTER-TIME__"))) {
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER-TIME__", DateUtil.getCurrentDateTime());
CounterBuilder.globalCounterBuilder.addCounter("__MASTER-TIMES__");
}
} else {
if (CharSequenceUtil.isNotBlank(CounterBuilder.globalCounterBuilder.getFieldValue("__MASTER-TIME__"))) {
CounterBuilder.globalCounterBuilder.setFieldValue("__MASTER-TIME__", "");
}
}
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-PublishToRedis");
CounterBuilder.globalCounterBuilder.setFieldValue("CounterJob-PublishToRedis-TIME", DateUtil.getCurrentDateTime());
// 记录到redis ,3 * 30s过期
jedis.setex(myNodeKey, 3 * 20, XJsonUtils.toJson(dynObj));
if (isMaster) {
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-Timer-MASTER");
Set<String> nodeKeys = jedis.smembers(appClusterName);
nodeKeys.forEach(k -> {
if (!jedis.exists(k)) {
jedis.srem(appClusterName, k);
CounterBuilder.globalCounterBuilder.addCounter("Remove-Node");
} else {
}
});
} else {
CounterBuilder.globalCounterBuilder.addCounter("CounterJob-Timer-NOTMASTER");
}
});
}
} catch (Exception ex) {
CounterBuilder.globalCounterBuilder.addCounter(ex, CounterJob5S.class);
}
}
}
package pps.core.common.job;
import pps.core.common.utils.CounterBuilder;
import pps.core.common.utils.TimeSpanChecker;
import pps.core.common.utils.TraceHelper;
import xstartup.base.XContext;
import xstartup.base.tool.XStorageTool;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
public class TempCleanJob5S {
public static final TimeSpanChecker jobChecker = new TimeSpanChecker(60 * 60, true);
public static final ConcurrentHashMap<String, String[]> tempFilePatttern = new ConcurrentHashMap<>();
public static boolean EnableJob = true;
static {
tempFilePatttern.put("/var/tmp/", new String[]{"^tracelog-\\d+.txt$"});
}
public static void executeTimerJob(XContext context) {
if (!EnableJob) {
return;
}
if (!jobChecker.checkNow()) {
return;
}
executeJob(context);
}
public static void executeJob(XContext context) {
tempFilePatttern.forEach((k, v) -> {
checkAndCleanTempFile(context, k, v);
});
}
private static void checkAndCleanTempFile(XContext context, String folder, String[] filePatterns) {
try {
String absoluteFolderPath = XStorageTool.getAbsolutePath(folder);
TraceHelper.appendTraceLog(context, "absolutePath", absoluteFolderPath);
File absoluteFolderPathFile = new File(absoluteFolderPath);
if (!absoluteFolderPathFile.exists()) {
TraceHelper.appendTraceLog(context, "ERROR", absoluteFolderPath + " not exists");
return;
}
String[] files = absoluteFolderPathFile.list();
for (String file : files) {
TraceHelper.appendTraceLog(context, "", file);
for (String pattern : filePatterns) {
if (Pattern.compile(pattern).matcher(file).find()) {
TraceHelper.appendTraceLog(context, "FOUND", file);
File f = new File(absoluteFolderPath, file);
try {
if (checkTimeAndDeleteFile(f)) {
TraceHelper.appendTraceLog(context, "Removed", absoluteFolderPathFile.getAbsolutePath());
}
} catch (Exception ex2) {
TraceHelper.appendTraceLog(context, ex2);
}
break;
}
}
}
} catch (Exception ex) {
CounterBuilder.globalCounterBuilder.addCounter(ex);
CounterBuilder.globalCounterBuilder.addCounter("checkAndCleanTempFile-ERROR-" + folder);
}
}
private static boolean checkTimeAndDeleteFile(File file) throws IOException {
Path path = file.toPath();
BasicFileAttributes file_att = Files.readAttributes(
path, BasicFileAttributes.class);
long createTime = file_att.creationTime().toMillis();
long now = System.currentTimeMillis();
if (now - createTime < TimeSpanChecker.TIMESPAN_MS_1d) {
return false;
}
file.delete();
return true;
}
}
\ No newline at end of file
package pps.core.common.provider.impl;
import cn.hutool.core.text.CharSequenceUtil;
import pps.core.common.cache.ConfigCache;
import pps.core.common.utils.CounterBuilder;
import xstartup.annotation.XImplement;
import xstartup.base.XContext;
import xstartup.kernel.system.provider.spec.XConfigProvider;
/**
* @author lixueyan
* @date 2022/8/5 0005 17:11
*/
@XImplement
public class PpsConfigProviderCommonImpl implements XConfigProvider {
@Override
public String findValue(XContext context, String config, String app, String key) {
// 实现自定义配置逻辑, 优先级 从低到高 数据库->properties文件
//从Properties文件中加载配置值
String configKey = config + "." + key;
String configKeyWithAppName = config + "." + app + "." + key;
String configValue = context.getProperty(configKeyWithAppName);
if (CharSequenceUtil.isBlank(configValue)) {
configValue = context.getProperty(configKey);
}
//加载缓存
final String configValue_ = configValue;
ConfigCache configCache = ConfigCache.get(context, configKey, false, () -> {
try {
CounterBuilder.globalCounterBuilder.addCounter("getConfig-Failed-" + configKey);
// 使用Properties配置文件配置
return configValue_;
} catch (Exception ex) {
CounterBuilder.globalCounterBuilder.addCounter(ex, this.getClass());
return configValue_;
}
});
//返回缓存缺省值
return configCache == null ? configValue_ : configCache.getConfigValue();
}
}
package pps.core.common.service.data;
import pps.core.common.utils.DynObj;
public class CounterOutput extends DynObj {
}
package pps.core.common.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 转换工具类
*
* @author lixueyan
*/
public class ConvertUtils {
private static Logger logger = LoggerFactory.getLogger(ConvertUtils.class);
public static <T> T sourceToTarget(Object source, Class<T> target) {
if (source == null) {
return null;
}
T targetObject = null;
try {
targetObject = target.newInstance();
BeanUtils.copyProperties(source, targetObject);
} catch (Exception e) {
logger.error("convert error ", e);
}
return targetObject;
}
public static <T> List<T> sourceToTarget(Collection<?> sourceList, Class<T> target) {
if (sourceList == null) {
return null;
}
List targetList = new ArrayList<>(sourceList.size());
try {
for (Object source : sourceList) {
T targetObject = target.newInstance();
BeanUtils.copyProperties(source, targetObject);
targetList.add(targetObject);
}
} catch (Exception e) {
logger.error("convert error ", e);
}
return targetList;
}
}
package pps.core.common.utils; package pps.core.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.CharSequenceUtil;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
...@@ -21,15 +22,14 @@ public class CounterBuilder { ...@@ -21,15 +22,14 @@ public class CounterBuilder {
public static final String COUNTER_NAME_BUILDTIME = "__BUILDTIME__"; public static final String COUNTER_NAME_BUILDTIME = "__BUILDTIME__";
private final static ConcurrentHashMap<String, CounterBuilder> counterBuilders = new ConcurrentHashMap<>(); private final static ConcurrentHashMap<String, CounterBuilder> counterBuilders = new ConcurrentHashMap<>();
public final String counterId = UUID.randomUUID().toString(); public final String counterId = UUID.randomUUID().toString();
// private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private final ConcurrentHashMap<String, String> fieldValueMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, String> fieldValueMap = new ConcurrentHashMap<String, String>();
private final ConcurrentHashMap<String, AtomicLong> counterMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, AtomicLong> counterMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, CounterBuildItemInfoType> fileInfoTypeMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, CounterBuildItemInfoType> fileInfoTypeMap = new ConcurrentHashMap<>();
private String groupName; private String groupName;
public CounterBuilder() { public CounterBuilder() {
this.setFieldValue("__COUNTERID__", counterId); this.setFieldValue("__COUNTERID__", counterId);
this.setFieldValue("__CREATETIME__", DateUtil.getCurrentDateTime()); this.setFieldValue("__CREATETIME__", DateUtil.date().toString());
} }
public CounterBuilder(String groupName) { public CounterBuilder(String groupName) {
...@@ -210,7 +210,7 @@ public class CounterBuilder { ...@@ -210,7 +210,7 @@ public class CounterBuilder {
@Override @Override
public String toString() { public String toString() {
ArrayList<String> lines = new ArrayList<String>(this.fieldValueMap.size() + this.counterMap.size()); ArrayList<String> lines = new ArrayList<>(this.fieldValueMap.size() + this.counterMap.size());
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
......
package pps.core.common.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DynamicPwd {
public static String buildDynPwd() {
String str = new SimpleDateFormat("dd:HH:mm").format(new Date());
String[] items = str.split(":");
String pwd = String.format("%02d%02d%02d", Integer.parseInt(items[2]), Integer.parseInt(items[1]) + 1, Integer.parseInt(items[0]));
return pwd;
}
public static void main(String[] args) throws Exception {
String pwd = buildDynPwd();
System.out.println(pwd);
}
}
...@@ -389,7 +389,7 @@ public class ExcelUtils { ...@@ -389,7 +389,7 @@ public class ExcelUtils {
String returnValue = null; String returnValue = null;
switch (cell.getCellType()) { switch (cell.getCellType()) {
case NUMERIC: //数字 case NUMERIC: //数字
if (XSSFDateUtil.isCellDateFormatted(cell)) { if (DateUtil.isCellDateFormatted(cell)) {
Date d = cell.getDateCellValue(); Date d = cell.getDateCellValue();
returnValue = XDateUtils.getDateTimeString(d); returnValue = XDateUtils.getDateTimeString(d);
} else { } else {
......
package pps.core.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
public class ExceptionHelper {
public static final String LINE_SEPERTOR = System.getProperty("line.separator");
public static String getExceptionLogDetail(Throwable e) {
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
try {
e.printStackTrace(printWriter);
printWriter.flush();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("EXCEPTION:").append(e.getClass().getName()).append(LINE_SEPERTOR)
.append(" Message:").append(e.getMessage()).append(LINE_SEPERTOR)
.append(" Stack:").append(writer.toString());
return stringBuilder.toString();
// return "EXCEPTION:" + e.getClass().getName() + lineSepertor
// + " Message:" + e.getMessage() + lineSepertor
// + " StackTrack:" + writer.toString();
} finally {
printWriter.close();
}
}
}
package pps.core.common.utils;
import cn.hutool.core.date.DateUtil;
import xstartup.base.XContext;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
public enum FiveSecondsTimerJobHelper implements Runnable {
INSTANCE;
private ReentrantLock lock = new ReentrantLock();
private Thread timerThread;
private List<Runnable> tasks = new ArrayList<>();
private XContext context;
public XContext getContext() {
return context;
}
public void setContext(XContext context) {
this.context = context;
}
public void register(Runnable runnable) {
lock.lock();
try {
this.tasks.add(runnable);
CounterBuilder.globalCounterBuilder.setFieldValue("FiveSecondsTimer-Tasks", this.tasks.size() + "");
if (timerThread == null) {
// 启动线程
timerThread = new Thread(this);
timerThread.setName("FiveSecondsTimerJobThread");
timerThread.start();
}
} finally {
lock.unlock();
}
}
@Override
public void run() {
try {
while (true) {
this.tasks.forEach(task -> {
try {
task.run();
} catch (Exception ex) {
CounterBuilder.globalCounterBuilder.addCounter("FiveSecondsTimerTaskException");
CounterBuilder.globalCounterBuilder.addCounter(ex, this.getClass());
}
});
Thread.sleep(5000);
CounterBuilder.globalCounterBuilder.addCounter("FiveSecondsTimer");
CounterBuilder.globalCounterBuilder.setFieldValue("FiveSecondsTimer-LastTime", DateUtil.date().toString());
}
} catch (Exception ex) {
CounterBuilder.globalCounterBuilder.addCounter(ex, this.getClass());
}
}
}
package pps.core.common.utils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public enum GlobalExecutorService {
INSTANCE;
private final ExecutorService executor = new ThreadPoolExecutor(10, 100, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
private AtomicLong runningTaskCounter = new AtomicLong(0);
private AtomicLong taskCounter = new AtomicLong(0);
public void execute(Runnable runnable) {
this.executor.execute(runnable);
runningTaskCounter.getAndAdd(1);
taskCounter.getAndAdd(1);
}
public void executeDone(int count) {
runningTaskCounter.addAndGet(-count);
}
public long getRunningTasksCount() {
return runningTaskCounter.get();
}
public long getTasksCount() {
return taskCounter.get();
}
}
package pps.core.common.utils;
/**
* @Description 雪花算法
*/
public class IdWorker {
private final long twepoch = 1288834974657L;
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceBits = 12L;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public static void main(String[] args) {
IdWorker idWorker = new IdWorker(0, 0);
for (int i = 0; i < 100; i++) {
long id = idWorker.nextId();
System.out.println(id);
}
}
/**
* 获得下一个ID (该方法是线程安全的)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
//如果毫秒相同,则从0递增生成序列号
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}
//上次生成ID的时间截
lastTimestamp = timestamp;
//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift) //
| (workerId << workerIdShift) //
| sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return System.currentTimeMillis();
}
}
\ No newline at end of file
package pps.core.common.utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import java.util.List;
public class ImportExcelUtils {
/**
* 判断Excel当前行是否为空
*
* @param row
* @return
*/
public static boolean isRowEmpty(Row row) {
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
Cell cell = row.getCell(c);
if (cell != null && cell.getCellType() != CellType.BLANK)
return false;
}
return true;
}
/**
* 数据非空校验
* 规则:titles 中 含有 * 的 会进行非空校验
*
* @param row
* @param titles
* @return
*/
public static String checkData(Row row, List<String> titles) {
DataFormatter formatter = new DataFormatter();
for (int i = 0; i < titles.size(); i++) {
Cell cell = row.getCell(i);
if (titles.get(i).startsWith("*") && StringUtils.isBlank(formatter.formatCellValue(cell))) {
String msg = String.format("第%s行 %s 不能为空", (i + 1), titles.get(i).replace("*", ""));
return msg;
}
}
return null;
}
}
package pps.core.common.utils;
import cn.hutool.core.text.CharSequenceUtil;
import com.google.common.base.Joiner;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* IP地址
*
* @author lixueyan
*/
public class IpUtils {
private static Logger logger = LoggerFactory.getLogger(IpUtils.class);
private volatile static String ips;
/**
* 获取IP地址
* <p>
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String unknown = "unknown";
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.isEmpty() || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
return ip;
}
public synchronized static String getHostIPs() {
return getHostIPs(false);
}
public static String getHostIPs(boolean refresh) {
if (!refresh && CharSequenceUtil.isNotBlank(ips)) {
return ips;
}
List<String> list = new ArrayList<>();
try {
Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface nint = en.nextElement();
if (nint.isLoopback()) {
continue;
}
if (nint.isPointToPoint()) {
continue;
}
if (nint.isVirtual()) {
continue;
}
if (!nint.isUp()) {
continue;
}
List<InterfaceAddress> interfaceAddresses = nint.getInterfaceAddresses();
if (interfaceAddresses == null) {
continue;
}
interfaceAddresses.forEach(item -> {
String addr = item.getAddress().getHostAddress();
if (CharSequenceUtil.isNotBlank(addr)) {
list.add(addr.trim());
}
});
}
} catch (java.net.SocketException e) {
// fine, let's take is as signal of not having any interfaces
}
list.sort((x, y) -> {
return x.compareTo(y);
});
ips = Joiner.on(",").join(list);
return ips;
}
}
package pps.core.common.utils;
import java.security.MessageDigest;
/**
* @author lixueyan
* @date 2022/11/11 0011 16:11
*/
public class MD5Util {
private static byte[] md5(String s) {
MessageDigest algorithm;
try {
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
} catch (Exception e) {
System.out.println("MD5 Error..." + e.getMessage());
}
return null;
}
private static final String toHex(byte hash[]) {
if (hash == null) {
return null;
}
StringBuffer buf = new StringBuffer(hash.length * 2);
int i;
for (i = 0; i < hash.length; i++) {
if ((hash[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString(hash[i] & 0xff, 16));
}
return buf.toString();
}
public static String hash(String s) {
try {
return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
} catch (Exception e) {
System.out.println("not supported charset..." + e.getMessage());
return s;
}
}
/**
* 对密码按照用户名,密码,盐进行加密
*
* @param username 用户名
* @param password 密码
* @param salt 盐
* @return
*/
public static String encryptPassword(String username, String password, String salt) {
return MD5Util.hash(username + password + salt);
}
/**
* 对密码按照密码,盐进行加密
*
* @param password 密码
* @param salt 盐
* @return
*/
public static String encryptPassword(String password, String salt) {
return MD5Util.hash(password + salt);
}
/**
* 对密码按照密码,盐进行加密
*
* @param password 密码
* @return
*/
public static String encryptPassword(String password) {
return MD5Util.hash(password);
}
}
package pps.core.common.utils;
public class NumUtils {
public static void main(String[] args) {
System.out.println(digitUppercase(11120.1));
}
/**
* 数字金额大写转换
*
* @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("^整$", "零整");
}
public static String getCode() {
return String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
}
}
package pps.core.common.utils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public enum ScadaExecutorService {
INSTANCE;
private final ExecutorService executor = new ThreadPoolExecutor(1, 50, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
private AtomicLong runningTaskCounter = new AtomicLong(0);
private AtomicLong taskCounter = new AtomicLong(0);
public void execute(Runnable runnable) {
this.executor.execute(runnable);
runningTaskCounter.getAndAdd(1);
taskCounter.getAndAdd(1);
}
public void executeDone(int count) {
runningTaskCounter.addAndGet(-count);
}
public long getRunningTasksCount() {
return runningTaskCounter.get();
}
public long getTasksCount() {
return taskCounter.get();
}
}
package pps.core.common.utils;
import cn.hutool.core.text.CharSequenceUtil;
import xstartup.base.util.XJsonUtils;
import xstartup.base.util.XStringUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
public class SmartRecord extends LinkedHashMap<String, Object> {
public SmartRecord() {
}
public SmartRecord(LinkedHashMap r) {
if (r != null) {
this.putAll(r);
}
}
public static <T> List<T> toList(List<SmartRecord> queryResult, Class<T> clz) {
final List<T> list = new ArrayList<T>();
queryResult.forEach(r -> {
list.add(r.toObj(clz));
});
return list;
}
public static List<SmartRecord> buildSmartRecords(List<LinkedHashMap<String, Object>> queryResult) {
final List<SmartRecord> list = new ArrayList<SmartRecord>();
queryResult.forEach(r -> {
list.add(new SmartRecord(r));
});
return list;
}
public Boolean boolValue(String fieldName) {
return boolValue(fieldName, Boolean.FALSE);
}
public Boolean boolValue(String fieldName, Boolean defaultValue) {
if (!this.containsKey(fieldName)) {
return defaultValue;
}
Object v = this.get(fieldName);
if (v == null) {
return Boolean.FALSE;
}
String strV = v.toString();
if (strV.equals("0") || strV.equals("false") || strV.equals("False")) {
return Boolean.FALSE;
}
return Boolean.TRUE;
}
public String strValue(String fieldName) {
return strValue(fieldName, "");
}
public String strValue(String fieldName, String defaultValue) {
if (!this.containsKey(fieldName)) {
return defaultValue;
}
Object v = this.get(fieldName);
if (v == null) {
return null;
}
return v.toString();
}
public Integer intValue(String fieldName) {
return intValue(fieldName, null);
}
public Integer intValue(String fieldName, Integer defaultValue) {
String strValue = strValue(fieldName, null);
if (CharSequenceUtil.isBlank(strValue)) {
return defaultValue;
} else {
return Integer.parseInt(strValue);
}
}
public Double doubleValue(String fieldName) {
return doubleValue(fieldName, null);
}
public Double doubleValue(String fieldName, Double defaultValue) {
String strValue = strValue(fieldName, null);
if (CharSequenceUtil.isBlank(strValue)) {
return defaultValue;
} else {
return Double.parseDouble(strValue);
}
}
public <T> T parseFromJson(String fieldName, Class<T> clz) {
String json = strValue(fieldName);
if (json == null || CharSequenceUtil.isBlank(json)) {
return null;
}
return XJsonUtils.toObject(json, clz);
}
public <T> T toObj(Class<T> clz) {
String json = XJsonUtils.toJson(this.columnOrPathToClass());
if (json == null || CharSequenceUtil.isBlank(json)) {
return null;
}
return XJsonUtils.toObject(json, clz);
}
public SmartRecord columnOrPathToClass() {
SmartRecord r = new SmartRecord();
this.keySet().forEach(k -> {
r.put(XStringUtils.columnToCamel(k), this.get(k));
});
return r;
}
public String valueJoin(String... fieldNames) {
StringBuilder sb = new StringBuilder();
for (String fieldName : fieldNames) {
String strValue = strValue(fieldName, "");
if (sb.length() > 0) {
sb.append(",");
}
sb.append(strValue);
}
return sb.toString();
}
}
package pps.core.common.utils;
import cn.hutool.core.text.CharSequenceUtil;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SqlFilter {
public static final List<String> BAD_KEYWORDS = Arrays.asList(
"select", "update", "delete", "insert", "truncate"
, "and", "or", "char", "into", "substr"
, "ascii", "declare", "exec", "count", "master"
, "drop", "execute", "table", "sitename", "xp_cmdshell"
, "like", "from", "grant", "use", "group_concat"
, "column_name", "information_schema.columns", "table_schema"
, "union", "where", "order", "by", "add"
, "all", "alter", "any", "as", "create"
, "in", "join", "inner", "not", "set"
, "--", "--;", ";--");
public static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
public static final Splitter SPLITTER_WHITESPACE = Splitter.on(PATTERN_WHITESPACE);
public static final Joiner JOINER_WHITESPACE = Joiner.on(" ");
public static final Pattern BAD_FORM_PATTERN_KEYWORDS = Pattern.compile("^(" + String.join("|", BAD_KEYWORDS) + ")$", Pattern.CASE_INSENSITIVE);
public static final String BAD_FORM_PATTERN_STR = "'|\\*|/|\\\\|--.*";//过滤掉的sql关键字,特殊字符前面需要加\\进行转义
public static final Pattern BAD_FORM_PATTERN = Pattern.compile(BAD_FORM_PATTERN_STR, Pattern.CASE_INSENSITIVE);
public static final String filterValue(String original) {
if (CharSequenceUtil.isBlank(original)) {
return original;
}
original = original.trim();
if (CharSequenceUtil.isBlank(original)) {
return original;
}
if (!PATTERN_WHITESPACE.matcher(original).find()) {
//没有空格
return filterValueNoSpace(original);
}
List<String> keywords = SPLITTER_WHITESPACE.splitToList(original);
List<String> fixedKeywords = new ArrayList<String>(keywords.size());
keywords.forEach(keyword -> {
String fixed = filterValueNoSpace(keyword);
if (CharSequenceUtil.isNotBlank(fixed)) {
fixedKeywords.add(fixed);
}
});
if (fixedKeywords.isEmpty()) {
return "";
}
return JOINER_WHITESPACE.join(fixedKeywords);
}
private static String filterValueNoSpace(String original) {
//关键字查询
Matcher matcher = BAD_FORM_PATTERN_KEYWORDS.matcher(original);
if (matcher.find()) {
return "";
}
Matcher matcher1 = BAD_FORM_PATTERN.matcher(original);
if (matcher1.find()) {
original = matcher1.replaceAll("");
}
return original;
}
}
package pps.core.common.utils;
public class StringAlignHelper {
/**
* 复制字符
*
* @param c 字符
* @param num 数量
* @return 新字符串
*/
public static String dup(char c, int num) {
if (c == 0 || num < 1) {
return "";
}
if (num == 1) {
return c + "";
}
StringBuilder sb = new StringBuilder(num);
for (int i = 0; i < num; i++) {
sb.append(c);
}
return sb.toString();
}
public static void dup(char c, int num, StringBuilder sb) {
if (c == 0 || num < 1) {
return;
}
for (int i = 0; i < num; i++) {
sb.append(c);
}
return;
}
/**
* 在字符串左侧填充一定数量的特殊字符
*
* @param o 可被 toString 的对象
* @param width 字符数量
* @param c 字符
* @return 新字符串
*/
public static String alignRight(Object o, int width, char c) {
if (null == o) {
return null;
}
String s = o.toString();
int len = charLength(s);
if (len >= width) {
return s;
}
return new StringBuilder(width).append(dup(c, width - len)).append(s).toString();
}
/**
* 在字符串右侧填充一定数量的特殊字符
*
* @param o 可被 toString 的对象
* @param width 字符数量
* @param c 字符
* @return 新字符串
*/
public static String alignLeft(Object o, int width, char c) {
if (null == o) {
return null;
}
String s = o.toString();
int length = charLength(s);
if (length >= width) {
return s;
}
return new StringBuilder(width).append(s).append(dup(c, width - length)).toString();
}
public static String alignCenter(Object o, int width, char c) {
if (null == o) {
return null;
}
String s = o.toString();
int length = charLength(s);
if (length >= width) {
return s;
}
int half = (width - length) / 2;
StringBuilder stringBuilder = new StringBuilder(width);
dup(c, half, stringBuilder);
stringBuilder.append(s);
dup(c, width - length - half, stringBuilder);
return stringBuilder.toString();
}
public static boolean isFullWidthCharacter(char c) {
// 全角空格为12288,半角空格为32
// 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
// 全角空格 || 其他全角字符
if (c == 12288 || (c > 65280 && c < 65375)) {
return true;
}
// 中文全部是全角
if (isChineseCharacter(c)) {
return true;
}
// 日文判断
// 全角平假名 u3040 - u309F
// 全角片假名 u30A0 - u30FF
if (c >= '\u3040' && c <= '\u30FF') {
return true;
}
return false;
}
/**
* 是中文字符吗?
*
* @param c 待判定字符
* @return 判断结果
*/
public static boolean isChineseCharacter(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
return true;
}
return false;
}
/**
* 计算字符串的字符长度(全角算2, 半角算1)
*
* @param str 被计算的字符串
* @return 字符串的字符长度
*/
public static int charLength(CharSequence str) {
int clength = 0;
for (int i = 0; i < str.length(); i++) {
clength += isFullWidthCharacter(str.charAt(i)) ? 2 : 1;
}
return clength;
}
}
package pps.core.common.utils;
import cn.hutool.core.text.CharSequenceUtil;
import java.util.ArrayList;
import java.util.Set;
public class ThreadHelper {
public static final String LINE_SEPERATOR = System.getProperty("line.separator");
public static String buildThreadsSimpleInfos(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
}
try {
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
ArrayList<Thread> threads = new ArrayList<>(threadSet.size());
threads.addAll(threadSet);
threads.sort((x, y) -> x.getName().compareTo(y.getName()));
//int i = 0;
for (Thread t : threads) {
//i++;
sb.append(t.getName());
sb.append("(");
sb.append(t.getId());
sb.append("),");
}
sb.append("TOTAL : ").append(threadSet.size());
} catch (Exception ex) {
}
return sb.toString();
}
public static void buildThreadsInfos(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
ArrayList<Thread> threads = new ArrayList<>(threadSet.size());
threads.addAll(threadSet);
threads.sort((x, y) -> x.getName().compareTo(y.getName()));
//int i = 0;
for (Thread t : threads) {
//i++;
sb.append("[");
sb.append(t.getName());
sb.append("] ID:");
sb.append(t.getId());
sb.append(LINE_SEPERATOR);
sb.append(arrayToString(t.getStackTrace(), LINE_SEPERATOR));
sb.append(LINE_SEPERATOR);
sb.append(LINE_SEPERATOR);
}
sb.append("TOTAL : ").append(threadSet.size()).append(LINE_SEPERATOR);
for (Thread item : threads) {
sb.append(item.getName()).append(LINE_SEPERATOR);
}
}
public static String arrayToString(Object[] a, String seperator) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
if (CharSequenceUtil.isBlank(seperator))
seperator = ", ";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax) {
return b.append(']').toString();
}
b.append(seperator);
}
}
}
package pps.core.common.utils;
import cn.hutool.core.text.CharSequenceUtil;
import java.util.concurrent.ConcurrentHashMap;
public class TimeSpanChecker {
public final static int TIMESPAN_MS_5s = 5 * 1000;
public final static int TIMESPAN_MS_10s = 10 * 1000;
public final static int TIMESPAN_MS_15s = 15 * 1000;
public final static int TIMESPAN_MS_30s = 30 * 1000;
public final static int TIMESPAN_MS_1m = 60 * 1000;
public final static int TIMESPAN_MS_5m = 5 * 60 * 1000;
public final static int TIMESPAN_MS_10m = 10 * 60 * 1000;
public final static int TIMESPAN_MS_30m = 30 * 60 * 1000;
public final static int TIMESPAN_MS_1h = 60 * 60 * 1000;
public final static int TIMESPAN_MS_1d = 24 * 60 * 60 * 1000;
private static final ConcurrentHashMap<String, TimeSpanChecker> checkers = new ConcurrentHashMap<>();
private final boolean skipFirstCheck;
private long preCheckTimeMs = 0;
private int seconds = 5;
public TimeSpanChecker(int _seconds) {
this.seconds = _seconds;
this.skipFirstCheck = true;
}
// public Date getPreCheckTimeMs() {
// return preCheckTimeMs;
// }
public TimeSpanChecker(int _seconds, boolean _skipFirstCheck) {
this.seconds = _seconds;
this.skipFirstCheck = _skipFirstCheck;
}
public static int getChecksSize() {
return checkers.size();
}
public static boolean checkNow(String checkerName, int seconds) {
return checkNow(checkerName, seconds, true);
}
public static boolean checkNow(String checkerName, int seconds, boolean skipFirstCheck) {
if (CharSequenceUtil.isBlank(checkerName) || seconds <= 0) {
return false;
}
if (checkers.containsKey(checkerName)) {
checkers.put(checkerName, new TimeSpanChecker(seconds, skipFirstCheck));
}
return checkers.get(checkerName).checkNow();
}
public static double timeUsed(Runnable runnable) {
long start = System.currentTimeMillis();
runnable.run();
long end = System.currentTimeMillis();
return (end - start) / 1000.0;
}
public boolean isSkipFirstCheck() {
return skipFirstCheck;
}
public int getSeconds() {
return seconds;
}
public void setSeconds(int seconds) {
this.seconds = seconds;
}
public boolean checkNow() {
if (preCheckTimeMs == 0) {
if (skipFirstCheck) {
preCheckTimeMs = System.currentTimeMillis();
return false;
} else {
preCheckTimeMs = System.currentTimeMillis();
return true;
}
}
double ms = System.currentTimeMillis() - this.preCheckTimeMs;
if (ms >= this.seconds * 1000) {
preCheckTimeMs = System.currentTimeMillis();
return true;
}
return false;
}
}
package pps.core.common.utils;
import org.apache.poi.ss.usermodel.DateUtil;
import java.util.Calendar;
/**
* @author lixueyan
* @date 2023/2/9 0009 13:41
*/
public class XSSFDateUtil extends DateUtil {
protected static int absoluteDay(Calendar cal, boolean use1904windowing) {
return DateUtil.absoluteDay(cal, use1904windowing);
}
}
...@@ -130,11 +130,6 @@ public class SysDictionaryService { ...@@ -130,11 +130,6 @@ public class SysDictionaryService {
if (entity.getEndTime() != null) { if (entity.getEndTime() != null) {
long l = entity.getEndTime().getTime() - System.currentTimeMillis(); long l = entity.getEndTime().getTime() - System.currentTimeMillis();
if (l > 0) { if (l > 0) {
/*List<SysDictionaryCache> list = SysDictionaryCache.list(context, alias);
SysDictionaryCache sysDictionaryCache = new SysDictionaryCache();
XCopyUtils.copyObject(entity, sysDictionaryCache);
list.add(sysDictionaryCache);
SysDictionaryCache.set(context, alias, list);*/
SysDictionaryCache.deleteCache(context, alias); SysDictionaryCache.deleteCache(context, alias);
QueryWrapper<SysDictionaryEnt> queryAlias = new QueryWrapper<>(); QueryWrapper<SysDictionaryEnt> queryAlias = new QueryWrapper<>();
queryAlias.lambda().eq(SysDictionaryEnt::getAlias, alias).gt(SysDictionaryEnt::getEndTime, new Date()); queryAlias.lambda().eq(SysDictionaryEnt::getAlias, alias).gt(SysDictionaryEnt::getEndTime, new Date());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment