diff --git a/build.gradle.kts b/build.gradle.kts index 7b28c14..41091c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils * CurrentFile build.gradle.kts - * LastUpdate 2025-09-15 11:20:04 + * LastUpdate 2025-09-15 22:22:00 * UpdateUser MingLiPro */ @@ -77,7 +77,6 @@ dependencies { implementation("org.mindrot:jbcrypt:0.4") implementation("org.jetbrains:annotations:24.0.0") compileOnly("net.java.dev.jna:jna:5.17.0") - //implementation("jakarta.annotation:jakarta.annotation-api:2.1.1") implementation("org.slf4j:slf4j-api:2.0.17") implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1") @@ -179,7 +178,6 @@ tasks.processResources { DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss.SSSSSSS" ) - ) ) ) diff --git a/gradle.properties b/gradle.properties index 7c86e05..50a8c72 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,10 +16,10 @@ # ProjectName mingli-utils # ModuleName mingli-utils # CurrentFile gradle.properties -# LastUpdate 2025-09-15 18:03:04 +# LastUpdate 2025-09-15 22:32:50 # UpdateUser MingLiPro # JDKVERSIONS=1.8 GROUPSID=com.mingliqiye.utils ARTIFACTID=mingli-utils -VERSIONS=4.0.6 +VERSIONS=4.0.7 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 137a92b..ccf215a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -16,7 +16,7 @@ # ProjectName mingli-utils # ModuleName mingli-utils # CurrentFile gradle-wrapper.properties -# LastUpdate 2025-09-15 12:01:36 +# LastUpdate 2025-09-15 22:32:50 # UpdateUser MingLiPro # distributionBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index c6d0206..0f35bdf 100755 --- a/gradlew +++ b/gradlew @@ -18,7 +18,7 @@ # ProjectName mingli-utils # ModuleName mingli-utils # CurrentFile gradlew -# LastUpdate 2025-09-15 12:01:36 +# LastUpdate 2025-09-15 22:32:50 # UpdateUser MingLiPro # diff --git a/jdk8/build.gradle.kts b/jdk8/build.gradle.kts index 9a9e3f6..8d9980f 100644 --- a/jdk8/build.gradle.kts +++ b/jdk8/build.gradle.kts @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.jdk8 * CurrentFile build.gradle.kts - * LastUpdate 2025-09-14 18:19:04 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ plugins { diff --git a/lombok.config b/lombok.config deleted file mode 100644 index 7164ffe..0000000 --- a/lombok.config +++ /dev/null @@ -1 +0,0 @@ -lombok.addLombokGeneratedAnnotation = false diff --git a/settings.gradle.kts b/settings.gradle.kts index cb1e4c0..b55a8d5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils * CurrentFile settings.gradle.kts - * LastUpdate 2025-09-13 02:37:04 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/java/com/mingliqiye/utils/Main.java b/src/main/java/com/mingliqiye/utils/Main.java deleted file mode 100644 index 4faa62b..0000000 --- a/src/main/java/com/mingliqiye/utils/Main.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Main.java - * LastUpdate 2025-09-15 11:18:12 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils; - -public class Main { - - public static void main(String[] args) { - MainKt.main(); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java b/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java deleted file mode 100644 index 5465335..0000000 --- a/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile GsonJsonApi.java - * LastUpdate 2025-09-15 11:20:04 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -import com.google.gson.*; -import com.mingliqiye.utils.json.converters.JsonConverter; -import com.mingliqiye.utils.json.converters.JsonStringConverter; -import org.jetbrains.annotations.NotNull; - -public class GsonJsonApi implements JsonApi { - - private Gson gsonUnicode; - private Gson gsonPretty; - private Gson gsonPrettyUnicode; - private Gson gson; - - public GsonJsonApi() { - gson = new GsonBuilder() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - - gsonUnicode = new GsonBuilder() - .disableHtmlEscaping() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - - gsonPretty = new GsonBuilder() - .setPrettyPrinting() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - - gsonPrettyUnicode = new GsonBuilder() - .setPrettyPrinting() - .disableHtmlEscaping() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - } - - public GsonJsonApi(Gson gson) { - this.gson = gson - .newBuilder() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - this.gsonUnicode = gson - .newBuilder() - .disableHtmlEscaping() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - this.gsonPretty = gson - .newBuilder() - .setPrettyPrinting() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - this.gsonPrettyUnicode = gson - .newBuilder() - .setPrettyPrinting() - .disableHtmlEscaping() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .create(); - } - - @Override - public T parse(String json, Class clazz) { - return gson.fromJson(json, clazz); - } - - @Override - public T parse(String json, JsonTypeReference type) { - return gson.fromJson(json, type.getType()); - } - - @Override - public String format(Object object) { - return gson.toJson(object); - } - - @Override - public String formatUnicode(Object object) { - return gsonUnicode.toJson(object); - } - - @Override - public String formatPretty(Object object) { - return gsonPretty.toJson(object); - } - - @Override - public String formatPrettyUnicode(Object object) { - return gsonPrettyUnicode.toJson(object); - } - - @Override - public boolean isValidJson(String json) { - try { - JsonElement element = JsonParser.parseString(json); - return true; - } catch (JsonSyntaxException e) { - return false; - } catch (Exception e) { - return false; - } - } - - @Override - public String merge(String... jsons) { - JsonObject merged = new JsonObject(); - for (String json : jsons) { - if (json == null || json.isEmpty()) { - continue; - } - try { - JsonObject obj = JsonParser.parseString(json).getAsJsonObject(); - for (String key : obj.keySet()) { - merged.add(key, obj.get(key)); - } - } catch (Exception e) { - // 忽略无效的 JSON 字符串 - } - } - return gson.toJson(merged); - } - - @Override - public String getNodeValue(String json, String path) { - try { - JsonElement element = JsonParser.parseString(json); - String[] paths = path.split("\\."); - JsonElement current = element; - - for (String p : paths) { - if (current.isJsonObject()) { - current = current.getAsJsonObject().get(p); - } else { - return null; - } - - if (current == null) { - return null; - } - } - - return current.isJsonPrimitive() - ? current.getAsString() - : current.toString(); - } catch (Exception e) { - return null; - } - } - - @Override - public String updateNodeValue(String json, String path, Object newValue) { - try { - JsonObject obj = JsonParser.parseString(json).getAsJsonObject(); - String[] paths = path.split("\\."); - JsonObject current = obj; - - // 导航到倒数第二层 - for (int i = 0; i < paths.length - 1; i++) { - String p = paths[i]; - if (!current.has(p) || !current.get(p).isJsonObject()) { - current.add(p, new JsonObject()); - } - current = current.getAsJsonObject(p); - } - - // 设置最后一层的值 - String lastPath = paths[paths.length - 1]; - if (newValue == null) { - current.remove(lastPath); - } else { - JsonElement element = gson.toJsonTree(newValue); - current.add(lastPath, element); - } - - return gson.toJson(obj); - } catch (Exception e) { - return json; - } - } - - @Override - public D convert(T source, Class destinationClass) { - String json = gson.toJson(source); - return gson.fromJson(json, destinationClass); - } - - @Override - public D convert(T source, JsonTypeReference destinationType) { - String json = gson.toJson(source); - return gson.fromJson(json, destinationType.getType()); - } - - @Override - public void addJsonConverter(@NotNull JsonConverter c) { - gson = gson - .newBuilder() - .registerTypeAdapter( - c.getTClass(), - c.getStringConverter().getGsonJsonStringConverterAdapter() - ) - .create(); - gsonUnicode = gsonUnicode - .newBuilder() - .registerTypeAdapter( - c.getTClass(), - c.getStringConverter().getGsonJsonStringConverterAdapter() - ) - .create(); - gsonPretty = gsonPretty - .newBuilder() - .registerTypeAdapter( - c.getTClass(), - c.getStringConverter().getGsonJsonStringConverterAdapter() - ) - .create(); - gsonPrettyUnicode = gsonPrettyUnicode - .newBuilder() - .registerTypeAdapter( - c.getTClass(), - c.getStringConverter().getGsonJsonStringConverterAdapter() - ) - .create(); - } - - @Override - public void addJsonStringConverter(@NotNull JsonStringConverter c) { - addJsonConverter(c); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java b/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java deleted file mode 100644 index 5021b67..0000000 --- a/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile JacksonJsonApi.java - * LastUpdate 2025-09-15 11:16:53 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.mingliqiye.utils.json.converters.JsonConverter; -import com.mingliqiye.utils.json.converters.JsonStringConverter; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * 基于Jackson的JSON处理实现类,提供JSON字符串解析、格式化、合并、节点操作等功能。 - */ -public class JacksonJsonApi implements JsonApi { - - private final ObjectMapper objectMapper; - - /** - * 使用默认的ObjectMapper构造实例 - */ - public JacksonJsonApi() { - this.objectMapper = new ObjectMapper(); - } - - /** - * 使用指定的ObjectMapper构造实例 - * - * @param objectMapper 自定义的ObjectMapper实例 - */ - public JacksonJsonApi(ObjectMapper objectMapper) { - this.objectMapper = objectMapper.copy(); - } - - /** - * 将JSON字符串解析为指定类型的对象 - * - * @param json 待解析的JSON字符串 - * @param clazz 目标对象类型 - * @param 泛型参数,表示目标对象类型 - * @return 解析后的对象 - * @throws JsonException 当解析失败时抛出异常 - */ - @Override - public T parse(String json, Class clazz) { - try { - return objectMapper.readValue(json, clazz); - } catch (IOException e) { - throw new JsonException("Failed to parse JSON string", e); - } - } - - /** - * 将JSON字符串解析为复杂泛型结构的对象(如List、Map等) - * - * @param json JSON字符串 - * @param type 泛型类型引用 - * @param 泛型参数,表示目标对象类型 - * @return 解析后的对象 - * @throws JsonException 当解析失败时抛出异常 - */ - @Override - public T parse(String json, JsonTypeReference type) { - try { - ObjectReader reader = objectMapper.readerFor( - objectMapper.constructType(type.getType()) - ); - return reader.readValue(json); - } catch (IOException e) { - throw new JsonException("Failed to parse JSON string", e); - } - } - - /** - * 将对象格式化为JSON字符串 - * - * @param object 待格式化的对象 - * @return 格式化后的JSON字符串 - * @throws JsonException 当格式化失败时抛出异常 - */ - @Override - public String format(Object object) { - try { - return objectMapper.writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new JsonException( - "Failed to format object to JSON string", - e - ); - } - } - - @Override - public String formatUnicode(Object object) { - try { - return objectMapper - .writer() - .with(JsonGenerator.Feature.ESCAPE_NON_ASCII) - .writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new JsonException(e); - } - } - - /** - * 将对象格式化为美化(带缩进)的JSON字符串 - * - * @param object 待格式化的对象 - * @return 美化后的JSON字符串 - * @throws JsonException 当格式化失败时抛出异常 - */ - @Override - public String formatPretty(Object object) { - try { - return objectMapper - .writerWithDefaultPrettyPrinter() - .writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new JsonException( - "Failed to format object to pretty JSON string", - e - ); - } - } - - @Override - public String formatPrettyUnicode(Object object) { - try { - return objectMapper - .writerWithDefaultPrettyPrinter() - .with(JsonGenerator.Feature.ESCAPE_NON_ASCII) - .writeValueAsString(object); - } catch (JsonProcessingException e) { - throw new JsonException( - "Failed to format object to pretty JSON string", - e - ); - } - } - - /** - * 将JSON字符串解析为指定元素类型的List - * - * @param json JSON字符串 - * @param elementType List中元素的类型 - * @param 泛型参数,表示List中元素的类型 - * @return 解析后的List对象 - */ - @Override - public List parseList(String json, Class elementType) { - return parse(json, JsonTypeUtils.listType(elementType)); - } - - /** - * 将JSON字符串解析为指定键值类型的Map - * - * @param json JSON字符串 - * @param keyType Map中键的类型 - * @param valueType Map中值的类型 - * @param 泛型参数,表示Map中键的类型 - * @param 泛型参数,表示Map中值的类型 - * @return 解析后的Map对象 - */ - @Override - public Map parseMap( - String json, - Class keyType, - Class valueType - ) { - return parse(json, JsonTypeUtils.MapType(keyType, valueType)); - } - - /** - * 判断给定字符串是否是有效的JSON格式 - * - * @param json 待验证的字符串 - * @return 如果是有效JSON返回true,否则返回false - */ - @Override - public boolean isValidJson(String json) { - try { - objectMapper.readTree(json); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 合并多个JSON字符串为一个JSON对象 - * - * @param jsons 多个JSON字符串 - * @return 合并后的JSON字符串 - * @throws JsonException 当合并失败时抛出异常 - */ - @Override - public String merge(String... jsons) { - ObjectNode result = objectMapper.createObjectNode(); - for (String json : jsons) { - try { - JsonNode node = objectMapper.readTree(json); - if (node.isObject()) { - result.setAll((ObjectNode) node); - } - } catch (IOException e) { - // 忽略无效的JSON字符串 - } - } - try { - return objectMapper.writeValueAsString(result); - } catch (JsonProcessingException e) { - throw new JsonException("Failed to merge JSON strings", e); - } - } - - /** - * 获取JSON字符串中指定路径的节点值 - * - * @param json JSON字符串 - * @param path 节点路径,使用"."分隔 - * @return 节点值的文本表示,如果路径不存在则返回null - * @throws JsonException 当获取节点值失败时抛出异常 - */ - @Override - public String getNodeValue(String json, String path) { - try { - JsonNode node = objectMapper.readTree(json); - String[] paths = path.split("\\."); - for (String p : paths) { - node = node.get(p); - if (node == null) { - return null; - } - } - return node.asText(); - } catch (IOException e) { - throw new JsonException("Failed to get node value", e); - } - } - - /** - * 更新JSON字符串中指定路径的节点值 - * - * @param json JSON字符串 - * @param path 节点路径,使用"."分隔 - * @param newValue 新的节点值 - * @return 更新后的JSON字符串 - * @throws JsonException 当更新节点值失败时抛出异常 - */ - @Override - public String updateNodeValue(String json, String path, Object newValue) { - try { - JsonNode node = objectMapper.readTree(json); - if (node instanceof ObjectNode) { - ObjectNode objectNode = (ObjectNode) node; - String[] paths = path.split("\\."); - JsonNode current = objectNode; - - // 导航到目标节点的父节点 - for (int i = 0; i < paths.length - 1; i++) { - current = current.get(paths[i]); - if (current == null || !(current instanceof ObjectNode)) { - return json; // 路径不存在或无效 - } - } - - // 更新值 - if (current instanceof ObjectNode) { - ObjectNode parent = (ObjectNode) current; - if (newValue == null) { - parent.remove(paths[paths.length - 1]); - } else { - parent.set( - paths[paths.length - 1], - objectMapper.valueToTree(newValue) - ); - } - } - - return objectMapper.writeValueAsString(objectNode); - } - return json; - } catch (IOException e) { - throw new JsonException("Failed to update node value", e); - } - } - - /** - * 在不同对象类型之间进行转换 - * - * @param source 源对象 - * @param destinationClass 目标对象类型 - * @param 源对象类型 - * @param 目标对象类型 - * @return 转换后的对象 - */ - @Override - public D convert(T source, Class destinationClass) { - return objectMapper.convertValue(source, destinationClass); - } - - /** - * 在不同泛型对象类型之间进行转换 - * - * @param source 源对象 - * @param destinationType 目标对象的泛型类型引用 - * @param 源对象类型 - * @param 目标对象类型 - * @return 转换后的对象 - */ - @Override - public D convert(T source, JsonTypeReference destinationType) { - return objectMapper.convertValue( - source, - objectMapper.constructType(destinationType.getType()) - ); - } - - @Override - public void addJsonConverter(@NotNull JsonConverter c) { - objectMapper.registerModule(c.getStringConverter().getJacksonJsonStringConverterAdapter().getJacksonModule()); - } - - @Override - public void addJsonStringConverter(@NotNull JsonStringConverter c) { - addJsonConverter(c); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/JsonException.java b/src/main/java/com/mingliqiye/utils/json/JsonException.java deleted file mode 100644 index f53aea3..0000000 --- a/src/main/java/com/mingliqiye/utils/json/JsonException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile JsonException.java - * LastUpdate 2025-09-09 09:25:08 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -public class JsonException extends RuntimeException { - - public JsonException(String message) { - super(message); - } - - public JsonException(String message, Throwable cause) { - super(message, cause); - } - - public JsonException(Throwable cause) { - this(cause.getMessage(), cause); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/JsonTypeReference.java b/src/main/java/com/mingliqiye/utils/json/JsonTypeReference.java deleted file mode 100644 index 2aa1105..0000000 --- a/src/main/java/com/mingliqiye/utils/json/JsonTypeReference.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile JsonTypeReference.java - * LastUpdate 2025-09-09 09:20:05 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Objects; -import lombok.Getter; - -/** - * 通用的 JSON 类型引用类,用于在运行时保留泛型类型信息 - * 适用于所有 JSON 库(Jackson、Gson、Fastjson 等) - * - * @param 引用的泛型类型 - */ -@Getter -public abstract class JsonTypeReference - implements Comparable> { - - protected final Type type; - - /** - * 构造函数,通过反射获取泛型类型信息 - * 仅供内部匿名子类使用 - */ - protected JsonTypeReference() { - Type superClass = getClass().getGenericSuperclass(); - - // 检查是否为匿名子类,防止直接实例化导致无法获取泛型信息 - if (superClass instanceof Class) { - throw new IllegalArgumentException( - "必须使用匿名子类方式创建 JsonTypeReference," + - "例如: new JsonTypeReference>() {}" - ); - } - - this.type = - ((ParameterizedType) superClass).getActualTypeArguments()[0]; - } - - /** - * 构造函数,直接指定类型 - * @param type 具体的类型信息 - */ - protected JsonTypeReference(Type type) { - this.type = Objects.requireNonNull(type, "Type cannot be null"); - } - - /** - * 创建类型引用实例 - * @param 目标类型 - * @return 类型引用实例 - */ - public static JsonTypeReference of() { - return new JsonTypeReference() {}; - } - - /** - * 根据 Class 创建类型引用 - * @param clazz 目标类 - * @param 目标类型 - * @return 类型引用实例 - */ - public static JsonTypeReference of(Class clazz) { - return new JsonTypeReference(clazz) {}; - } - - /** - * 根据 Type 创建类型引用 - * @param type 目标类型 - * @param 目标类型 - * @return 类型引用实例 - */ - public static JsonTypeReference of(Type type) { - return new JsonTypeReference(type) {}; - } - - /** - * 获取原始类型(去掉泛型参数的类型) - * @return 原始类型 Class - */ - @SuppressWarnings("unchecked") - public Class getRawType() { - Type rawType = type; - - // 如果是参数化类型,则提取原始类型部分 - if (type instanceof ParameterizedType) { - rawType = ((ParameterizedType) type).getRawType(); - } - - if (rawType instanceof Class) { - return (Class) rawType; - } - - throw new IllegalStateException("无法获取原始类型: " + type); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - JsonTypeReference that = (JsonTypeReference) o; - - // 对于 ParameterizedType,需要更完整的比较 - if ( - this.type instanceof ParameterizedType && - that.type instanceof ParameterizedType - ) { - ParameterizedType thisParamType = (ParameterizedType) this.type; - ParameterizedType thatParamType = (ParameterizedType) that.type; - - return ( - Objects.equals( - thisParamType.getRawType(), - thatParamType.getRawType() - ) && - Arrays.equals( - thisParamType.getActualTypeArguments(), - thatParamType.getActualTypeArguments() - ) && - Objects.equals( - thisParamType.getOwnerType(), - thatParamType.getOwnerType() - ) - ); - } - - return Objects.equals(type, that.type); - } - - @Override - public int hashCode() { - // 针对 ParameterizedType 进行完整哈希计算 - if (type instanceof ParameterizedType) { - ParameterizedType paramType = (ParameterizedType) type; - return Objects.hash( - paramType.getRawType(), - Arrays.hashCode(paramType.getActualTypeArguments()), - paramType.getOwnerType() - ); - } - return Objects.hash(type); - } - - @Override - public String toString() { - return "JsonTypeReference{" + type + '}'; - } - - @Override - public int compareTo(JsonTypeReference o) { - return this.type.toString().compareTo(o.type.toString()); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/JsonTypeUtils.java b/src/main/java/com/mingliqiye/utils/json/JsonTypeUtils.java deleted file mode 100644 index 4f94f77..0000000 --- a/src/main/java/com/mingliqiye/utils/json/JsonTypeUtils.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile JsonTypeUtils.java - * LastUpdate 2025-09-09 09:18:08 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * JSON 类型工具类,提供类型相关的工具方法 - */ -public class JsonTypeUtils { - - private JsonTypeUtils() { - // 工具类,防止实例化 - } - - /** - * 检查给定的类型是否是指定类或其子类/实现类。 - * - * @param type 要检查的类型 - * @param expectedClass 期望匹配的类 - * @return 如果类型匹配则返回 true,否则返回 false - */ - public static boolean isTypeOf(Type type, Class expectedClass) { - if (type instanceof Class) { - return expectedClass.isAssignableFrom((Class) type); - } else if (type instanceof ParameterizedType) { - return isTypeOf( - ((ParameterizedType) type).getRawType(), - expectedClass - ); - } - return false; - } - - /** - * 获取泛型类型的参数类型。 - * - * @param type 泛型类型 - * @param index 参数索引(从0开始) - * @return 指定位置的泛型参数类型 - * @throws IllegalArgumentException 当无法获取指定索引的泛型参数时抛出异常 - */ - public static Type getGenericParameter(Type type, int index) { - if (type instanceof ParameterizedType) { - Type[] typeArgs = - ((ParameterizedType) type).getActualTypeArguments(); - if (index >= 0 && index < typeArgs.length) { - return typeArgs[index]; - } - } - throw new IllegalArgumentException( - "无法获取泛型参数: " + type + " at index " + index - ); - } - - /** - * 获取类型名称,支持普通类和泛型类型。 - * - * @param type 类型对象 - * @return 类型名称字符串 - */ - public static String getTypeName(Type type) { - if (type instanceof Class) { - return ((Class) type).getSimpleName(); - } else if (type instanceof ParameterizedType) { - ParameterizedType pType = (ParameterizedType) type; - Class rawType = (Class) pType.getRawType(); - Type[] typeArgs = pType.getActualTypeArguments(); - - StringBuilder sb = new StringBuilder(rawType.getSimpleName()); - sb.append("<"); - for (int i = 0; i < typeArgs.length; i++) { - if (i > 0) sb.append(", "); - sb.append(getTypeName(typeArgs[i])); - } - sb.append(">"); - return sb.toString(); - } - return type.getTypeName(); - } - - /** - * 创建一个表示数组类型的引用对象。 - * - * @param componentType 数组元素的类型 - * @param 元素类型 - * @return 表示数组类型的 JsonTypeReference 对象 - */ - public static JsonTypeReference arrayType(Class componentType) { - return new JsonTypeReference() { - private final Type arrayType = java.lang.reflect.Array.newInstance( - componentType, - 0 - ).getClass(); - - @Override - public Type getType() { - return new ParameterizedType() { - private final Type[] actualTypeArguments = new Type[] { - componentType, - }; - - @Override - public Type[] getActualTypeArguments() { - return actualTypeArguments; - } - - @Override - public Type getRawType() { - return arrayType; - } - - @Override - public Type getOwnerType() { - return null; - } - }; - } - }; - } - - /** - * 创建一个表示 List 类型的引用对象。 - * - * @param componentType List 中元素的类型 - * @param 元素类型 - * @return 表示 List 类型的 JsonTypeReference 对象 - * @throws IllegalArgumentException 如果 componentType 为 null,则抛出异常 - */ - public static JsonTypeReference> listType( - Class componentType - ) { - if (componentType == null) { - throw new IllegalArgumentException("componentType cannot be null"); - } - - return new JsonTypeReference>() { - @Override - public Type getType() { - return new ParameterizedType() { - @Override - public Type[] getActualTypeArguments() { - return new Type[] { componentType }; - } - - @Override - public Type getRawType() { - return List.class; - } - - @Override - public Type getOwnerType() { - return null; - } - }; - } - }; - } - - /** - * 创建一个表示 Map 类型的引用对象。 - * - * @param keyType Map 键的类型 - * @param valueType Map 值的类型 - * @param 键类型 - * @param 值类型 - * @return 表示 Map 类型的 JsonTypeReference 对象 - * @throws IllegalArgumentException 如果 keyType 或 valueType 为 null,则抛出异常 - */ - public static JsonTypeReference> MapType( - Class keyType, - Class valueType - ) { - if (keyType == null) { - throw new IllegalArgumentException("keyType cannot be null"); - } - if (valueType == null) { - throw new IllegalArgumentException("valueType cannot be null"); - } - - return new JsonTypeReference>() { - @Override - public Type getType() { - return new ParameterizedType() { - @Override - public Type[] getActualTypeArguments() { - return new Type[] { keyType, valueType }; - } - - @Override - public Type getRawType() { - return Map.class; - } - - @Override - public Type getOwnerType() { - return null; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof ParameterizedType)) return false; - - ParameterizedType that = (ParameterizedType) obj; - return ( - Objects.equals(getRawType(), that.getRawType()) && - Arrays.equals( - getActualTypeArguments(), - that.getActualTypeArguments() - ) && - Objects.equals(getOwnerType(), that.getOwnerType()) - ); - } - - @Override - public int hashCode() { - return ( - Arrays.hashCode(getActualTypeArguments()) ^ - Objects.hashCode(getRawType()) ^ - Objects.hashCode(getOwnerType()) - ); - } - }; - } - }; - } -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/Description.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/Description.java deleted file mode 100644 index 43da8d5..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/Description.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Description.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import lombok.Data; - -@Data -public class Description { - - private String text; - private Extra[] extra; -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/Extra.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/Extra.java deleted file mode 100644 index a092765..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/Extra.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Extra.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import lombok.Data; - -@Data -public class Extra { - - private String text; - private String color; - private Boolean bold; - private Boolean italic; -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/MinecraftServerStatus.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/MinecraftServerStatus.java deleted file mode 100644 index 91fbabd..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/MinecraftServerStatus.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile MinecraftServerStatus.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import lombok.Data; - -@Data -public class MinecraftServerStatus { - - private Description description; - private Players players; - private Version version; - private String favicon; - private boolean enforcesSecureChat; - private boolean previewsChat; - private String jsonData; -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/Players.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/Players.java deleted file mode 100644 index ae1ce45..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/Players.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Players.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import lombok.Data; - -@Data -public class Players { - - private int max; - private int online; - private PlayerSample[] sample; -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/SLP.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/SLP.java deleted file mode 100644 index 64e0adf..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/SLP.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile SLP.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.mingliqiye.utils.network.NetworkEndpoint; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * Minecraft 服务器列表协议(Server List Ping, SLP)工具类。 - * 提供了与 Minecraft 服务器通信以获取其状态信息的功能。 - */ -public class SLP { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - /** - * 将 int32 值截断为无符号 short(2 字节)并按大端序写入字节数组。 - * - * @param value 需要转换的整数(int32) - * @return 包含两个字节的数组,表示无符号 short - */ - public static byte[] toUnsignedShort(int value) { - byte[] array = new byte[2]; - ByteBuffer.wrap(array, 0, 2) - .order(ByteOrder.BIG_ENDIAN) - .putShort((short) (value & 0xFFFF)); - return array; - } - - /** - * 构造 Minecraft 握手包数据。 - * 握手包用于初始化客户端与服务器之间的连接。 - * - * @param serverIP 服务器 IP 地址或域名 - * @param serverPort 服务器端口号 - * @param type 连接类型(通常为 1 表示获取状态) - * @return 握手包的完整字节数组 - * @throws IOException 如果构造过程中发生 IO 错误 - */ - public static byte[] getHandshakePack( - String serverIP, - int serverPort, - int type - ) throws IOException { - ByteArrayOutputStream pack = new ByteArrayOutputStream(); - ByteArrayOutputStream byteArrayOutputStream = - new ByteArrayOutputStream(); - pack.write(0x00); // 握手包标识符 - pack.write(toVarInt(1156)); // 协议版本号(示例值) - byte[] sip = serverIP.getBytes(); - pack.write(toVarInt(sip.length)); // 服务器地址长度 - pack.write(sip); // 服务器地址 - pack.write(toUnsignedShort(serverPort)); // 服务器端口 - pack.write(toVarInt(type)); // 下一阶段类型(1 表示状态请求) - byteArrayOutputStream.write(toVarInt(pack.size())); // 包长度前缀 - byteArrayOutputStream.write(pack.toByteArray()); - - return byteArrayOutputStream.toByteArray(); - } - - /** - * 获取状态请求包的固定字节表示。 - * 此包用于向服务器请求当前状态信息。 - * - * @return 状态请求包的字节数组 - */ - public static byte[] getStatusPack() { - return new byte[] { 0x01, 0x00 }; - } - - /** - * 从输入流中读取服务器返回的状态 JSON 数据,并解析为 MinecraftServerStatus 实体对象。 - * - * @param inputStream 输入流,包含服务器响应的数据 - * @return 解析后的 MinecraftServerStatus 对象 - * @throws IOException 如果读取过程中发生 IO 错误 - */ - public static MinecraftServerStatus getStatusJsonEntity( - DataInputStream inputStream - ) throws IOException { - readVarInt(inputStream); // 忽略第一个 VarInt(包长度) - inputStream.readByte(); // 忽略包标识符 - int lengthjson = readVarInt(inputStream); // 读取 JSON 数据长度 - byte[] data = new byte[lengthjson]; - inputStream.readFully(data); // 读取完整的 JSON 数据 - MinecraftServerStatus serverStatus = objectMapper.readValue( - data, - MinecraftServerStatus.class - ); - serverStatus.setJsonData(new String(data)); // 设置原始 JSON 字符串 - return serverStatus; - } - - /** - * 从输入流中读取一个 VarInt 类型的整数(最多 5 个字节)。 - * - * @param in 输入流 - * @return 解码后的整数值 - * @throws IOException 如果读取过程中发生 IO 错误 - */ - public static int readVarInt(DataInputStream in) throws IOException { - int value = 0; - int length = 0; - byte currentByte; - do { - currentByte = in.readByte(); - value |= (currentByte & 0x7F) << (length * 7); - length += 1; - if (length > 5) { - throw new RuntimeException("VarInt too long"); - } - } while ((currentByte & 0x80) != 0); - return value; - } - - /** - * 将一个 int32 整数编码为 VarInt 格式的字节数组(1 到 5 个字节)。 - * - * @param value 需要编码的整数 - * @return 编码后的 VarInt 字节数组 - */ - public static byte[] toVarInt(int value) { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - while (true) { - if ((value & 0xFFFFFF80) == 0) { - buffer.write(value); // 最后一个字节 - break; - } - buffer.write((value & 0x7F) | 0x80); // 写入带继续位的字节 - value >>>= 7; // 右移 7 位继续处理 - } - return buffer.toByteArray(); - } - - /** - * 创建一个新的 Socket 连接到指定的网络端点,并设置超时时间。 - * - * @param networkEndpoint 目标网络端点(包括主机和端口) - * @return 已连接的 Socket 实例 - * @throws IOException 如果连接失败或发生 IO 错误 - */ - public static Socket getNewConnect(NetworkEndpoint networkEndpoint) - throws IOException { - Socket socket = new Socket(); - socket.setSoTimeout(5000); // 设置读取超时时间为 5 秒 - socket.connect(networkEndpoint.toInetSocketAddress()); // 执行连接操作 - return socket; - } - - /** - * 使用 "host:port" 格式的字符串连接到 Minecraft 服务器并获取其状态信息。 - * - * @param s 域名或 IP 地址加端口号组成的字符串,例如 "127.0.0.1:25565" - * @return 服务器状态实体对象 - * @throws IOException 如果连接失败或发生 IO 错误 - */ - public static MinecraftServerStatus getServerStatus(String s) - throws IOException { - return getServerStatus(NetworkEndpoint.of(s)); - } - - /** - * 使用指定的主机名和端口号连接到 Minecraft 服务器并获取其状态信息。 - * - * @param s 主机名或 IP 地址 - * @param i 端口号 - * @return 服务器状态实体对象 - * @throws IOException 如果连接失败或发生 IO 错误 - */ - public static MinecraftServerStatus getServerStatus(String s, Integer i) - throws IOException { - return getServerStatus(NetworkEndpoint.of(s, i)); - } - - /** - * 使用 NetworkEndpoint 实例连接到 Minecraft 服务器并获取其状态信息。 - * - * @param e 网络端点实例,包含主机和端口信息 - * @return 服务器状态实体对象 - * @throws IOException 如果连接失败或发生 IO 错误 - * @see NetworkEndpoint - */ - public static MinecraftServerStatus getServerStatus(NetworkEndpoint e) - throws IOException { - Socket socket = getNewConnect(e); // 建立 TCP 连接 - OutputStream out = socket.getOutputStream(); // 获取输出流发送数据 - DataInputStream in = new DataInputStream(socket.getInputStream()); // 获取输入流接收数据 - out.write(getHandshakePack(e.getHost(), e.getPort(), 1)); // 发送握手包 - out.write(getStatusPack()); // 发送状态请求包 - return getStatusJsonEntity(in); // 读取并解析服务器响应 - } -} diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/Version.java b/src/main/java/com/mingliqiye/utils/minecraft/slp/Version.java deleted file mode 100644 index ec3ec1a..0000000 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/Version.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Version.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.minecraft.slp; - -import lombok.Data; - -@Data -public class Version { - - private String name; - private int protocol; -} diff --git a/src/main/java/com/mingliqiye/utils/network/NetworkAddress.java b/src/main/java/com/mingliqiye/utils/network/NetworkAddress.java deleted file mode 100644 index 7531b64..0000000 --- a/src/main/java/com/mingliqiye/utils/network/NetworkAddress.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile NetworkAddress.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.network; - -import com.mingliqiye.utils.string.StringUtils; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; - -import java.io.Serializable; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.regex.Pattern; - -/** - * 网络地址类,用于表示一个网络地址(IP或域名),并提供相关操作。 - * 支持IPv4和IPv6地址的解析与验证。 - * - * @author MingLiPro - */ -public class NetworkAddress implements Serializable { - - /** - * IPv6标识 - */ - public static int IPV6 = 6; - - /** - * IPv4标识 - */ - public static int IPV4 = 4; - - /** - * IPv4地址正则表达式 - */ - static String IPV4REG = - "^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2" + - "(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$"; - - /** - * 编译后的IPv4地址匹配模式 - */ - private static final Pattern IPV4_PATTERN = Pattern.compile(IPV4REG); - - /** - * IPv6地址正则表达式 - */ - static String IPV6REG = - "^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|" + - "^(::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4})$" + - "|" + - "^(::)$|" + - "^([0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4})$|" + - "^(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})$|" + - "^(([0-9a-fA-F]{1,4}:){6}(([0-9]{1,3}\\.){3}[0-9]{1,3}))$|" + - "^::([fF]{4}:)?(([0-9]{1,3}\\.){3}[0-9]{1,3})$"; - - /** - * 编译后的IPv6地址匹配模式 - */ - private static final Pattern IPV6_PATTERN = Pattern.compile(IPV6REG); - - /** - * IP地址类型:4 表示 IPv4,6 表示 IPv6 - */ - @Getter - private int IPv; - - /** - * IP地址字符串 - */ - @Getter - private String ip; - - /** - * 域名(如果输入的是域名) - */ - private String domain; - - /** - * 标识是否是域名解析来的IP - */ - private boolean isdom; - - /** - * 构造方法,根据传入的字符串判断是IP地址还是域名,并进行相应处理。 - * - * @param domip 可能是IP地址或域名的字符串 - */ - NetworkAddress(String domip) { - try { - // 尝试将输入识别为IP地址 - IPv = testIp(domip); - ip = domip; - } catch (NetworkException e) { - try { - // 如果不是有效IP,则尝试作为域名解析 - String ips = getHostIp(domip); - IPv = testIp(ips); - ip = ips; - isdom = true; - domain = domip; - } catch (UnknownHostException ex) { - throw new NetworkException(ex); - } - } - } - - /** - * 静态工厂方法,创建 NetworkAddress 实例。 - * - * @param domip 可能是IP地址或域名的字符串 - * @return 新建的 NetworkAddress 实例 - */ - public static NetworkAddress of(String domip) { - return new NetworkAddress(domip); - } - - /** - * 静态工厂方法,通过 InetAddress 创建 NetworkAddress 实例。 - * - * @param inetAddress InetAddress 对象 - * @return 新建的 NetworkAddress 实例 - */ - public static NetworkAddress of(InetAddress inetAddress) { - return new NetworkAddress(inetAddress.getHostAddress()); - } - - /** - * 从DNS服务器解析域名获取对应的IP地址。 - * - * @param domain 域名 - * @return 解析出的第一个IP地址 - * @throws UnknownHostException 如果域名无法解析 - */ - public static String getHostIp(@NotNull String domain) - throws UnknownHostException { - InetAddress[] addresses = InetAddress.getAllByName(domain.trim()); - return addresses[0].getHostAddress(); - } - - /** - * 检测给定字符串是否为有效的IPv4或IPv6地址。 - * - * @param ip 要检测的IP地址字符串 - * @return 4 表示IPv4,6 表示IPv6 - * @throws NetworkException 如果IP格式无效 - */ - public static int testIp(String ip) { - if (ip == null) { - throw new NetworkException("IP地址不能为null"); - } - String trimmedIp = ip.trim(); - - // 判断是否匹配IPv4格式 - if (IPV4_PATTERN.matcher(trimmedIp).matches()) { - return IPV4; - } - - // 判断是否匹配IPv6格式 - if (IPV6_PATTERN.matcher(trimmedIp).matches()) { - return IPV6; - } - - // 不符合任一格式时抛出异常 - throw new NetworkException( - StringUtils.format("[{}] 不是有效的IPv4或IPv6地址", ip) - ); - } - - /** - * 将当前 NetworkAddress 转换为 InetAddress 对象。 - * - * @return InetAddress 对象 - */ - public InetAddress toInetAddress() { - try { - return InetAddress.getByName(ip != null ? ip : domain); - } catch (UnknownHostException e) { - throw new RuntimeException(e); - } - } - - /** - * 返回 NetworkAddress 的字符串表示形式。 - * - * @return 字符串表示 - */ - public String toString() { - return isdom - ? StringUtils.format( - "NetworkAddress(IP='{}',type='{}'," + "domain='{}')", - ip, - IPv, - domain - ) - : StringUtils.format("NetworkAddress(IP='{}',type='{}')", ip, IPv); - } -} diff --git a/src/main/java/com/mingliqiye/utils/network/NetworkEndpoint.java b/src/main/java/com/mingliqiye/utils/network/NetworkEndpoint.java deleted file mode 100644 index ad950c8..0000000 --- a/src/main/java/com/mingliqiye/utils/network/NetworkEndpoint.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile NetworkEndpoint.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.network; - -import com.mingliqiye.utils.string.StringUtils; -import lombok.Getter; - -import java.io.Serializable; -import java.net.InetSocketAddress; - -/** - * IP和端口聚集类,用于封装网络地址与端口信息。 - * 该类提供了与InetSocketAddress之间的相互转换功能。 - * - * @author MingLiPro - * @see InetSocketAddress - */ -public class NetworkEndpoint implements Serializable { - - @Getter - private final NetworkAddress networkAddress; - - @Getter - private final NetworkPort networkPort; - - /** - * 构造函数,使用指定的网络地址和端口创建NetworkEndpoint实例。 - * - * @param networkAddress 网络地址对象 - * @param networkPort 网络端口对象 - * @see NetworkAddress - * @see NetworkPort - */ - private NetworkEndpoint( - NetworkAddress networkAddress, - NetworkPort networkPort - ) { - this.networkAddress = networkAddress; - this.networkPort = networkPort; - } - - /** - * 根据给定的InetSocketAddress对象创建NetworkEndpoint实例。 - * - * @param address InetSocketAddress对象 - * @return 新建的NetworkEndpoint实例 - * @see InetSocketAddress - */ - public static NetworkEndpoint of(InetSocketAddress address) { - return new NetworkEndpoint( - new NetworkAddress(address.getHostString()), - new NetworkPort(address.getPort()) - ); - } - - /** - * 根据主机名或IP字符串和端口号创建NetworkEndpoint实例。 - * - * @param s 主机名或IP地址字符串 - * @param i 端口号 - * @return 新建的NetworkEndpoint实例 - */ - public static NetworkEndpoint of(String s, Integer i) { - NetworkAddress networkAddress = new NetworkAddress(s); - NetworkPort networkPort = new NetworkPort(i); - return new NetworkEndpoint(networkAddress, networkPort); - } - - /** - * 根据"host:port"格式的字符串创建NetworkEndpoint实例。 - * 例如:"127.0.0.1:8080" - * - * @param s "host:port"格式的字符串 - * @return 新建的NetworkEndpoint实例 - */ - public static NetworkEndpoint of(String s) { - // 查找最后一个冒号的位置,以支持IPv6地址中的冒号 - int lastColonIndex = s.lastIndexOf(':'); - return of( - s.substring(0, lastColonIndex), - Integer.parseInt(s.substring(lastColonIndex + 1)) - ); - } - - /** - * 将当前NetworkEndpoint转换为InetSocketAddress对象。 - * - * @return 对应的InetSocketAddress对象 - * @see InetSocketAddress - */ - public InetSocketAddress toInetSocketAddress() { - return new InetSocketAddress( - networkAddress.toInetAddress(), - networkPort.getPort() - ); - } - - /** - * 将当前NetworkEndpoint转换为"host:port"格式的字符串。 - * 例如:"127.0.0.1:25563" - * - * @return 格式化后的字符串 - */ - public String toHostPortString() { - return StringUtils.format( - "{}:{}", - networkAddress.getIp(), - networkPort.getPort() - ); - } - - /** - * 返回NetworkEndpoint的详细字符串表示形式。 - * 格式:NetworkEndpoint(IP=...,Port=...,Endpoint=...) - * - * @return 包含详细信息的字符串 - */ - public String toString() { - return StringUtils.format( - "NetworkEndpoint(IP={},Port={},Endpoint={})", - networkAddress.getIp(), - networkPort.getPort(), - toHostPortString() - ); - } - - /** - * 获取主机名或IP地址字符串。 - * - * @return 主机名或IP地址 - */ - public String getHost() { - return networkAddress.getIp(); - } - - /** - * 获取端口号。 - * - * @return 端口号 - */ - public Integer getPort() { - return networkPort.getPort(); - } -} diff --git a/src/main/java/com/mingliqiye/utils/network/NetworkException.java b/src/main/java/com/mingliqiye/utils/network/NetworkException.java deleted file mode 100644 index 4def71c..0000000 --- a/src/main/java/com/mingliqiye/utils/network/NetworkException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile NetworkException.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.network; - -/** - * 网络异常类,用于处理网络相关的运行时异常 - * - * @author MingLiPro - */ -public class NetworkException extends RuntimeException { - - /** - * 构造一个带有指定详细消息的网络异常 - * - * @param message 异常的详细消息 - */ - public NetworkException(String message) { - super(message); - } - - /** - * 构造一个网络异常,指定原因异常 - * - * @param e 导致此异常的原因异常 - */ - public NetworkException(Exception e) { - super(e); - } -} diff --git a/src/main/java/com/mingliqiye/utils/network/NetworkPort.java b/src/main/java/com/mingliqiye/utils/network/NetworkPort.java deleted file mode 100644 index 2e28641..0000000 --- a/src/main/java/com/mingliqiye/utils/network/NetworkPort.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile NetworkPort.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.network; - -import com.mingliqiye.utils.string.StringUtils; -import lombok.Getter; - -import java.io.Serializable; - -/** - * 网络端口类 - * - * @author MingLiPro - */ -public class NetworkPort implements Serializable { - - @Getter - private final int port; - - /** - * 构造函数,创建一个网络端口对象 - * - * @param port 端口号,必须在0-65535范围内 - */ - public NetworkPort(int port) { - testPort(port); - this.port = port; - } - - /** - * 验证端口号是否合法 - * - * @param port 待验证的端口号 - * @throws NetworkException 当端口号不在合法范围(0-65535)内时抛出异常 - */ - public static void testPort(int port) { - // 验证端口号范围是否在0-65535之间 - if (!(0 <= port && 65535 >= port)) { - throw new NetworkException( - StringUtils.format("{} 不是正确的端口号", port) - ); - } - } -} diff --git a/src/main/kotlin/com/mingliqiye/utils/Main.kt b/src/main/kotlin/com/mingliqiye/utils/Main.kt index 80ceff0..2f4c274 100644 --- a/src/main/kotlin/com/mingliqiye/utils/Main.kt +++ b/src/main/kotlin/com/mingliqiye/utils/Main.kt @@ -16,17 +16,16 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Main.kt - * LastUpdate 2025-09-15 18:02:00 + * LastUpdate 2025-09-15 22:31:33 * UpdateUser MingLiPro */ +@file:JvmName("Main") + package com.mingliqiye.utils import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration -import com.mingliqiye.utils.uuid.UUID + fun main() { AutoConfiguration.printBanner() - - println(UUID.of("b5c4579e-921a-11f0-ad12-d7949d0c61b8").equals(UUID.of("b5c4579e-921a-11f0-ad12-d7949d0c61b8"))) - println(UUID.getV1()) } diff --git a/src/main/kotlin/com/mingliqiye/utils/aes/AesUtils.kt b/src/main/kotlin/com/mingliqiye/utils/aes/AesUtils.kt index 0969991..56762ed 100644 --- a/src/main/kotlin/com/mingliqiye/utils/aes/AesUtils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/aes/AesUtils.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile AesUtils.kt - * LastUpdate 2025-09-14 18:43:04 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/kotlin/com/mingliqiye/utils/base64/Base64Utils.kt b/src/main/kotlin/com/mingliqiye/utils/base64/Base64Utils.kt index 0c1ff37..980492a 100644 --- a/src/main/kotlin/com/mingliqiye/utils/base64/Base64Utils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/base64/Base64Utils.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Base64Utils.kt - * LastUpdate 2025-09-14 18:44:22 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @file:JvmName("Base64Utils") diff --git a/src/main/kotlin/com/mingliqiye/utils/bean/Factory.kt b/src/main/kotlin/com/mingliqiye/utils/bean/Factory.kt index d8b63e1..44c8730 100644 --- a/src/main/kotlin/com/mingliqiye/utils/bean/Factory.kt +++ b/src/main/kotlin/com/mingliqiye/utils/bean/Factory.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Factory.kt - * LastUpdate 2025-09-14 19:09:28 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @file:JvmName("Factory") diff --git a/src/main/kotlin/com/mingliqiye/utils/bean/annotation/ComponentBean.kt b/src/main/kotlin/com/mingliqiye/utils/bean/annotation/ComponentBean.kt index e9b6d86..a99b7e4 100644 --- a/src/main/kotlin/com/mingliqiye/utils/bean/annotation/ComponentBean.kt +++ b/src/main/kotlin/com/mingliqiye/utils/bean/annotation/ComponentBean.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile ComponentBean.kt - * LastUpdate 2025-09-14 18:48:59 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/kotlin/com/mingliqiye/utils/bean/springboot/SpringBeanUtils.kt b/src/main/kotlin/com/mingliqiye/utils/bean/springboot/SpringBeanUtils.kt index 6cbc38f..96f1a46 100644 --- a/src/main/kotlin/com/mingliqiye/utils/bean/springboot/SpringBeanUtils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/bean/springboot/SpringBeanUtils.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile SpringBeanUtils.kt - * LastUpdate 2025-09-14 22:10:45 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/kotlin/com/mingliqiye/utils/jna/FieldStructure.kt b/src/main/kotlin/com/mingliqiye/utils/jna/FieldStructure.kt index 0a5b2bc..c14c23f 100644 --- a/src/main/kotlin/com/mingliqiye/utils/jna/FieldStructure.kt +++ b/src/main/kotlin/com/mingliqiye/utils/jna/FieldStructure.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile FieldStructure.kt - * LastUpdate 2025-09-14 18:19:29 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/kotlin/com/mingliqiye/utils/json/GsonJsonApi.kt b/src/main/kotlin/com/mingliqiye/utils/json/GsonJsonApi.kt new file mode 100644 index 0000000..934fb76 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/GsonJsonApi.kt @@ -0,0 +1,231 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile GsonJsonApi.kt + * LastUpdate 2025-09-15 22:07:43 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.json + +import com.google.gson.* +import com.mingliqiye.utils.json.converters.JsonConverter +import com.mingliqiye.utils.json.converters.JsonStringConverter + +class GsonJsonApi : JsonApi { + + private var gsonUnicode: Gson + private var gsonPretty: Gson + private var gsonPrettyUnicode: Gson + private var gson: Gson + + constructor() { + gson = GsonBuilder() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + + gsonUnicode = GsonBuilder() + .disableHtmlEscaping() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + + gsonPretty = GsonBuilder() + .setPrettyPrinting() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + + gsonPrettyUnicode = GsonBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + } + + constructor(gson: Gson) { + this.gson = gson + .newBuilder() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + this.gsonUnicode = gson + .newBuilder() + .disableHtmlEscaping() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + this.gsonPretty = gson + .newBuilder() + .setPrettyPrinting() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + this.gsonPrettyUnicode = gson + .newBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) + .create() + } + + override fun parse(json: String, clazz: Class): T { + return gson.fromJson(json, clazz) + } + + override fun parse(json: String, type: JsonTypeReference): T { + return gson.fromJson(json, type.type) + } + + override fun format(obj: Any): String { + return gson.toJson(obj) + } + + override fun formatUnicode(obj: Any): String { + return gsonUnicode.toJson(obj) + } + + override fun formatPretty(obj: Any): String { + return gsonPretty.toJson(obj) + } + + override fun formatPrettyUnicode(obj: Any): String { + return gsonPrettyUnicode.toJson(obj) + } + + override fun isValidJson(json: String): Boolean { + return try { + JsonParser.parseString(json) + true + } catch (e: JsonSyntaxException) { + false + } catch (e: Exception) { + false + } + } + + override fun merge(vararg jsons: String): String { + val merged = JsonObject() + for (json in jsons) { + if (json.isNullOrEmpty()) { + continue + } + try { + val obj = JsonParser.parseString(json).asJsonObject + for (key in obj.keySet()) { + merged.add(key, obj.get(key)) + } + } catch (e: Exception) { + // 忽略无效的 JSON 字符串 + } + } + return gson.toJson(merged) + } + + override fun getNodeValue(json: String, path: String): String? { + return try { + var element = JsonParser.parseString(json) + val paths = path.split("\\.".toRegex()).toTypedArray() + var current = element + + for (p in paths) { + if (current.isJsonObject) { + current = current.asJsonObject.get(p) + } else { + return null + } + + if (current == null) { + return null + } + } + + if (current.isJsonPrimitive) current.asString else current.toString() + } catch (e: Exception) { + null + } + } + + override fun updateNodeValue(json: String, path: String, newValue: Any): String { + return try { + val obj = JsonParser.parseString(json).asJsonObject + val paths = path.split("\\.".toRegex()).toTypedArray() + var current = obj + + // 导航到倒数第二层 + for (i in 0 until paths.size - 1) { + val p = paths[i] + if (!current.has(p) || !current.get(p).isJsonObject) { + current.add(p, JsonObject()) + } + current = current.getAsJsonObject(p) + } + + // 设置最后一层的值 + val lastPath = paths[paths.size - 1] + val element = gson.toJsonTree(newValue) + current.add(lastPath, element) + + gson.toJson(obj) + } catch (e: Exception) { + json + } + } + + override fun convert(source: T, destinationClass: Class): D { + val json = gson.toJson(source) + return gson.fromJson(json, destinationClass) + } + + override fun convert(source: T, destinationType: JsonTypeReference): D { + val json = gson.toJson(source) + return gson.fromJson(json, destinationType.type) + } + + override fun addJsonConverter(c: JsonConverter<*, *>) { + c.getStringConverter()?.let { + gson = gson + .newBuilder() + .registerTypeAdapter( + it.tClass, + it.gsonJsonStringConverterAdapter + ) + .create() + gsonUnicode = gsonUnicode + .newBuilder() + .registerTypeAdapter( + it.tClass, + it.gsonJsonStringConverterAdapter + ) + .create() + gsonPretty = gsonPretty + .newBuilder() + .registerTypeAdapter( + it.tClass, + it.gsonJsonStringConverterAdapter + ) + .create() + gsonPrettyUnicode = gsonPrettyUnicode + .newBuilder() + .registerTypeAdapter( + it.tClass, + it.gsonJsonStringConverterAdapter + ) + .create() + } + + } + + override fun addJsonStringConverter(c: JsonStringConverter<*>) { + addJsonConverter(c) + } +} diff --git a/src/main/kotlin/com/mingliqiye/utils/json/JacksonJsonApi.kt b/src/main/kotlin/com/mingliqiye/utils/json/JacksonJsonApi.kt new file mode 100644 index 0000000..1e9dfb6 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/JacksonJsonApi.kt @@ -0,0 +1,301 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile JacksonJsonApi.kt + * LastUpdate 2025-09-15 22:07:43 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.json + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.ObjectReader +import com.fasterxml.jackson.databind.node.ObjectNode +import com.mingliqiye.utils.json.converters.JsonConverter +import com.mingliqiye.utils.json.converters.JsonStringConverter +import java.io.IOException + +/** + * 基于Jackson的JSON处理实现类,提供JSON字符串解析、格式化、合并、节点操作等功能。 + */ +class JacksonJsonApi : JsonApi { + + private val objectMapper: ObjectMapper + + /** + * 使用默认的ObjectMapper构造实例 + */ + constructor() { + this.objectMapper = ObjectMapper() + } + + /** + * 使用指定的ObjectMapper构造实例 + * + * @param objectMapper 自定义的ObjectMapper实例 + */ + constructor(objectMapper: ObjectMapper) { + this.objectMapper = objectMapper.copy() + } + + /** + * 将JSON字符串解析为指定类型的对象 + * + * @param json 待解析的JSON字符串 + * @param clazz 目标对象类型 + * @param 泛型参数,表示目标对象类型 + * @return 解析后的对象 + * @throws JsonException 当解析失败时抛出异常 + */ + override fun parse(json: String, clazz: Class): T { + return try { + objectMapper.readValue(json, clazz) + } catch (e: IOException) { + throw JsonException("Failed to parse JSON string", e) + } + } + + /** + * 将JSON字符串解析为复杂泛型结构的对象(如List、Map等) + * + * @param json JSON字符串 + * @param type 泛型类型引用 + * @param 泛型参数,表示目标对象类型 + * @return 解析后的对象 + * @throws JsonException 当解析失败时抛出异常 + */ + override fun parse(json: String, type: JsonTypeReference): T { + return try { + val reader: ObjectReader = objectMapper.readerFor( + objectMapper.constructType(type.type) + ) + reader.readValue(json) + } catch (e: IOException) { + throw JsonException("Failed to parse JSON string", e) + } + } + + /** + * 将对象格式化为JSON字符串 + * + * @param `object` 待格式化的对象 + * @return 格式化后的JSON字符串 + * @throws JsonException 当格式化失败时抛出异常 + */ + override fun format(obj: Any): String { + return try { + objectMapper.writeValueAsString(obj) + } catch (e: JsonProcessingException) { + throw JsonException( + "Failed to format object to JSON string", + e + ) + } + } + + override fun formatUnicode(obj: Any): String { + return try { + objectMapper + .writer() + .with(JsonGenerator.Feature.ESCAPE_NON_ASCII) + .writeValueAsString(obj) + } catch (e: JsonProcessingException) { + throw JsonException(e) + } + } + + /** + * 将对象格式化为美化(带缩进)的JSON字符串 + * + * @param `object` 待格式化的对象 + * @return 美化后的JSON字符串 + * @throws JsonException 当格式化失败时抛出异常 + */ + override fun formatPretty(obj: Any): String { + return try { + objectMapper + .writerWithDefaultPrettyPrinter() + .writeValueAsString(obj) + } catch (e: JsonProcessingException) { + throw JsonException( + "Failed to format object to pretty JSON string", + e + ) + } + } + + override fun formatPrettyUnicode(obj: Any): String { + return try { + objectMapper + .writerWithDefaultPrettyPrinter() + .with(JsonGenerator.Feature.ESCAPE_NON_ASCII) + .writeValueAsString(obj) + } catch (e: JsonProcessingException) { + throw JsonException( + "Failed to format object to pretty JSON string", + e + ) + } + } + + + /** + * 判断给定字符串是否是有效的JSON格式 + * + * @param json 待验证的字符串 + * @return 如果是有效JSON返回true,否则返回false + */ + override fun isValidJson(json: String): Boolean { + return try { + objectMapper.readTree(json) + true + } catch (e: Exception) { + false + } + } + + /** + * 合并多个JSON字符串为一个JSON对象 + * + * @param jsons 多个JSON字符串 + * @return 合并后的JSON字符串 + * @throws JsonException 当合并失败时抛出异常 + */ + override fun merge(vararg jsons: String): String { + val result: ObjectNode = objectMapper.createObjectNode() + for (json in jsons) { + try { + val node: JsonNode = objectMapper.readTree(json) + if (node.isObject) { + result.setAll(node as ObjectNode) + } + } catch (e: IOException) { + // 忽略无效的JSON字符串 + } + } + return try { + objectMapper.writeValueAsString(result) + } catch (e: JsonProcessingException) { + throw JsonException("Failed to merge JSON strings", e) + } + } + + /** + * 获取JSON字符串中指定路径的节点值 + * + * @param json JSON字符串 + * @param path 节点路径,使用"."分隔 + * @return 节点值的文本表示,如果路径不存在则返回null + * @throws JsonException 当获取节点值失败时抛出异常 + */ + override fun getNodeValue(json: String, path: String): String? { + return try { + var node: JsonNode = objectMapper.readTree(json) + val paths: Array = path.split("\\.".toRegex()).toTypedArray() + for (p in paths) { + node = node.get(p) + } + node.asText() + } catch (e: IOException) { + throw JsonException("Failed to get node value", e) + } + } + + /** + * 更新JSON字符串中指定路径的节点值 + * + * @param json JSON字符串 + * @param path 节点路径,使用"."分隔 + * @param newValue 新的节点值 + * @return 更新后的JSON字符串 + * @throws JsonException 当更新节点值失败时抛出异常 + */ + override fun updateNodeValue(json: String, path: String, newValue: Any): String { + return try { + val node: JsonNode = objectMapper.readTree(json) + if (node is ObjectNode) { + val objectNode: ObjectNode = node + val paths: Array = path.split("\\.".toRegex()).toTypedArray() + var current: JsonNode = objectNode + + // 导航到目标节点的父节点 + for (i in 0 until paths.size - 1) { + current = current.get(paths[i]) + if (current !is ObjectNode) { + return json // 路径不存在或无效 + } + } + + // 更新值 + if (current is ObjectNode) { + val parent: ObjectNode = current + parent.set( + paths[paths.size - 1], + objectMapper.valueToTree(newValue) + ) + } + + objectMapper.writeValueAsString(objectNode) + } + json + } catch (e: IOException) { + throw JsonException("Failed to update node value", e) + } + } + + /** + * 在不同对象类型之间进行转换 + * + * @param source 源对象 + * @param destinationClass 目标对象类型 + * @param 源对象类型 + * @param 目标对象类型 + * @return 转换后的对象 + */ + override fun convert(source: T, destinationClass: Class): D { + return objectMapper.convertValue(source, destinationClass) + } + + /** + * 在不同泛型对象类型之间进行转换 + * + * @param source 源对象 + * @param destinationType 目标对象的泛型类型引用 + * @param 源对象类型 + * @param 目标对象类型 + * @return 转换后的对象 + */ + override fun convert(source: T, destinationType: JsonTypeReference): D { + return objectMapper.convertValue( + source, + objectMapper.constructType(destinationType.type) + ) + } + + override fun addJsonConverter(c: JsonConverter<*, *>) { + c.getStringConverter()?.let { + objectMapper.registerModule(it.jacksonJsonStringConverterAdapter.jacksonModule) + } + } + + override fun addJsonStringConverter(c: JsonStringConverter<*>) { + addJsonConverter(c) + } +} diff --git a/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt b/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt index bb253eb..0de3c89 100644 --- a/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt +++ b/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile JsonApi.kt - * LastUpdate 2025-09-15 11:10:59 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @@ -306,8 +306,8 @@ interface JsonApi { * @param 泛型参数,表示List中元素的类型 * @return 解析后的List集合 */ - fun parseList(json: String, elementType: Class): MutableList { - return parse>(json, JsonTypeUtils.listType(elementType)) + fun parseList(json: String, elementType: Class): List { + return parse(json, type = listType(elementType)) } /** @@ -372,7 +372,7 @@ interface JsonApi { * @param path 节点路径(如:"user.name") * @return 节点值的字符串表示 */ - fun getNodeValue(json: String, path: String): String + fun getNodeValue(json: String, path: String): String? /** * 更新JSON字符串中指定路径节点的值 diff --git a/src/main/java/com/mingliqiye/utils/minecraft/slp/PlayerSample.java b/src/main/kotlin/com/mingliqiye/utils/json/JsonException.kt similarity index 67% rename from src/main/java/com/mingliqiye/utils/minecraft/slp/PlayerSample.java rename to src/main/kotlin/com/mingliqiye/utils/json/JsonException.kt index 2ab141f..86692d2 100644 --- a/src/main/java/com/mingliqiye/utils/minecraft/slp/PlayerSample.java +++ b/src/main/kotlin/com/mingliqiye/utils/json/JsonException.kt @@ -15,18 +15,18 @@ * * ProjectName mingli-utils * ModuleName mingli-utils.main - * CurrentFile PlayerSample.java - * LastUpdate 2025-09-09 08:37:33 + * CurrentFile JsonException.kt + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ -package com.mingliqiye.utils.minecraft.slp; +package com.mingliqiye.utils.json -import lombok.Data; +class JsonException : RuntimeException { -@Data -public class PlayerSample { + constructor(message: String) : super(message) - private String name; - private String id; + constructor(message: String, cause: Throwable) : super(message, cause) + + constructor(cause: Throwable) : this(cause.message ?: "", cause) } diff --git a/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeReference.kt b/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeReference.kt new file mode 100644 index 0000000..a09739d --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeReference.kt @@ -0,0 +1,164 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile JsonTypeReference.kt + * LastUpdate 2025-09-15 22:32:50 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.json + +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type +import java.util.* + +/** + * 通用的 JSON 类型引用类,用于在运行时保留泛型类型信息 + * 适用于所有 JSON 库(Jackson、Gson、Fastjson 等) + * + * @param 引用的泛型类型 + */ +abstract class JsonTypeReference : Comparable> { + + open var type: Type = Any::class.java + + /** + * 构造函数,通过反射获取泛型类型信息 + * 仅供内部匿名子类使用 + */ + protected constructor() { + val superClass: Type = this.javaClass.genericSuperclass + + // 检查是否为匿名子类,防止直接实例化导致无法获取泛型信息 + if (superClass is Class<*>) { + throw IllegalArgumentException( + "必须使用匿名子类方式创建 JsonTypeReference," + + "例如: new JsonTypeReference>() {}" + ) + } + + this.type = (superClass as ParameterizedType).actualTypeArguments[0] + } + + /** + * 构造函数,直接指定类型 + * @param type 具体的类型信息 + */ + protected constructor(type: Type) { + this.type = Objects.requireNonNull(type, "Type cannot be null") + } + + /** + * 创建类型引用实例 + * @param 目标类型 + * @return 类型引用实例 + */ + companion object { + @JvmStatic + fun of(): JsonTypeReference { + return object : JsonTypeReference() {} + } + + /** + * 根据 Class 创建类型引用 + * @param clazz 目标类 + * @param 目标类型 + * @return 类型引用实例 + */ + @JvmStatic + fun of(clazz: Class): JsonTypeReference { + return object : JsonTypeReference(clazz) {} + } + + /** + * 根据 Type 创建类型引用 + * @param type 目标类型 + * @param 目标类型 + * @return 类型引用实例 + */ + @JvmStatic + fun of(type: Type): JsonTypeReference { + return object : JsonTypeReference(type) {} + } + } + + /** + * 获取原始类型(去掉泛型参数的类型) + * @return 原始类型 Class + */ + @Suppress("UNCHECKED_CAST") + fun getRawType(): Class { + var rawType: Type = type + + // 如果是参数化类型,则提取原始类型部分 + if (type is ParameterizedType) { + rawType = (type as ParameterizedType).rawType + } + + if (rawType is Class<*>) { + return rawType as Class + } + + throw IllegalStateException("无法获取原始类型: $type") + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || this.javaClass != other.javaClass) return false + val that = other as JsonTypeReference<*> + + // 对于 ParameterizedType,需要更完整的比较 + if (this.type is ParameterizedType && that.type is ParameterizedType) { + val thisParamType = this.type as ParameterizedType + val thatParamType = that.type as ParameterizedType + + return ( + Objects.equals( + thisParamType.rawType, + thatParamType.rawType + ) && + thisParamType.actualTypeArguments.contentEquals(thatParamType.actualTypeArguments) && + Objects.equals( + thisParamType.ownerType, + thatParamType.ownerType + ) + ) + } + + return Objects.equals(type, that.type) + } + + override fun hashCode(): Int { + if (type is ParameterizedType) { + val paramType = type as ParameterizedType + return Objects.hash( + paramType.rawType, + paramType.actualTypeArguments.contentHashCode(), + paramType.ownerType + ) + } + return Objects.hash(type) + } + + override fun toString(): String { + return "JsonTypeReference{$type}" + } + + override fun compareTo(other: JsonTypeReference): Int { + return this.type.toString().compareTo(other.type.toString()) + } +} diff --git a/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeUtils.kt b/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeUtils.kt new file mode 100644 index 0000000..79b5c97 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/JsonTypeUtils.kt @@ -0,0 +1,201 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile JsonTypeUtils.kt + * LastUpdate 2025-09-15 22:04:54 + * UpdateUser MingLiPro + */ +@file:JvmName("JsonTypeUtils") + +package com.mingliqiye.utils.json + +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type +import java.util.* + + +/** + * 检查给定的类型是否是指定类或其子类/实现类。 + * + * @param type 要检查的类型 + * @param expectedClass 期望匹配的类 + * @return 如果类型匹配则返回 true,否则返回 false + */ +fun isTypeOf(type: Type, expectedClass: Class<*>): Boolean { + return when (type) { + is Class<*> -> expectedClass.isAssignableFrom(type) + is ParameterizedType -> isTypeOf(type.rawType, expectedClass) + else -> false + } +} + +/** + * 获取泛型类型的参数类型。 + * + * @param type 泛型类型 + * @param index 参数索引(从0开始) + * @return 指定位置的泛型参数类型 + * @throws IllegalArgumentException 当无法获取指定索引的泛型参数时抛出异常 + */ +fun getGenericParameter(type: Type, index: Int): Type { + if (type is ParameterizedType) { + val typeArgs = type.actualTypeArguments + if (index >= 0 && index < typeArgs.size) { + return typeArgs[index] + } + } + throw IllegalArgumentException( + "无法获取泛型参数: $type at index $index" + ) +} + +/** + * 获取类型名称,支持普通类和泛型类型。 + * + * @param type 类型对象 + * @return 类型名称字符串 + */ +fun getTypeName(type: Type): String { + return when (type) { + is Class<*> -> type.simpleName + is ParameterizedType -> { + val rawType = type.rawType as Class<*> + val typeArgs = type.actualTypeArguments + + val sb = StringBuilder(rawType.simpleName) + sb.append("<") + for (i in typeArgs.indices) { + if (i > 0) sb.append(", ") + sb.append(getTypeName(typeArgs[i])) + } + sb.append(">") + sb.toString() + } + + else -> type.typeName + } +} + +/** + * 创建一个表示数组类型的引用对象。 + * + * @param componentType 数组元素的类型 + * @param 元素类型 + * @return 表示数组类型的 JsonTypeReference 对象 + */ +fun arrayType(componentType: Class): JsonTypeReference> { + return object : JsonTypeReference>() { + private val arrayType: Type = java.lang.reflect.Array.newInstance( + componentType, 0 + ).javaClass + + override var type: Type = Any::class.java + get() = object : ParameterizedType { + private val actualTypeArguments = arrayOf(componentType) + + override fun getActualTypeArguments(): Array { + return actualTypeArguments + } + + override fun getRawType(): Type { + return arrayType + } + + override fun getOwnerType(): Type? { + return null + } + } + } +} + +/** + * 创建一个表示 List 类型的引用对象。 + * + * @param componentType List 中元素的类型 + * @param 元素类型 + * @return 表示 List 类型的 JsonTypeReference 对象 + * @throws IllegalArgumentException 如果 componentType 为 null,则抛出异常 + */ +fun listType(componentType: Class): JsonTypeReference> { + + return object : JsonTypeReference>() { + override var type: Type = Any::class.java + get() = object : ParameterizedType { + override fun getActualTypeArguments(): Array { + return arrayOf(componentType) + } + + override fun getRawType(): Type { + return List::class.java + } + + override fun getOwnerType(): Type? { + return null + } + } + } +} + +/** + * 创建一个表示 Map 类型的引用对象。 + * + * @param keyType Map 键的类型 + * @param valueType Map 值的类型 + * @param 键类型 + * @param 值类型 + * @return 表示 Map 类型的 JsonTypeReference 对象 + * @throws IllegalArgumentException 如果 keyType 或 valueType 为 null,则抛出异常 + */ +fun MapType(keyType: Class, valueType: Class): JsonTypeReference> { + + return object : JsonTypeReference>() { + override var type: Type = Any::class.java + get() = object : ParameterizedType { + override fun getActualTypeArguments(): Array { + return arrayOf(keyType, valueType) + } + + override fun getRawType(): Type { + return Map::class.java + } + + override fun getOwnerType(): Type? { + return null + } + + override fun equals(obj: Any?): Boolean { + if (this === obj) return true + if (obj !is ParameterizedType) return false + + val that = obj + return (Objects.equals( + rawType, + that.rawType + ) && actualTypeArguments.contentEquals(that.actualTypeArguments) && Objects.equals( + ownerType, + that.ownerType + )) + } + + override fun hashCode(): Int { + return (actualTypeArguments.contentHashCode() xor Objects.hashCode(rawType) xor Objects.hashCode( + ownerType + )) + } + } + } +} diff --git a/src/main/kotlin/com/mingliqiye/utils/logger/Loggers.kt b/src/main/kotlin/com/mingliqiye/utils/logger/Loggers.kt index 8fcf2ef..4b8cfc6 100644 --- a/src/main/kotlin/com/mingliqiye/utils/logger/Loggers.kt +++ b/src/main/kotlin/com/mingliqiye/utils/logger/Loggers.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Loggers.kt - * LastUpdate 2025-09-14 18:19:29 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ diff --git a/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt b/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt new file mode 100644 index 0000000..fa4a5c0 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt @@ -0,0 +1,350 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile AddressPort.kt + * LastUpdate 2025-09-15 22:01:27 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.network + +import java.io.Serializable +import java.net.InetAddress +import java.net.InetSocketAddress +import java.net.UnknownHostException +import java.util.regex.Pattern + +/** + * 网络地址类,用于表示一个网络地址(IP或域名),并提供相关操作。 + * 支持IPv4和IPv6地址的解析与验证。 + * + * @author MingLiPro + */ +class NetworkAddress private constructor(domip: String) : Serializable { + + /** + * IPv6标识 + */ + companion object { + const val IPV6 = 6 + + /** + * IPv4标识 + */ + const val IPV4 = 4 + + /** + * IPv4地址正则表达式 + */ + private const val IPV4REG = + "^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2" + "(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$" + + /** + * 编译后的IPv4地址匹配模式 + */ + private val IPV4_PATTERN = Pattern.compile(IPV4REG) + + /** + * IPv6地址正则表达式 + */ + private const val IPV6REG = + "^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|" + "^(::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4})$" + "|" + "^(::)$|" + "^([0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4})$|" + "^(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})$|" + "^(([0-9a-fA-F]{1,4}:){6}(([0-9]{1,3}\\.){3}[0-9]{1,3}))$|" + "^::([fF]{4}:)?(([0-9]{1,3}\\.){3}[0-9]{1,3})$" + + /** + * 编译后的IPv6地址匹配模式 + */ + private val IPV6_PATTERN = Pattern.compile(IPV6REG) + + /** + * 静态工厂方法,创建 NetworkAddress 实例。 + * + * @param domip 可能是IP地址或域名的字符串 + * @return 新建的 NetworkAddress 实例 + */ + @JvmStatic + fun of(domip: String): NetworkAddress { + return NetworkAddress(domip) + } + + /** + * 静态工厂方法,通过 InetAddress 创建 NetworkAddress 实例。 + * + * @param inetAddress InetAddress 对象 + * @return 新建的 NetworkAddress 实例 + */ + @JvmStatic + fun of(inetAddress: InetAddress): NetworkAddress { + return NetworkAddress(inetAddress.hostAddress) + } + + /** + * 从DNS服务器解析域名获取对应的IP地址。 + * + * @param domain 域名 + * @return 解析出的第一个IP地址 + * @throws UnknownHostException 如果域名无法解析 + */ + @JvmStatic + @Throws(UnknownHostException::class) + fun getHostIp(domain: String): String { + val addresses = InetAddress.getAllByName(domain.trim()) + return addresses[0].hostAddress + } + + /** + * 检测给定字符串是否为有效的IPv4或IPv6地址。 + * + * @param ip 要检测的IP地址字符串 + * @return 4 表示IPv4,6 表示IPv6 + * @throws NetworkException 如果IP格式无效 + */ + @JvmStatic + fun testIp(ip: String?): Int { + if (ip == null) { + throw NetworkException("IP地址不能为null") + } + val trimmedIp = ip.trim() + + // 判断是否匹配IPv4格式 + if (IPV4_PATTERN.matcher(trimmedIp).matches()) { + return IPV4 + } + + // 判断是否匹配IPv6格式 + if (IPV6_PATTERN.matcher(trimmedIp).matches()) { + return IPV6 + } + + // 不符合任一格式时抛出异常 + throw NetworkException( + "[$ip] 不是有效的IPv4或IPv6地址" + ) + } + } + + /** + * IP地址类型:4 表示 IPv4,6 表示 IPv6 + */ + var iPv: Int = 0 + private set + + /** + * IP地址字符串 + */ + var ip: String? = null + private set + + /** + * 域名(如果输入的是域名) + */ + private var domain: String? = null + + /** + * 标识是否是域名解析来的IP + */ + private var isdom = false + + /** + * 构造方法,根据传入的字符串判断是IP地址还是域名,并进行相应处理。 + * + * @param domip 可能是IP地址或域名的字符串 + */ + init { + try { + // 尝试将输入识别为IP地址 + this.iPv = testIp(domip) + this.ip = domip + } catch (e: NetworkException) { + try { + // 如果不是有效IP,则尝试作为域名解析 + val ips = getHostIp(domip) + this.iPv = testIp(ips) + this.ip = ips + this.isdom = true + this.domain = domip + } catch (ex: UnknownHostException) { + throw NetworkException(ex) + } + } + } + + /** + * 将当前 NetworkAddress 转换为 InetAddress 对象。 + * + * @return InetAddress 对象 + */ + fun toInetAddress(): InetAddress { + try { + return InetAddress.getByName(if (ip != null) ip else domain) + } catch (e: UnknownHostException) { + throw RuntimeException(e) + } + } + + /** + * 返回 NetworkAddress 的字符串表示形式。 + * + * @return 字符串表示 + */ + override fun toString(): String { + return if (isdom) "NetworkAddress(IP='$ip',type='$iPv',domain='$domain')" + else "NetworkAddress(IP='$ip',type='$iPv')" + } +} + + +class NetworkPort : Serializable { + val port: Int + + constructor(port: Int) { + testPort(port) + this.port = port + } + + companion object { + fun testPort(port: Int) { + // 验证端口号范围是否在0-65535之间 + if (port !in 0..65535) { + throw NetworkException("$port 不是正确的端口号") + } + } + } +} + +class NetworkException : RuntimeException { + /** + * 构造一个带有指定详细消息的网络异常 + * + * @param message 异常的详细消息 + */ + constructor(message: String?) : super(message) + + /** + * 构造一个网络异常,指定原因异常 + * + * @param e 导致此异常的原因异常 + */ + constructor(e: Exception?) : super(e) +} + +/** + * IP和端口聚集类,用于封装网络地址与端口信息。 + * 该类提供了与InetSocketAddress之间的相互转换功能。 + * + * @author MingLiPro + * @see java.net.InetSocketAddress + */ +class NetworkEndpoint private constructor( + val networkAddress: NetworkAddress, val networkPort: NetworkPort +) : Serializable { + + + companion object { + /** + * 根据给定的InetSocketAddress对象创建NetworkEndpoint实例。 + * + * @param address InetSocketAddress对象 + * @return 新建的NetworkEndpoint实例 + * @see java.net.InetSocketAddress + */ + @JvmStatic + fun of(address: InetSocketAddress): NetworkEndpoint { + return NetworkEndpoint( + NetworkAddress.of(address.hostString), NetworkPort(address.port) + ) + } + + /** + * 根据主机名或IP字符串和端口号创建NetworkEndpoint实例。 + * + * @param s 主机名或IP地址字符串 + * @param i 端口号 + * @return 新建的NetworkEndpoint实例 + */ + @JvmStatic + fun of(s: String, i: Int): NetworkEndpoint { + val networkAddress = NetworkAddress.of(s) + val networkPort = NetworkPort(i) + return NetworkEndpoint(networkAddress, networkPort) + } + + /** + * 根据"host:port"格式的字符串创建NetworkEndpoint实例。 + * 例如:"127.0.0.1:8080" + * + * @param s "host:port"格式的字符串 + * @return 新建的NetworkEndpoint实例 + */ + @JvmStatic + fun of(s: String): NetworkEndpoint { + val lastColonIndex = s.lastIndexOf(':') + return of( + s.take(lastColonIndex), s.substring(lastColonIndex + 1).toInt() + ) + } + } + + /** + * 将当前NetworkEndpoint转换为InetSocketAddress对象。 + * + * @return 对应的InetSocketAddress对象 + * @see InetSocketAddress + */ + fun toInetSocketAddress(): InetSocketAddress { + return InetSocketAddress( + networkAddress.toInetAddress(), networkPort.port + ) + } + + /** + * 将当前NetworkEndpoint转换为"host:port"格式的字符串。 + * 例如:"127.0.0.1:25563" + * + * @return 格式化后的字符串 + */ + fun toHostPortString(): String { + return "${networkAddress.ip}:${networkPort.port}" + } + + /** + * 返回NetworkEndpoint的详细字符串表示形式。 + * 格式:NetworkEndpoint(IP=...,Port=...,Endpoint=...) + * + * @return 包含详细信息的字符串 + */ + override fun toString(): String { + return "NetworkEndpoint(IP=${networkAddress.ip},Port=${networkPort.port},Endpoint=${toHostPortString()})" + } + + /** + * 获取主机名或IP地址字符串。 + * + * @return 主机名或IP地址 + */ + fun host(): String { + return networkAddress.ip ?: "" + } + + /** + * 获取端口号。 + * + * @return 端口号 + */ + fun port(): Int { + return networkPort.port + } +} diff --git a/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt b/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt index 5ca427e..89a236c 100644 --- a/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt +++ b/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt @@ -16,13 +16,15 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile RandomBytes.kt - * LastUpdate 2025-09-15 09:54:33 + * LastUpdate 2025-09-15 22:27:36 * UpdateUser MingLiPro */ @file:JvmName("RandomBytes") package com.mingliqiye.utils.random +import java.security.SecureRandom + /** * 生成指定长度的随机字节数组 * @param length 数组长度 @@ -78,3 +80,13 @@ fun randomByteNoHave(from: Byte, to: Byte): Byte { val randomValue = randomIntNoHave(fromInt, toInt) return (randomValue and 0xFF).toByte() } + +val secureRandom: SecureRandom by lazy { + SecureRandom() +} + +fun randomByteSecure(size: Int): ByteArray { + val bytes = ByteArray(size) + secureRandom.nextBytes(bytes) + return bytes +} diff --git a/src/main/kotlin/com/mingliqiye/utils/security/AesUtils.kt b/src/main/kotlin/com/mingliqiye/utils/security/AesUtils.kt index 63605d1..87bdab5 100644 --- a/src/main/kotlin/com/mingliqiye/utils/security/AesUtils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/security/AesUtils.kt @@ -1,6 +1,29 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile AesUtils.kt + * LastUpdate 2025-09-15 22:32:50 + * UpdateUser MingLiPro + */ + @file:JvmName("AesUtils") package com.mingliqiye.utils.security + import javax.crypto.Cipher import javax.crypto.spec.GCMParameterSpec @@ -9,8 +32,8 @@ const val AES_GCM_NO_PADDING = "AES/GCM/NoPadding" const val AES_GCM_NO_PADDING_IV_LENGTH = 12 const val AES_GCM_NO_PADDING_TAG_LENGTH = 16 -fun encryptAesGcmNoPadding(src: ByteArray, key: ByteArray,iv: ByteArray): ByteArray { - val secretKeySpec = createSecretKeySpec(ALGORITHM,key) +fun encryptAesGcmNoPadding(src: ByteArray, key: ByteArray, iv: ByteArray): ByteArray { + val secretKeySpec = createSecretKeySpec(ALGORITHM, key) val cipher = Cipher.getInstance(AES_GCM_NO_PADDING) val gcmParameterSpec = GCMParameterSpec( AES_GCM_NO_PADDING_TAG_LENGTH * 8, @@ -19,16 +42,18 @@ fun encryptAesGcmNoPadding(src: ByteArray, key: ByteArray,iv: ByteArray): ByteAr cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec) return cipher.doFinal(src) } -fun encryptAesGcmNoPadding(src: ByteArray, key: String,iv: ByteArray): ByteArray { + +fun encryptAesGcmNoPadding(src: ByteArray, key: String, iv: ByteArray): ByteArray { return encryptAesGcmNoPadding(src, key.toByteArray(), iv) } -fun encryptAesGcmNoPadding(src: String, key: String,iv: ByteArray): ByteArray { + +fun encryptAesGcmNoPadding(src: String, key: String, iv: ByteArray): ByteArray { return encryptAesGcmNoPadding(src.toByteArray(), key.toByteArray(), iv) } fun main() { val iv = getRandomBytes(16) - println(encryptAesGcmNoPadding("mingliqiye","key", iv)) + println(encryptAesGcmNoPadding("mingliqiye", "key", iv)) } diff --git a/src/main/kotlin/com/mingliqiye/utils/security/SecureUtils.kt b/src/main/kotlin/com/mingliqiye/utils/security/SecureUtils.kt index 12c7e60..bc96628 100644 --- a/src/main/kotlin/com/mingliqiye/utils/security/SecureUtils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/security/SecureUtils.kt @@ -1,3 +1,25 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile SecureUtils.kt + * LastUpdate 2025-09-15 22:32:50 + * UpdateUser MingLiPro + */ + @file:JvmName("SecureUtils") package com.mingliqiye.utils.security @@ -25,9 +47,9 @@ fun createSecretKey(algorithm: String, data: String): ByteArray { } fun createSecretKeySpec(algorithm: String, data: String): SecretKey { - return SecretKeySpec( createSecretKey(algorithm,data), algorithm) + return SecretKeySpec(createSecretKey(algorithm, data), algorithm) } fun createSecretKeySpec(algorithm: String, data: ByteArray): SecretKey { - return SecretKeySpec( createSecretKey(algorithm,data), algorithm) -} \ No newline at end of file + return SecretKeySpec(createSecretKey(algorithm, data), algorithm) +} diff --git a/src/main/kotlin/com/mingliqiye/utils/springboot/autoconfigure/AutoConfiguration.kt b/src/main/kotlin/com/mingliqiye/utils/springboot/autoconfigure/AutoConfiguration.kt index 9bc395f..f50987e 100644 --- a/src/main/kotlin/com/mingliqiye/utils/springboot/autoconfigure/AutoConfiguration.kt +++ b/src/main/kotlin/com/mingliqiye/utils/springboot/autoconfigure/AutoConfiguration.kt @@ -16,14 +16,17 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile AutoConfiguration.kt - * LastUpdate 2025-09-15 08:51:52 + * LastUpdate 2025-09-15 22:20:25 * UpdateUser MingLiPro */ package com.mingliqiye.utils.springboot.autoconfigure import com.mingliqiye.utils.logger.mingLiLoggerFactory -import com.mingliqiye.utils.system.getJdkVersion +import com.mingliqiye.utils.system.computerName +import com.mingliqiye.utils.system.getPid +import com.mingliqiye.utils.system.jdkVersion +import com.mingliqiye.utils.system.userName import com.mingliqiye.utils.time.DateTime import com.mingliqiye.utils.time.Formatter import org.springframework.context.annotation.ComponentScan @@ -63,8 +66,11 @@ open class AutoConfiguration { metaData.append(String(buffer, 0, readlen)) } val da = metaData.toString().split("\n").toMutableList() - da.add("time=" + DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7)) - da.add("jdkRuntime=" + getJdkVersion()) + da.add("jdkRuntime=$jdkVersion") + da.add("pid=$getPid") + da.add("computerName=$computerName") + da.add("userName=$userName") + da.add("time=" + DateTime.now().format(Formatter.STANDARD_DATETIME_MILLISECOUND7, true)) da.forEach { s: String -> val d = s.trim { it <= ' ' }.split("=".toRegex(), 2).toTypedArray() if (d.size >= 2) { diff --git a/src/main/kotlin/com/mingliqiye/utils/string/StringUtils.kt b/src/main/kotlin/com/mingliqiye/utils/string/StringUtils.kt index fbdac3c..c71cad8 100644 --- a/src/main/kotlin/com/mingliqiye/utils/string/StringUtils.kt +++ b/src/main/kotlin/com/mingliqiye/utils/string/StringUtils.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile StringUtils.kt - * LastUpdate 2025-09-14 21:46:14 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @file:JvmName("StringUtils") diff --git a/src/main/kotlin/com/mingliqiye/utils/system/SystemUtil.kt b/src/main/kotlin/com/mingliqiye/utils/system/SystemUtil.kt index 44c671a..41aac96 100644 --- a/src/main/kotlin/com/mingliqiye/utils/system/SystemUtil.kt +++ b/src/main/kotlin/com/mingliqiye/utils/system/SystemUtil.kt @@ -16,26 +16,33 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile SystemUtil.kt - * LastUpdate 2025-09-15 11:18:34 + * LastUpdate 2025-09-15 22:19:57 * UpdateUser MingLiPro */ @file:JvmName("SystemUtils") package com.mingliqiye.utils.system +import java.lang.management.ManagementFactory import java.net.Inet4Address +import java.net.InetAddress import java.net.NetworkInterface import java.net.SocketException -private val osName: String? = System.getProperties().getProperty("os.name") +/** + * 操作系统名称属性,延迟初始化 + */ +val osName: String? by lazy { + System.getProperties().getProperty("os.name") +} /** * 判断当前操作系统是否为Windows系统 * * @return 如果是Windows系统返回true,否则返回false */ -fun isWindows(): Boolean { - return osName != null && osName.startsWith("Windows") +val isWindows: Boolean by lazy { + osName != null && osName!!.startsWith("Windows") } /** @@ -43,8 +50,8 @@ fun isWindows(): Boolean { * * @return 如果是Mac系统返回true,否则返回false */ -fun isMac(): Boolean { - return osName != null && osName.startsWith("Mac") +val isMac: Boolean by lazy { + osName != null && osName!!.startsWith("Mac") } /** @@ -52,31 +59,30 @@ fun isMac(): Boolean { * * @return 如果是Unix/Linux系统返回true,否则返回false */ -fun isUnix(): Boolean { +val isUnix: Boolean by lazy { if (osName == null) { - return false + false + } else { + (osName!!.startsWith("Linux") || osName!!.startsWith("AIX") || osName!!.startsWith("SunOS") || osName!!.startsWith( + "Mac OS X" + ) || osName!!.startsWith( + "FreeBSD" + )) } - return (osName.startsWith("Linux") || osName.startsWith("AIX") || osName.startsWith("SunOS") || osName.startsWith("Mac OS X") || osName.startsWith( - "FreeBSD" - )) } /** - * 获取JDK版本号 - * - * @return JDK版本号字符串 + * JDK版本号属性,延迟初始化 */ -fun getJdkVersion(): String? { - return System.getProperty("java.specification.version") +val jdkVersion: String? by lazy { + System.getProperty("java.specification.version") } /** - * 获取Java版本号的整数形式 - * - * @return Java版本号的整数形式(如:8、11、17等) + * Java版本号的整数形式属性,延迟初始化 */ -fun getJavaVersionAsInteger(): Int { - val version = getJdkVersion() +val javaVersionAsInteger: Int by lazy { + val version = jdkVersion if (version == null || version.isEmpty()) { throw IllegalStateException( "Unable to determine Java version from property 'java.specification.version'" @@ -98,7 +104,7 @@ fun getJavaVersionAsInteger(): Int { } version.take(2) } - return uversion.toInt() + uversion.toInt() } /** @@ -106,18 +112,17 @@ fun getJavaVersionAsInteger(): Int { * * @return 如果JDK版本大于8返回true,否则返回false */ -fun isJdk8Plus(): Boolean { - return getJavaVersionAsInteger() > 8 +val isJdk8Plus: Boolean by lazy { + javaVersionAsInteger > 8 } /** - * 获取本地IP地址数组 + * 本地IP地址数组,延迟初始化 * - * @return 本地IP地址字符串数组 * @throws RuntimeException 当获取网络接口信息失败时抛出 */ -fun getLocalIps(): Array { - return try { +val localIps: Array by lazy { + try { val ipList: MutableList = ArrayList() val interfaces = NetworkInterface.getNetworkInterfaces() @@ -145,22 +150,18 @@ fun getLocalIps(): Array { } /** - * 获取本地IP地址列表 - * - * @return 本地IP地址的字符串列表 + * 本地IP地址列表,延迟初始化 */ -fun getLocalIpsByList(): List { - return getLocalIps().toList() +val localIpsByList: List by lazy { + localIps.toList() } /** - * 获取本地回环地址 - * - * @return 回环地址字符串,通常为"127.0.0.1" + * 本地回环地址数组,延迟初始化 */ -fun getLoopbackIps(): Array { +val loopbackIps: Array by lazy { val strings: MutableList = ArrayList(3) - return try { + return@lazy try { val interfaces = NetworkInterface.getNetworkInterfaces() while (interfaces.hasMoreElements()) { @@ -183,11 +184,92 @@ fun getLoopbackIps(): Array { } /** - * 获取本地回环地址IP列表 - * - * @return 本地回环地址IP字符串列表的副本 + * 本地回环地址IP列表,延迟初始化 */ -fun getLoopbackIpsByList(): List { - // 将本地回环地址IP数组转换为列表并返回 - return getLoopbackIps().toList() +val loopbackIpsByList: List by lazy { + loopbackIps.toList() +} + +/** + * 获取当前进程的PID + * + * @return 进程ID,如果无法获取则返回-1 + */ +val getPid: Long by lazy { + try { + val name = ManagementFactory.getRuntimeMXBean().name + val index = name.indexOf('@') + if (index > 0) { + name.take(index).toLong() + } else { + -1L + } + } catch (e: Exception) { + -1L + } +} + +/** + * 获取当前进程的PID字符串形式 + * + * @return 进程ID字符串,如果无法获取则返回"-1" + */ +val pidAsString: String by lazy { + try { + val name = ManagementFactory.getRuntimeMXBean().name + val index = name.indexOf('@') + if (index > 0) { + name.take(index) + } else { + "-1" + } + } catch (e: Exception) { + "-1" + } +} + +/** + * 获取计算机名 + * + * @return 计算机名,如果无法获取则返回"unknown" + */ +val computerName: String by lazy { + try { + var name = System.getenv("COMPUTERNAME") + if (name.isNullOrBlank()) { + name = System.getenv("HOSTNAME") + } + if (name.isNullOrBlank()) { + name = InetAddress.getLocalHost().hostName + } + name ?: "unknown" + } catch (e: Exception) { + "unknown" + } +} + +/** + * 获取当前用户名 + * + * @return 当前用户名,如果无法获取则返回"unknown" + */ +val userName: String by lazy { + try { + getEnvVar("USERNAME") + ?: getEnvVar("USER") + ?: System.getProperty("user.name") + ?: "unknown" + } catch (e: SecurityException) { + "unknown" + } catch (e: Exception) { + "unknown" + } +} + +private fun getEnvVar(name: String): String? { + return try { + System.getenv(name)?.takeIf { it.isNotBlank() } + } catch (e: SecurityException) { + null + } } diff --git a/src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt b/src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt index b605eea..80e65cc 100644 --- a/src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt +++ b/src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile DateTime.kt - * LastUpdate 2025-09-15 09:57:50 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @@ -27,8 +27,8 @@ import com.mingliqiye.utils.jna.NANOS_PER_100NS import com.mingliqiye.utils.jna.WinKernel32Api import com.mingliqiye.utils.jna.getWinKernel32Apis import com.mingliqiye.utils.logger.mingLiLoggerFactory -import com.mingliqiye.utils.system.getJavaVersionAsInteger import com.mingliqiye.utils.system.isWindows +import com.mingliqiye.utils.system.javaVersionAsInteger import org.slf4j.Logger import java.io.Serializable import java.time.LocalDateTime @@ -185,8 +185,8 @@ class DateTime private constructor( companion object { private val WIN_KERNEL_32_API: WinKernel32Api? = if ( - getJavaVersionAsInteger() == 8 && - isWindows() + javaVersionAsInteger == 8 && + isWindows ) { val log: Logger = mingLiLoggerFactory.getLogger("mingli-utils DateTime") val a = getWinKernel32Apis() diff --git a/src/main/kotlin/com/mingliqiye/utils/uuid/MysqlUUIDv1.kt b/src/main/kotlin/com/mingliqiye/utils/uuid/MysqlUUIDv1.kt index 4ddf00a..c7bcd1a 100644 --- a/src/main/kotlin/com/mingliqiye/utils/uuid/MysqlUUIDv1.kt +++ b/src/main/kotlin/com/mingliqiye/utils/uuid/MysqlUUIDv1.kt @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile MysqlUUIDv1.kt - * LastUpdate 2025-09-14 18:19:29 + * LastUpdate 2025-09-15 22:32:50 * UpdateUser MingLiPro */ @file:JvmName("MysqlUUIDv1") diff --git a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 8735d74..db0d345 100644 --- a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -16,7 +16,7 @@ # ProjectName mingli-utils # ModuleName mingli-utils.main # CurrentFile org.springframework.boot.autoconfigure.AutoConfiguration.imports -# LastUpdate 2025-09-09 08:37:33 +# LastUpdate 2025-09-15 22:32:50 # UpdateUser MingLiPro #