no message
All checks were successful
Gitea Actions Build / Build (push) Successful in 1m3s

This commit is contained in:
Armamem0t 2025-09-11 16:26:26 +08:00
parent 77d60b38fc
commit b1dc8c0ac8
Signed by: minglipro
GPG Key ID: 5F355A77B22AA93B
15 changed files with 298 additions and 432 deletions

View File

@ -64,14 +64,15 @@ dependencies {
annotationProcessor("org.projectlombok:lombok:1.18.38")
compileOnly("org.springframework.boot:spring-boot-starter:2.7.14")
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2")
compileOnly("com.google.code.gson:gson:2.13.1")
compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58")
compileOnly("org.projectlombok:lombok:1.18.38")
implementation("org.bouncycastle:bcprov-jdk18on:1.81")
implementation("com.github.f4b6a3:uuid-creator:6.1.0")
implementation("org.mindrot:jbcrypt:0.4")
implementation("org.jetbrains:annotations:24.0.0")
implementation("net.java.dev.jna:jna:5.17.0")
// https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api
implementation("jakarta.annotation:jakarta.annotation-api:2.1.1")
}

View File

@ -22,4 +22,4 @@
JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils
VERSIONS=3.1.1
VERSIONS=3.1.2

View File

@ -1,45 +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 Serializers.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Serializers {
/**
* 为ObjectMapper添加自定义序列化器 uuid time
* @see com.mingliqiye.utils.uuid.UUID
* @see com.mingliqiye.utils.time.DateTime
* @param objectMapper ObjectMapper实例用于注册自定义序列化器
*/
public static void addSerializers(ObjectMapper objectMapper) {
// 添加UUID相关的序列化器
com.mingliqiye.utils.uuid.serialization.Jackson.addSerializers(
objectMapper
);
// 添加时间相关的序列化器
com.mingliqiye.utils.time.serialization.Jackson.addSerializers(
objectMapper
);
}
}

View File

@ -0,0 +1,32 @@
package com.mingliqiye.utils.json.converters;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.time.Formatter;
public class DateTimeJsonConverter extends JsonStringConverter<DateTime> {
@Override
public Class<DateTime> getTClass() {
return DateTime.class;
}
@Override
public String convert(DateTime obj) {
if (obj == null) {
return null;
}
return obj.format(Formatter.STANDARD_DATETIME);
}
@Override
public DateTime deConvert(String string) {
if (string == null) {
return null;
}
return DateTime.parse(
string,
Formatter.STANDARD_DATETIME_MILLISECOUND7,
true
);
}
}

View File

@ -0,0 +1,158 @@
package com.mingliqiye.utils.json.converters;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* JSON转换器接口提供对象与字符串之间的相互转换功能并支持多种JSON库
*
* @param <T> 需要转换的对象类型
*/
public abstract class JsonStringConverter<T> {
public abstract Class<T> getTClass();
/**
* 将对象转换为字符串
*
* @param obj 待转换的对象
* @return 转换后的字符串
*/
abstract String convert(T obj);
/**
* 将字符串转换为对象
*
* @param string 待转换的字符串
* @return 转换后的对象
*/
abstract T deConvert(String string);
/**
* 获取Jackson反序列化器
*
* @return Jackson的JsonDeserializer实例
*/
public JsonDeserializer<T> getJacksonJsonDeserializer() {
return new JsonDeserializer<T>() {
@Override
public T deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
// 如果是NaN则返回null
if (p.isNaN()) return null;
return deConvert(p.getValueAsString());
}
};
}
/**
* 获取Jackson序列化器
*
* @return Jackson的JsonSerializer实例
*/
public JsonSerializer<T> getJacksonJsonSerializer() {
return new JsonSerializer<T>() {
@Override
public void serialize(
T value,
JsonGenerator gen,
SerializerProvider serializers
) throws IOException {
// 如果值为null则写入null
if (value == null) {
gen.writeNull();
return;
}
gen.writeString(convert(value));
}
};
}
public Module getJacksonModule() {
Class<T> tClass = getTClass();
SimpleModule m = new SimpleModule(tClass.getSimpleName());
m.addSerializer(tClass, getJacksonJsonSerializer());
m.addDeserializer(tClass, getJacksonJsonDeserializer());
return m;
}
/**
* 获取Gson类型适配器
*
* @return Gson的TypeAdapter实例
*/
public TypeAdapter<T> getGsonTypeAdapter() {
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
// 如果值为null则写入null值
if (value == null) {
out.nullValue();
return;
}
out.value(convert(value));
}
@Override
public T read(JsonReader in) throws IOException {
String value = in.nextString();
return deConvert(value);
}
};
}
/**
* FastJson 支持
*/
/**
* 获取FastJson对象写入器
*
* @return FastJson的ObjectWriter实例
*/
public ObjectWriter<T> getFastJsonObjectWriter() {
return (
JSONWriter writer,
Object object,
Object fieldName,
Type fieldType,
long features
) -> {
// 如果对象为null则写入null
if (object == null) {
writer.writeNull();
return;
}
writer.writeString(convert((T) object));
};
}
/**
* 获取FastJson对象读取器
*
* @return FastJson的ObjectReader实例
*/
public ObjectReader<T> getFastJsonObjectReader() {
return (
JSONReader reader,
Type fieldType,
Object fieldName,
long features
) -> {
String value = reader.readString();
return deConvert(value);
};
}
}

View File

@ -0,0 +1,27 @@
package com.mingliqiye.utils.json.converters;
import com.mingliqiye.utils.uuid.UUID;
public class UUIDJsonStringConverter extends JsonStringConverter<UUID> {
@Override
public Class<UUID> getTClass() {
return UUID.class;
}
@Override
public String convert(UUID obj) {
if (obj == null) {
return null;
}
return obj.toUUIDString();
}
@Override
public UUID deConvert(String string) {
if (string == null) {
return null;
}
return UUID.of(string);
}
}

View File

@ -38,7 +38,7 @@ import java.io.InputStream;
@ComponentScan(
{
"com.mingliqiye.utils.bean.springboot",
"com.mingliqiye.utils.springboot.autoconfigure.converters",
"com.mingliqiye.utils.springboot.converters",
}
)
public class AutoConfiguration {

View File

@ -0,0 +1,58 @@
package com.mingliqiye.utils.springboot.autoconfigure;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter;
import com.mingliqiye.utils.json.converters.JsonStringConverter;
import com.mingliqiye.utils.json.converters.UUIDJsonStringConverter;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.uuid.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
@ConditionalOnClass(Gson.class)
@AutoConfiguration
@AutoConfigureAfter(
name = {
"org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration",
}
)
public class GsonAutoConfiguration {
private static final Logger log = LoggerFactory.getLogger(
"MingliUtils-GsonAutoConfiguration"
);
public static GsonBuilder addTypeAdapter(GsonBuilder gsonBuilder) {
JsonStringConverter<DateTime> dateTimeJsonConverter =
new DateTimeJsonConverter();
JsonStringConverter<UUID> uuidJsonStringConverter =
new UUIDJsonStringConverter();
return gsonBuilder
.registerTypeAdapter(
uuidJsonStringConverter.getTClass(),
uuidJsonStringConverter.getGsonTypeAdapter()
)
.registerTypeAdapter(
dateTimeJsonConverter.getTClass(),
dateTimeJsonConverter.getGsonTypeAdapter()
);
}
@Bean
@Primary
@ConditionalOnMissingBean
public GsonBuilder gsonBuilder() {
try {
return addTypeAdapter(new GsonBuilder());
} finally {
log.info("MingliUtils GsonBuilder TypeAdapter add");
}
}
}

View File

@ -1,38 +1,35 @@
package com.mingliqiye.utils.springboot.autoconfigure;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mingliqiye.utils.jackson.Serializers;
import com.mingliqiye.utils.json.JacksonJsonApi;
import com.mingliqiye.utils.json.JsonApi;
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter;
import com.mingliqiye.utils.json.converters.UUIDJsonStringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
@ConditionalOnClass(ObjectMapper.class)
@AutoConfiguration
@AutoConfigureAfter(
name = {
"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration",
}
)
@ConditionalOnClass(ObjectMapper.class)
public class JacksonAutoConfiguration {
private final Logger log = LoggerFactory.getLogger(
private static final Logger log = LoggerFactory.getLogger(
"MingliUtils-JacksonAutoConfiguration"
);
public JacksonAutoConfiguration() {
log.info("MingliUtils JacksonAutoConfiguration succeed");
public JacksonAutoConfiguration(ObjectMapper objectMapper) {
addModules(objectMapper);
log.info("MingliUtils Jackson Serializers created");
}
@Bean
public JsonApi jsonApi(ObjectMapper objectMapper) {
log.info("Creating JacksonJsonApi bean");
Serializers.addSerializers(objectMapper);
log.info("MingliUtils Serializers created");
return new JacksonJsonApi(objectMapper);
public static ObjectMapper addModules(ObjectMapper objectMapper) {
return objectMapper
.registerModule(new UUIDJsonStringConverter().getJacksonModule())
.registerModule(new DateTimeJsonConverter().getJacksonModule());
}
}

View File

@ -1,12 +1,12 @@
package com.mingliqiye.utils.springboot.autoconfigure.converters;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME;
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.time.DateTime;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME;
/**
* spring boot DateTime到字符串转换器
*

View File

@ -1,12 +1,12 @@
package com.mingliqiye.utils.springboot.autoconfigure.converters;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME_MILLISECOUND7;
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.time.DateTime;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import static com.mingliqiye.utils.time.Formatter.STANDARD_DATETIME_MILLISECOUND7;
/**
* spring boot 字符串到DateTime转换器
*

View File

@ -1,4 +1,4 @@
package com.mingliqiye.utils.springboot.autoconfigure.converters;
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.uuid.UUID;
import org.jetbrains.annotations.NotNull;

View File

@ -1,4 +1,4 @@
package com.mingliqiye.utils.springboot.autoconfigure.converters;
package com.mingliqiye.utils.springboot.converters;
import com.mingliqiye.utils.uuid.UUID;
import org.jetbrains.annotations.NotNull;

View File

@ -1,221 +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 Jackson.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.time.serialization;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.mingliqiye.utils.time.DateTime;
import com.mingliqiye.utils.time.Formatter;
import java.io.IOException;
/**
* Jackson 适配器
*
* @author MingLiPro
*/
public class Jackson {
/**
* 为ObjectMapper添加自定义的 DateTime 序列化器和反序列化器
*
* @param objectMapper 用于注册自定义序列化模块的ObjectMapper实例
*/
public static void addSerializers(ObjectMapper objectMapper) {
// 创建SimpleModule并添加DateTime类型的序列化器和反序列化器
SimpleModule module = new SimpleModule("MingliqiyeDateTimeModule")
.addSerializer(DateTime.class, new DateTimeJsonSerializer())
.addDeserializer(DateTime.class, new DateTimeJsonDeserializerM7());
objectMapper.registerModule(module);
}
/**
* yyyy-MM-dd HH:mm:ss.SSSSSSS 的反序列化适配器
* <p>
* JSON 字符串按照指定格式解析为 DateTime 对象
*/
public static class DateTimeJsonDeserializerM7
extends DateTimeJsonDeserializer {
/**
* 获取当前使用的日期时间格式化器
*
* @return 返回标准的 7 位毫秒时间格式化器
*/
@Override
public Formatter getFormatter() {
return Formatter.STANDARD_DATETIME_MILLISECOUND7;
}
}
/**
* 默认日期时间反序列化器
* <p>
* 提供基础的日期时间反序列化功能支持自定义格式化器
*/
public static class DateTimeJsonDeserializer
extends JsonDeserializer<DateTime> {
/**
* 获取当前使用的日期时间格式化器
*
* @return 返回标准的日期时间格式化器
*/
public Formatter getFormatter() {
return Formatter.STANDARD_DATETIME;
}
/**
* 获取格式化器对应的字符串表达式
*
* @return 格式化器的字符串值
*/
public String getFormatterString() {
return getFormatter().getValue();
}
/**
* 反序列化方法 JSON 解析为 DateTime 对象
*
* @param p JSON 解析器对象
* @param ctxt 反序列化上下文
* @return 解析后的 DateTime 对象若输入为 NaN 则返回 null
* @throws IOException 当解析过程中发生 IO 异常时抛出
*/
@Override
public DateTime deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
// 如果是 NaN 值则返回 null
if (p.isNaN()) {
return null;
}
// 使用指定格式将字符串解析为 DateTime 对象
return DateTime.parse(
p.getValueAsString(),
getFormatterString(),
true
);
}
}
/**
* yyyy-MM-dd HH:mm:ss.SSSSSSS 的序列化适配器
* <p>
* DateTime 对象按指定格式转换为 JSON 字符串
*/
public static class DateTimeJsonSerializerM7
extends DateTimeJsonSerializer {
/**
* 获取当前使用的日期时间格式化器
*
* @return 返回标准的 7 位毫秒时间格式化器
*/
@Override
public Formatter getFormatter() {
return Formatter.STANDARD_DATETIME_MILLISECOUND7;
}
}
/**
* 默认日期时间序列化器
* <p>
* 提供基础的日期时间序列化功能支持自定义格式化器
*/
public static class DateTimeJsonSerializer
extends JsonSerializer<DateTime> {
/**
* 获取当前使用的日期时间格式化器
*
* @return 返回标准的日期时间格式化器
*/
public Formatter getFormatter() {
return Formatter.STANDARD_DATETIME;
}
/**
* 获取格式化器对应的字符串表达式
*
* @return 格式化器的字符串值
*/
public String getFormatterString() {
return getFormatter().getValue();
}
/**
* 序列化方法 DateTime 对象写入 JSON 生成器
*
* @param value 要序列化的 DateTime 对象
* @param gen JSON 生成器
* @param serializers 序列化提供者
* @throws IOException 当写入过程中发生 IO 异常时抛出
*/
@Override
public void serialize(
DateTime value,
JsonGenerator gen,
SerializerProvider serializers
) throws IOException {
// 若值为 null则直接写入 null
if (value == null) {
gen.writeNull();
return;
}
// 按照指定格式将 DateTime 写入为字符串
gen.writeString(value.format(getFormatterString(), true));
}
/**
* 带类型信息的序列化方法用于支持多态类型处理
*
* @param value 要序列化的 DateTime 对象
* @param gen JSON 生成器
* @param serializers 序列化提供者
* @param typeSer 类型序列化器
* @throws IOException 当写入过程中发生 IO 异常时抛出
*/
@Override
public void serializeWithType(
DateTime value,
JsonGenerator gen,
SerializerProvider serializers,
TypeSerializer typeSer
) throws IOException {
// 写入类型前缀
WritableTypeId typeId = typeSer.writeTypePrefix(
gen,
typeSer.typeId(value, JsonToken.VALUE_STRING)
);
// 执行实际序列化
serialize(value, gen, serializers);
// 写入类型后缀
typeSer.writeTypeSuffix(gen, typeId);
}
}
}

View File

@ -1,141 +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 Jackson.java
* LastUpdate 2025-09-09 08:37:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.uuid.serialization;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.mingliqiye.utils.uuid.UUID;
import com.mingliqiye.utils.uuid.UUIDException;
import java.io.IOException;
/**
* Jackson 序列化/反序列化适配器类用于处理自定义 UUID 类的 JSON 转换
*
* @author MingLiPro
*/
public class Jackson {
/**
* 为ObjectMapper添加UUID序列化和反序列化器
*
* @param objectMapper ObjectMapper实例用于注册自定义序列化模块
*/
public static void addSerializers(ObjectMapper objectMapper) {
// 创建SimpleModule并添加UUID的序列化器和反序列化器
SimpleModule module = new SimpleModule("MingliqiyeUUIDModule")
.addSerializer(UUID.class, new UUIDJsonSerializer())
.addDeserializer(UUID.class, new UUIDJsonDeserializer());
objectMapper.registerModule(module);
}
/**
* UUID 反序列化器
* <p>
* JSON 字符串反序列化为自定义 UUID 对象
*/
public static class UUIDJsonDeserializer extends JsonDeserializer<UUID> {
/**
* 反序列化方法 JSON 解析为 UUID 对象
*
* @param p JSON 解析器对象
* @param ctxt 反序列化上下文
* @return 解析后的 UUID 对象若输入为 NaN 则返回 null
* @throws IOException 当解析过程中发生 IO 异常时抛出
*/
@Override
public UUID deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
// 如果是 NaN 值则返回 null
if (p.isNaN()) {
return null;
}
// 使用指定字符串值创建新的 UUID 对象
return new UUID(p.getValueAsString());
}
}
/**
* UUID 序列化器
* <p>
* 将自定义 UUID 对象序列化为 JSON 字符串
*/
public static class UUIDJsonSerializer extends JsonSerializer<UUID> {
/**
* 序列化方法 UUID 对象写入 JSON 生成器
*
* @param uuid 要序列化的 UUID 对象
* @param jsonGenerator JSON 生成器
* @param serializerProvider 序列化提供者
* @throws UUIDException UUID 处理过程中发生异常时抛出
* @throws IOException 当写入过程中发生 IO 异常时抛出
*/
@Override
public void serialize(
UUID uuid,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider
) throws UUIDException, IOException {
// 若值为 null则直接写入 null
if (uuid == null) {
jsonGenerator.writeNull();
return;
}
// UUID 写入为字符串
jsonGenerator.writeString(uuid.toUUIDString());
}
/**
* 带类型信息的序列化方法用于支持多态类型处理
*
* @param value 要序列化的 UUID 对象
* @param gen JSON 生成器
* @param serializers 序列化提供者
* @param typeSer 类型序列化器
* @throws IOException 当写入过程中发生 IO 异常时抛出
*/
@Override
public void serializeWithType(
UUID value,
JsonGenerator gen,
SerializerProvider serializers,
TypeSerializer typeSer
) throws IOException {
// 写入类型前缀
WritableTypeId typeId = typeSer.writeTypePrefix(
gen,
typeSer.typeId(value, JsonToken.VALUE_STRING)
);
// 执行实际序列化
serialize(value, gen, serializers);
// 写入类型后缀
typeSer.writeTypeSuffix(gen, typeId);
}
}
}