generated from mingliqiye/lib-tem
feat(utils): 添加高精度时间获取功能并优化相关工具类
All checks were successful
Gitea Actions Build / Build (push) Successful in 54s
All checks were successful
Gitea Actions Build / Build (push) Successful in 54s
- 新增 AutoConfiguration 类,用于 Spring Boot 自动配置 - 添加高精度时间获取功能,兼容 Java1.8 及以上版本- 优化 DateTime 类,增加 fileTimeToLocalDateTime 方法 - 更新 ForEach 类,增加对基本类型数组的遍历支持 -调整 Factory 类,使用 BEANS 和 TYPE_BEANS 替代原变量名 - 更新 ByteUtil 类,添加常用字节常量- 修改 HashUtils 类,优化文件读取缓冲区大小
This commit is contained in:
parent
cb10406455
commit
9ebd09a810
@ -1,3 +1,6 @@
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
plugins {
|
||||
idea
|
||||
id("java-library")
|
||||
@ -22,18 +25,17 @@ java {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
annotationProcessor("org.jetbrains:annotations:24.0.0")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.38")
|
||||
compileOnly("org.springframework.boot:spring-boot-starter:2.7.14")
|
||||
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2")
|
||||
compileOnly("org.mybatis:mybatis:3.5.19")
|
||||
|
||||
compileOnly("org.projectlombok:lombok:1.18.38")
|
||||
implementation("org.bouncycastle:bcprov-jdk18on:1.81")
|
||||
implementation("com.github.f4b6a3:uuid-creator:6.1.0")
|
||||
implementation("org.mindrot:jbcrypt:0.4")
|
||||
implementation("org.jetbrains:annotations:24.0.0")
|
||||
compileOnly("org.projectlombok:lombok:1.18.38")
|
||||
|
||||
annotationProcessor("org.jetbrains:annotations:24.0.0")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.38")
|
||||
implementation("net.java.dev.jna:jna:5.17.0")
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +61,22 @@ tasks.withType<Javadoc> {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
tasks.withType<org.gradle.jvm.tasks.Jar> {
|
||||
manifest {
|
||||
attributes(
|
||||
mapOf(
|
||||
"Implementation-Title" to ARTIFACTID,
|
||||
"Implementation-Version" to VERSIONS,
|
||||
"Implementation-Package" to GROUPSID,
|
||||
"Implementation-Vendor" to "minglipro",
|
||||
"Implementation-Build-Time" to LocalDateTime.now()
|
||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
|
||||
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
@ -79,3 +97,19 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
filesMatching("META-INF/meta-data") {
|
||||
expand(
|
||||
mapOf(
|
||||
"buildTime" to LocalDateTime.now()
|
||||
.format(
|
||||
DateTimeFormatter.ofPattern(
|
||||
"yyyy-MM-dd HH:mm:ss.SSSSSSS"
|
||||
)
|
||||
)
|
||||
) + project.properties
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
JDKVERSIONS=1.8
|
||||
GROUPSID=com.mingliqiye.utils
|
||||
ARTIFACTID=mingli-utils
|
||||
VERSIONS=1.1.4
|
||||
VERSIONS=2.0.0
|
||||
|
7
resources/META-INF/meta-data
Normal file
7
resources/META-INF/meta-data
Normal file
@ -0,0 +1,7 @@
|
||||
buildTime=$buildTime
|
||||
groupId=$GROUPSID
|
||||
artifactId=$ARTIFACTID
|
||||
version=$VERSIONS
|
||||
buildJdkVersion=$JDKVERSIONS
|
||||
author=MingLiPro
|
||||
website=mingliqiye.com
|
@ -0,0 +1 @@
|
||||
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
|
@ -19,13 +19,13 @@ public class Factory {
|
||||
/**
|
||||
* 存储所有已注册的Bean实例,键为Bean名称,值为Bean实例
|
||||
*/
|
||||
public static final ConcurrentMap<String, Object> beans =
|
||||
public static final ConcurrentMap<String, Object> BEANS =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 存储按类型查找的Bean实例,键为Bean的Class对象,值为Bean实例
|
||||
*/
|
||||
private static final ConcurrentMap<Class<?>, Object> typeBeans =
|
||||
private static final ConcurrentMap<Class<?>, Object> TYPE_BEANS =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
@ -114,11 +114,11 @@ public class Factory {
|
||||
? clazz.getName()
|
||||
: component.value();
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
beans.put(name, instance);
|
||||
typeBeans.put(clazz, instance);
|
||||
BEANS.put(name, instance);
|
||||
TYPE_BEANS.put(clazz, instance);
|
||||
|
||||
for (Class<?> interfaceClass : clazz.getInterfaces()) {
|
||||
typeBeans.putIfAbsent(interfaceClass, instance);
|
||||
TYPE_BEANS.putIfAbsent(interfaceClass, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,7 +129,7 @@ public class Factory {
|
||||
* @throws Exception 如果在注入过程中发生异常
|
||||
*/
|
||||
private static void injectDependencies() throws Exception {
|
||||
for (Object bean : beans.values()) {
|
||||
for (Object bean : BEANS.values()) {
|
||||
for (Field field : bean.getClass().getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(InjectBean.class)) {
|
||||
InjectBean inject = field.getAnnotation(InjectBean.class);
|
||||
@ -161,17 +161,17 @@ public class Factory {
|
||||
*/
|
||||
private static Object findDependency(Class<?> type, String name) {
|
||||
if (!name.isEmpty()) {
|
||||
return beans.get(name);
|
||||
return BEANS.get(name);
|
||||
}
|
||||
|
||||
Object dependency = typeBeans.get(type);
|
||||
Object dependency = TYPE_BEANS.get(type);
|
||||
if (dependency != null) {
|
||||
return dependency;
|
||||
}
|
||||
|
||||
for (Class<?> interfaceType : typeBeans.keySet()) {
|
||||
for (Class<?> interfaceType : TYPE_BEANS.keySet()) {
|
||||
if (type.isAssignableFrom(interfaceType)) {
|
||||
return typeBeans.get(interfaceType);
|
||||
return TYPE_BEANS.get(interfaceType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,8 +187,8 @@ public class Factory {
|
||||
public static void add(Object object) {
|
||||
Class<?> clazz = object.getClass();
|
||||
String name = clazz.getName();
|
||||
beans.put(name, object);
|
||||
typeBeans.put(clazz, object);
|
||||
BEANS.put(name, object);
|
||||
TYPE_BEANS.put(clazz, object);
|
||||
try {
|
||||
injectDependencies();
|
||||
} catch (Exception e) {
|
||||
@ -204,8 +204,8 @@ public class Factory {
|
||||
* @throws RuntimeException 如果在注入依赖时发生异常
|
||||
*/
|
||||
public static void add(String name, Object object) {
|
||||
beans.put(name, object);
|
||||
typeBeans.put(object.getClass(), object);
|
||||
BEANS.put(name, object);
|
||||
TYPE_BEANS.put(object.getClass(), object);
|
||||
try {
|
||||
injectDependencies();
|
||||
} catch (Exception e) {
|
||||
@ -221,7 +221,7 @@ public class Factory {
|
||||
* @return 对应类型的Bean实例,未找到则返回null
|
||||
*/
|
||||
public static <T> T get(Class<T> objclass) {
|
||||
return objclass.cast(typeBeans.get(objclass));
|
||||
return objclass.cast(TYPE_BEANS.get(objclass));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +233,7 @@ public class Factory {
|
||||
* @return 对应名称和类型的Bean实例,未找到则返回null
|
||||
*/
|
||||
public static <T> T get(String name, Class<T> objclass) {
|
||||
return objclass.cast(beans.get(name));
|
||||
return objclass.cast(BEANS.get(name));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,6 +243,6 @@ public class Factory {
|
||||
* @return 对应名称的Bean实例,未找到则返回null
|
||||
*/
|
||||
public static Object get(String name) {
|
||||
return beans.get(name);
|
||||
return BEANS.get(name);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ComponentBean {
|
||||
|
@ -5,6 +5,9 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface InjectBean {
|
||||
|
@ -19,6 +19,9 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class SpringBeanUtil implements ApplicationContextAware {
|
||||
|
||||
public static final String PACKAGE_NAME =
|
||||
SpringBeanUtil.class.getPackage().getName();
|
||||
|
||||
/**
|
||||
* 获取applicationContext
|
||||
*/
|
||||
|
@ -11,6 +11,16 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class ByteUtil {
|
||||
|
||||
public static final byte ESC_ASC = 0x1A;
|
||||
public static final byte ESC_DESC = 0x1B;
|
||||
public static final byte ESC_NONE = 0x00;
|
||||
public static final byte ESC_START = 0x01;
|
||||
public static final byte ESC_END = 0x02;
|
||||
public static final byte ESC_ESC = 0x03;
|
||||
public static final byte ESC_CONTROL = 0x04;
|
||||
public static final byte ESC_DATA = 0x05;
|
||||
public static final byte ESC_RESERVED = 0x06;
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符串列表
|
||||
* <p>
|
||||
|
@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
/**
|
||||
* ListsAMaps 工具类提供对集合和映射的增强遍历功能。
|
||||
* 包含多个重载的 forEach 方法,支持带索引的遍历操作。
|
||||
* @author MingLiPro
|
||||
*/
|
||||
public class ForEach {
|
||||
|
||||
@ -165,6 +166,191 @@ public class ForEach {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void forEach(Consumer<? super T> action, T... objects) {
|
||||
int i = 0;
|
||||
while (i < objects.length) {
|
||||
T object = objects[i];
|
||||
action.call(object, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void forEach(T[] objects, Consumer<? super T> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
public static <T> void forEach(
|
||||
T[] objects,
|
||||
java.util.function.Consumer<? super T> action
|
||||
) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
public static <T> void forEach(
|
||||
java.util.function.Consumer<? super T> action,
|
||||
T... objects
|
||||
) {
|
||||
forEach((t, i) -> action.accept(t), objects);
|
||||
}
|
||||
|
||||
public static void forEach(int[] objects, Consumer<Integer> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Integer> action, int... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Integer> action,
|
||||
int... objects
|
||||
) {
|
||||
for (Integer object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
public static void forEach(byte[] objects, Consumer<Byte> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Byte> action, byte... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Byte> action,
|
||||
byte... objects
|
||||
) {
|
||||
for (Byte object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// short类型
|
||||
public static void forEach(short[] objects, Consumer<Short> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Short> action, short... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Short> action,
|
||||
short... objects
|
||||
) {
|
||||
for (short object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// long类型
|
||||
public static void forEach(long[] objects, Consumer<Long> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Long> action, long... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Long> action,
|
||||
long... objects
|
||||
) {
|
||||
for (long object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// float类型
|
||||
public static void forEach(float[] objects, Consumer<Float> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Float> action, float... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Float> action,
|
||||
float... objects
|
||||
) {
|
||||
for (float object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// double类型
|
||||
public static void forEach(double[] objects, Consumer<Double> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Double> action, double... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Double> action,
|
||||
double... objects
|
||||
) {
|
||||
for (double object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// char类型
|
||||
public static void forEach(char[] objects, Consumer<Character> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Character> action, char... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Character> action,
|
||||
char... objects
|
||||
) {
|
||||
for (char object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
// boolean类型
|
||||
public static void forEach(boolean[] objects, Consumer<Boolean> action) {
|
||||
forEach(action, objects);
|
||||
}
|
||||
|
||||
private static void forEach(Consumer<Boolean> action, boolean... objects) {
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
action.call(objects[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void forEach(
|
||||
java.util.function.Consumer<Boolean> action,
|
||||
boolean... objects
|
||||
) {
|
||||
for (boolean object : objects) {
|
||||
action.accept(object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义消费者接口,用于接收元素值和索引。
|
||||
*
|
||||
|
@ -39,7 +39,7 @@ public class HashUtils {
|
||||
MessageDigest digest = MessageDigest.getInstance(algorithm);
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
byte[] buffer = new byte[8192]; // 8KB 缓冲区
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
|
||||
// 分块读取文件内容并更新摘要
|
||||
|
37
src/com/mingliqiye/utils/jna/FieldStructure.java
Normal file
37
src/com/mingliqiye/utils/jna/FieldStructure.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.mingliqiye.utils.jna;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
public class FieldStructure extends Structure {
|
||||
|
||||
@Override
|
||||
protected List<String> getFieldOrder() {
|
||||
List<String> fieldOrderList = new ArrayList<String>();
|
||||
for (
|
||||
Class<?> cls = getClass();
|
||||
!cls.equals(FieldStructure.class);
|
||||
cls = cls.getSuperclass()
|
||||
) {
|
||||
Field[] fields = cls.getDeclaredFields();
|
||||
int modifiers;
|
||||
for (Field field : fields) {
|
||||
modifiers = field.getModifiers();
|
||||
if (
|
||||
Modifier.isStatic(modifiers) ||
|
||||
!Modifier.isPublic(modifiers)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
fieldOrderList.add(field.getName());
|
||||
}
|
||||
}
|
||||
return fieldOrderList;
|
||||
}
|
||||
}
|
15
src/com/mingliqiye/utils/jna/time/WinKernel32.java
Normal file
15
src/com/mingliqiye/utils/jna/time/WinKernel32.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.mingliqiye.utils.jna.time;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.ptr.LongByReference;
|
||||
|
||||
public interface WinKernel32 extends Library {
|
||||
static WinKernel32 load() {
|
||||
return Native.load("kernel32", WinKernel32.class);
|
||||
}
|
||||
|
||||
boolean QueryPerformanceCounter(LongByReference lpPerformanceCount);
|
||||
boolean QueryPerformanceFrequency(LongByReference lpFrequency);
|
||||
void GetSystemTimePreciseAsFileTime(byte[] lpSystemTimeAsFileTime);
|
||||
}
|
31
src/com/mingliqiye/utils/random/RandomBytes.java
Normal file
31
src/com/mingliqiye/utils/random/RandomBytes.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.mingliqiye.utils.random;
|
||||
|
||||
import com.mingliqiye.utils.collection.ForEach;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
public class RandomBytes {
|
||||
|
||||
public static byte[] randomBytes(int length) {
|
||||
byte[] bytes = new byte[length];
|
||||
ForEach.forEach(bytes, (b, i) ->
|
||||
bytes[i] = randomByte((byte) 0x00, (byte) 0xff)
|
||||
);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte randomByte(byte from, byte to) {
|
||||
int fromInt = from & 0xFF;
|
||||
int toInt = to & 0xFF;
|
||||
int randomValue = RandomInt.randomInt(fromInt, toInt);
|
||||
return (byte) (randomValue & 0xFF);
|
||||
}
|
||||
|
||||
public static byte randomByteNoHave(byte from, byte to) {
|
||||
int fromInt = from & 0xFF;
|
||||
int toInt = to & 0xFF;
|
||||
int randomValue = RandomInt.randomIntNoHave(fromInt, toInt);
|
||||
return (byte) (randomValue & 0xFF);
|
||||
}
|
||||
}
|
37
src/com/mingliqiye/utils/random/RandomInt.java
Normal file
37
src/com/mingliqiye/utils/random/RandomInt.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.mingliqiye.utils.random;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
public class RandomInt {
|
||||
|
||||
/**
|
||||
* 生成指定范围内的随机整数
|
||||
* @param min 最小值(包含)
|
||||
* @param max 最大值(不包含)
|
||||
* @return 随机整数
|
||||
*/
|
||||
public static int randomIntNoHave(int min, int max) {
|
||||
if (min > max) {
|
||||
int t = min;
|
||||
min = max;
|
||||
max = t;
|
||||
}
|
||||
if (min == max) {
|
||||
return min;
|
||||
}
|
||||
return ThreadLocalRandom.current().nextInt(min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指定范围内的随机整数
|
||||
* @param min 最小值(包含)
|
||||
* @param max 最大值(包含)
|
||||
* @return 随机整数
|
||||
*/
|
||||
public static int randomInt(int min, int max) {
|
||||
return randomIntNoHave(min, ++max);
|
||||
}
|
||||
}
|
24
src/com/mingliqiye/utils/random/RandomString.java
Normal file
24
src/com/mingliqiye/utils/random/RandomString.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.mingliqiye.utils.random;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
public class RandomString {
|
||||
|
||||
public static String randomString(int length, String chars) {
|
||||
String[] charsd = chars.split("");
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index = RandomInt.randomInt(0, charsd.length - 1);
|
||||
sb.append(charsd[index]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String randomString(int length) {
|
||||
return randomString(
|
||||
length,
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package com.mingliqiye.utils.springboot.autoconfigure;
|
||||
|
||||
import com.mingliqiye.utils.collection.ForEach;
|
||||
import com.mingliqiye.utils.time.DateTime;
|
||||
import com.mingliqiye.utils.time.Formatter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author MingLiPro
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AutoConfiguration.class)
|
||||
public class AutoConfiguration {
|
||||
|
||||
private static String banner =
|
||||
"---------------------------------------------------------\n" +
|
||||
"| $$\\ $$\\ $$\\ $$\\ $$\\ $$$$$$$$\\ $$$$$$\\ |\n" +
|
||||
"| $$$\\ $$$ |$$ | $$ | $$ |\\__$$ __|$$ __$$\\ |\n" +
|
||||
"| $$$$\\ $$$$ |$$ | $$ | $$ | $$ | $$ / \\__| |\n" +
|
||||
"| $$\\$$\\$$ $$ |$$ | $$ | $$ | $$ | \\$$$$$$\\ |\n" +
|
||||
"| $$ \\$$$ $$ |$$ | $$ | $$ | $$ | \\____$$\\ |\n" +
|
||||
"| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | |\n" +
|
||||
"| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ | |\n" +
|
||||
"| \\__| \\__|\\________|\\______/ \\__| \\______/ |\n";
|
||||
|
||||
public AutoConfiguration() throws IOException {
|
||||
print();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
new AutoConfiguration();
|
||||
}
|
||||
|
||||
public void print() throws IOException {
|
||||
InputStream inputStream = AutoConfiguration.class.getResourceAsStream(
|
||||
"/META-INF/meta-data"
|
||||
);
|
||||
int readlen;
|
||||
byte[] buffer = new byte[1024];
|
||||
StringBuilder metaData = new StringBuilder();
|
||||
while ((readlen = inputStream.read(buffer)) != -1) {
|
||||
metaData.append(new String(buffer, 0, readlen));
|
||||
}
|
||||
ForEach.forEach(metaData.toString().split("\n"), (s, i) -> {
|
||||
String[] d = s.trim().split("=", 2);
|
||||
if (d.length >= 2) {
|
||||
String content = "| " + d[0] + ": " + d[1];
|
||||
// 直接计算需要的空格数来对齐
|
||||
int targetLength = 56; // 为右侧的 | 留出空间
|
||||
if (content.length() < targetLength) {
|
||||
int spacesNeeded = targetLength - content.length();
|
||||
StringBuilder da = new StringBuilder(content);
|
||||
for (int ia = 0; ia < spacesNeeded; ia++) {
|
||||
da.append(" ");
|
||||
}
|
||||
banner += da + "|\n";
|
||||
} else {
|
||||
banner += content.substring(0, targetLength) + "|\n";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
System.out.printf(
|
||||
banner,
|
||||
DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7)
|
||||
);
|
||||
System.out.println(
|
||||
"---------------------------------------------------------"
|
||||
);
|
||||
}
|
||||
}
|
1318
src/com/mingliqiye/utils/stream/ListStream.java
Normal file
1318
src/com/mingliqiye/utils/stream/ListStream.java
Normal file
File diff suppressed because it is too large
Load Diff
313
src/com/mingliqiye/utils/stream/MapStream.java
Normal file
313
src/com/mingliqiye/utils/stream/MapStream.java
Normal file
@ -0,0 +1,313 @@
|
||||
package com.mingliqiye.utils.stream;
|
||||
|
||||
import com.mingliqiye.utils.collection.Lists;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
|
||||
/**
|
||||
* 用于处理键值对的流实现
|
||||
*
|
||||
* @author MingLiPro
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
*/
|
||||
public class MapStream<K, V> {
|
||||
|
||||
private final List<Map.Entry<K, V>> entries;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
*
|
||||
* @param entries 包含键值对的列表
|
||||
*/
|
||||
private MapStream(List<Map.Entry<K, V>> entries) {
|
||||
this.entries = entries != null ? entries : Lists.newArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Map创建MapStream
|
||||
*
|
||||
* @param map 输入Map
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @return MapStream实例
|
||||
*/
|
||||
public static <K, V> MapStream<K, V> of(Map<K, V> map) {
|
||||
return new MapStream<>(new ArrayList<>(map.entrySet()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从键值对数组创建MapStream
|
||||
*
|
||||
* @param entries 键值对数组
|
||||
* @param <K> 键类型
|
||||
* @param <V> 值类型
|
||||
* @return MapStream实例
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <K, V> MapStream<K, V> of(Map.Entry<K, V>... entries) {
|
||||
return new MapStream<>(Lists.newArrayList(entries));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据键过滤MapStream
|
||||
*
|
||||
* @param keyPredicate 键的谓词条件
|
||||
* @return 过滤后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> filterByKey(Predicate<? super K> keyPredicate) {
|
||||
List<Map.Entry<K, V>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
if (keyPredicate.test(entry.getKey())) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据值过滤MapStream
|
||||
*
|
||||
* @param valuePredicate 值的谓词条件
|
||||
* @return 过滤后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> filterByValue(Predicate<? super V> valuePredicate) {
|
||||
List<Map.Entry<K, V>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
if (valuePredicate.test(entry.getValue())) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤MapStream
|
||||
*
|
||||
* @param predicate 键值对的谓词条件
|
||||
* @return 过滤后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> filter(Predicate<Map.Entry<K, V>> predicate) {
|
||||
List<Map.Entry<K, V>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
if (predicate.test(entry)) {
|
||||
result.add(entry);
|
||||
}
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换键
|
||||
*
|
||||
* @param keyMapper 键映射函数
|
||||
* @param <R> 新的键类型
|
||||
* @return 转换后的MapStream
|
||||
*/
|
||||
public <R> MapStream<R, V> mapKey(
|
||||
Function<? super K, ? extends R> keyMapper
|
||||
) {
|
||||
List<Map.Entry<R, V>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
R newKey = keyMapper.apply(entry.getKey());
|
||||
result.add(new AbstractMap.SimpleEntry<>(newKey, entry.getValue()));
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换值
|
||||
*
|
||||
* @param valueMapper 值映射函数
|
||||
* @param <R> 新的值类型
|
||||
* @return 转换后的MapStream
|
||||
*/
|
||||
public <R> MapStream<K, R> mapValue(
|
||||
Function<? super V, ? extends R> valueMapper
|
||||
) {
|
||||
List<Map.Entry<K, R>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
R newValue = valueMapper.apply(entry.getValue());
|
||||
result.add(new AbstractMap.SimpleEntry<>(entry.getKey(), newValue));
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换键值对
|
||||
*
|
||||
* @param entryMapper 键值对映射函数
|
||||
* @param <R> 新的键类型
|
||||
* @param <S> 新的值类型
|
||||
* @return 转换后的MapStream
|
||||
*/
|
||||
public <R, S> MapStream<R, S> map(
|
||||
Function<Map.Entry<K, V>, Map.Entry<R, S>> entryMapper
|
||||
) {
|
||||
List<Map.Entry<R, S>> result = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
result.add(entryMapper.apply(entry));
|
||||
}
|
||||
return new MapStream<>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将键值对流转换为Map
|
||||
*
|
||||
* @return 包含所有键值对的Map
|
||||
*/
|
||||
public Map<K, V> toMap() {
|
||||
Map<K, V> map = new HashMap<>();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将键值对流转换为Map,指定Map类型和键冲突时的合并函数
|
||||
*
|
||||
* @param mapSupplier Map工厂函数
|
||||
* @param mergeFunction 键冲突合并函数
|
||||
* @param <M> Map类型
|
||||
* @return 包含所有键值对的Map
|
||||
*/
|
||||
public <M extends Map<K, V>> M toMap(
|
||||
Supplier<M> mapSupplier,
|
||||
BinaryOperator<V> mergeFunction
|
||||
) {
|
||||
M map = mapSupplier.get();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
map.merge(entry.getKey(), entry.getValue(), mergeFunction);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对每个键值对执行操作
|
||||
*
|
||||
* @param action 要执行的操作
|
||||
*/
|
||||
public void forEach(BiConsumer<? super K, ? super V> action) {
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
action.accept(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算键值对数量
|
||||
*
|
||||
* @return 键值对数量
|
||||
*/
|
||||
public long count() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取键的流
|
||||
*
|
||||
* @return 键的流
|
||||
*/
|
||||
public ListStream<K> keys() {
|
||||
List<K> keys = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
keys.add(entry.getKey());
|
||||
}
|
||||
return ListStream.of(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值的流
|
||||
*
|
||||
* @return 值的流
|
||||
*/
|
||||
public ListStream<V> values() {
|
||||
List<V> values = Lists.newArrayList();
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
values.add(entry.getValue());
|
||||
}
|
||||
return ListStream.of(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对键值对进行排序
|
||||
*
|
||||
* @param comparator 比较器
|
||||
* @return 排序后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> sorted(Comparator<Map.Entry<K, V>> comparator) {
|
||||
List<Map.Entry<K, V>> sortedEntries = Lists.newArrayList(entries);
|
||||
sortedEntries.sort(comparator);
|
||||
return new MapStream<>(sortedEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制键值对数量
|
||||
*
|
||||
* @param maxSize 最大数量
|
||||
* @return 限制后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> limit(long maxSize) {
|
||||
if (maxSize < 0) {
|
||||
throw new IllegalArgumentException("maxSize must be non-negative");
|
||||
}
|
||||
if (maxSize == 0) {
|
||||
return new MapStream<>(Lists.newArrayList());
|
||||
}
|
||||
|
||||
List<Map.Entry<K, V>> limitedEntries = Lists.newArrayList();
|
||||
long count = 0;
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
if (count >= maxSize) {
|
||||
break;
|
||||
}
|
||||
limitedEntries.add(entry);
|
||||
count++;
|
||||
}
|
||||
return new MapStream<>(limitedEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳过指定数量的键值对
|
||||
*
|
||||
* @param n 要跳过的数量
|
||||
* @return 跳过后的MapStream
|
||||
*/
|
||||
public MapStream<K, V> skip(long n) {
|
||||
if (n < 0) {
|
||||
throw new IllegalArgumentException("n must be non-negative");
|
||||
}
|
||||
if (n == 0) {
|
||||
return new MapStream<>(Lists.newArrayList(entries));
|
||||
}
|
||||
|
||||
List<Map.Entry<K, V>> skippedEntries = Lists.newArrayList();
|
||||
long count = 0;
|
||||
for (Map.Entry<K, V> entry : entries) {
|
||||
if (count >= n) {
|
||||
skippedEntries.add(entry);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return new MapStream<>(skippedEntries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (entries.isEmpty()) {
|
||||
return "MapStream()";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MapStream(");
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
Map.Entry<K, V> entry = entries.get(i);
|
||||
sb.append(entry.getKey()).append("=").append(entry.getValue());
|
||||
if (i != entries.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.mingliqiye.utils.time;
|
||||
|
||||
import com.mingliqiye.utils.jna.time.WinKernel32;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
@ -24,11 +25,23 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @see ZoneId
|
||||
* @see Instant
|
||||
*/
|
||||
|
||||
@Setter
|
||||
public final class DateTime {
|
||||
|
||||
private static final String version = System.getProperty("java.version");
|
||||
private static final WinKernel32 WIN_KERNEL_32;
|
||||
private static final long FILETIME_EPOCH_OFFSET = -116444736000000000L;
|
||||
private static final long NANOS_PER_100NS = 100;
|
||||
|
||||
static {
|
||||
if (version.startsWith("1.8")) {
|
||||
WIN_KERNEL_32 = WinKernel32.load();
|
||||
} else {
|
||||
WIN_KERNEL_32 = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private ZoneId zoneId = ZoneId.systemDefault();
|
||||
|
||||
@Getter
|
||||
@ -52,13 +65,40 @@ public final class DateTime {
|
||||
|
||||
/**
|
||||
* 获取当前时间的 DateTime 实例。
|
||||
* 如果运行在 Java 1.8 环境下,则通过 WinKernel32 获取高精度时间。
|
||||
*
|
||||
* @return 返回当前时间的 DateTime 实例
|
||||
*/
|
||||
public static DateTime now() {
|
||||
if (WIN_KERNEL_32 != null) {
|
||||
byte[] fileTimeBuffer = new byte[8];
|
||||
WIN_KERNEL_32.GetSystemTimePreciseAsFileTime(fileTimeBuffer);
|
||||
long fileTime =
|
||||
(long) (fileTimeBuffer[0] & 0xFF) |
|
||||
((long) (fileTimeBuffer[1] & 0xFF) << 8) |
|
||||
((long) (fileTimeBuffer[2] & 0xFF) << 16) |
|
||||
((long) (fileTimeBuffer[3] & 0xFF) << 24) |
|
||||
((long) (fileTimeBuffer[4] & 0xFF) << 32) |
|
||||
((long) (fileTimeBuffer[5] & 0xFF) << 40) |
|
||||
((long) (fileTimeBuffer[6] & 0xFF) << 48) |
|
||||
((long) (fileTimeBuffer[7] & 0xFF) << 56);
|
||||
long unixNanos =
|
||||
(fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS;
|
||||
Instant instant = Instant.ofEpochSecond(
|
||||
unixNanos / 1_000_000_000L,
|
||||
unixNanos % 1_000_000_000L
|
||||
);
|
||||
return DateTime.of(
|
||||
instant.atZone(ZoneId.systemDefault()).toLocalDateTime()
|
||||
);
|
||||
}
|
||||
return new DateTime();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(DateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 Date 对象转换为 DateTime 实例。
|
||||
*
|
||||
@ -215,6 +255,26 @@ public final class DateTime {
|
||||
return new DateTime(LocalDateTime.of(year, month, day, hour, minute));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 FILETIME 转换为 LocalDateTime。
|
||||
*
|
||||
* @param fileTime FILETIME 时间戳(100纳秒单位自1601年1月1日起)
|
||||
* @return 转换后的 LocalDateTime 实例
|
||||
*/
|
||||
public static LocalDateTime fileTimeToLocalDateTime(long fileTime) {
|
||||
// 1. 将 FILETIME (100ns间隔 since 1601) 转换为 Unix 时间戳 (纳秒 since 1970)
|
||||
long unixNanos = (fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS;
|
||||
|
||||
// 2. 从纳秒时间戳创建 Instant
|
||||
Instant instant = Instant.ofEpochSecond(
|
||||
unixNanos / 1_000_000_000L,
|
||||
unixNanos % 1_000_000_000L
|
||||
);
|
||||
|
||||
// 3. 转换为系统默认时区的 LocalDateTime
|
||||
return instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年、月、日、时、分、秒创建 DateTime 实例
|
||||
*
|
||||
@ -292,15 +352,6 @@ public final class DateTime {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 LocalDateTime 实例。
|
||||
*
|
||||
* @param localDateTime LocalDateTime 对象
|
||||
*/
|
||||
public void setLocalDateTime(LocalDateTime localDateTime) {
|
||||
this.localDateTime = localDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前 DateTime 转换为 Date 对象。
|
||||
*
|
||||
@ -444,7 +495,6 @@ public final class DateTime {
|
||||
* @param dateTime 指定时间
|
||||
* @return 如果当前时间在指定时间之后则返回 true,否则返回 false
|
||||
*/
|
||||
|
||||
public boolean isAfter(DateTime dateTime) {
|
||||
if (dateTime == null) {
|
||||
return false;
|
||||
@ -458,7 +508,6 @@ public final class DateTime {
|
||||
* @param dateTime 指定时间
|
||||
* @return 如果当前时间在指定时间之前则返回 true,否则返回 false
|
||||
*/
|
||||
|
||||
public boolean isBefore(DateTime dateTime) {
|
||||
if (dateTime == null) {
|
||||
return false;
|
||||
|
@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.mingliqiye.utils.time.DateTime;
|
||||
import com.mingliqiye.utils.time.Formatter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.mingliqiye.utils.uuid.UUID;
|
||||
import com.mingliqiye.utils.uuid.UUIDException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@ -24,13 +23,13 @@ public class Jackson {
|
||||
*
|
||||
* @param objectMapper ObjectMapper实例,用于注册自定义序列化模块
|
||||
*/
|
||||
public static void addSerializers(ObjectMapper objectMapper) {
|
||||
// 创建SimpleModule并添加UUID的序列化器和反序列化器
|
||||
SimpleModule module = new SimpleModule()
|
||||
.addSerializer(UUID.class, new UUIDJsonSerializer())
|
||||
.addDeserializer(UUID.class, new UUIDJsonDeserializer());
|
||||
objectMapper.registerModule(module);
|
||||
}
|
||||
public static void addSerializers(ObjectMapper objectMapper) {
|
||||
// 创建SimpleModule并添加UUID的序列化器和反序列化器
|
||||
SimpleModule module = new SimpleModule()
|
||||
.addSerializer(UUID.class, new UUIDJsonSerializer())
|
||||
.addDeserializer(UUID.class, new UUIDJsonDeserializer());
|
||||
objectMapper.registerModule(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* UUID 反序列化器
|
||||
|
Loading…
x
Reference in New Issue
Block a user