feat(utils): 添加数组工具类和国际化支持

- 添加ByteArray.toHexString和String.toHexByteArray扩展函数
- 实现多种数组类型的copyTo和copyFrom扩展方法
- 在AutoConfiguration中集成I18N国际化功能
- 添加AutoService注解及处理器用于自动服务注册
- 新增BadGatewayException HTTP状态异常类
- 更新启动横幅格式并添加国际化文本支持
This commit is contained in:
Armamem0t 2026-02-08 03:17:14 +08:00
parent a5a532bc82
commit 1173e979f4
Signed by: minglipro
GPG Key ID: 5F355A77B22AA93B
93 changed files with 4271 additions and 1292 deletions

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils
* CurrentFile build.gradle.kts
* LastUpdate 2026-02-05 11:04:04
* LastUpdate 2026-02-08 03:14:06
* UpdateUser MingLiPro
*/
@ -31,6 +31,7 @@ plugins {
`maven-publish`
kotlin("jvm") version "2.2.20"
id("org.jetbrains.dokka") version "2.0.0"
kotlin("kapt") version "2.2.20"
}
val GROUPSID = project.properties["GROUPSID"] as String
val VERSIONS = project.properties["VERSIONS"] as String
@ -72,12 +73,15 @@ dependencies {
implementation("org.slf4j:slf4j-api:2.0.17")
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
implementation(kotlin("reflect"))
compileOnly("org.mindrot:jbcrypt:0.4")
compileOnly("com.squareup.okhttp3:okhttp:5.3.2")
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.21.0")
compileOnly("com.fasterxml.jackson.module:jackson-module-kotlin:2.21.0")
compileOnly("org.springframework.boot:spring-boot-starter-web:2.7.18")
compileOnly("com.google.code.gson:gson:2.13.2")
compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("io.netty:netty-all:4.1.130.Final")
compileOnly("com.baomidou:mybatis-plus-core:3.5.15")
@ -87,6 +91,7 @@ dependencies {
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
// testImplementation("com.squareup.okhttp3:okhttp:5.3.2")
testImplementation("com.mingliqiye.logger:logger-log4j2:1.0.5")
testImplementation("com.google.code.gson:gson:2.13.2")
testImplementation("com.fasterxml.jackson.core:jackson-databind:2.21.0")
testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.21.0")
}
@ -103,6 +108,15 @@ tasks.withType<JavaExec>().configureEach {
)
}
kapt {
arguments {
arg(
"kapt.kotlin.generated",
project.layout.buildDirectory.dir("generated/source/kapt/main").get().asFile.absolutePath
)
}
}
tasks.withType<org.gradle.jvm.tasks.Jar> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from("LICENSE") { into("META-INF") }
@ -213,7 +227,7 @@ tasks.build {
tasks.processResources {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
outputs.upToDateWhen { false }
filesMatching("META-INF/meta-data") {
filesMatching(listOf("META-INF/meta-data", "fabric.mod.json")) {
expand(
project.properties + mapOf(
"buildTime" to LocalDateTime.now().format(

View File

@ -16,13 +16,13 @@
# ProjectName mingli-utils
# ModuleName mingli-utils
# CurrentFile gradle.properties
# LastUpdate 2026-02-05 11:06:50
# LastUpdate 2026-02-08 03:15:06
# UpdateUser MingLiPro
#
JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils
VERSIONS=4.6.0
VERSIONS=4.6.4
signing.keyId=B22AA93B
signing.password=
signing.secretKeyRingFile=secret.gpg

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils
* CurrentFile settings.gradle.kts
* LastUpdate 2025-09-16 12:32:52
* LastUpdate 2026-02-07 17:00:59
* UpdateUser MingLiPro
*/

View File

@ -0,0 +1,41 @@
/*
* Copyright 2026 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 AutoService.kt
* LastUpdate 2026-02-07 17:00:39
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
import kotlin.reflect.KClass
/**
* 标记一个类为其提供自动服务注册功能的注解
*
* 此注解用于标识那些需要被自动注册为服务的类通过指定[value]参数
* 可以声明该类实现的服务接口类型注解的作用范围限定为类CLASS
* 并且仅在源码级别保留SOURCE不会编译到字节码中
* @since 4.6.3
*
* @param value 需要注册的服务接口类型数组默认为空数组
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class AutoService(
val value: Array<KClass<*>> = []
)

View File

@ -16,12 +16,21 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile DateTimeJsonFormat.kt
* LastUpdate 2026-02-04 22:14:47
* LastUpdate 2026-02-07 08:05:39
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.time
package com.mingliqiye.utils.annotation
import com.mingliqiye.utils.time.Formatter
/**
* 日期时间JSON格式化注解用于标注字段的日期时间格式化方式
*
* @property value 格式化器类型默认为NONE
* @property formatter 自定义格式化字符串默认为空字符串
* @property repcZero 是否替换零值默认为true
*/
@Target(AnnotationTarget.FIELD)
annotation class DateTimeJsonFormat(
val value: Formatter = Formatter.NONE,

View File

@ -0,0 +1,31 @@
/*
* Copyright 2026 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 TestAnnotation.kt
* LastUpdate 2026-02-07 08:44:25
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
annotation class TestAnnotation(val value: String = "test")
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.SOURCE)
annotation class TestFieldAnnotation(val required: Boolean = true)

View File

@ -16,14 +16,21 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUIDJsonFormat.kt
* LastUpdate 2026-02-04 22:14:47
* LastUpdate 2026-02-07 08:05:58
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.uuid
package com.mingliqiye.utils.annotation
import com.mingliqiye.utils.base.BaseType
import com.mingliqiye.utils.uuid.UUIDFormatType
/**
* UUID JSON格式化注解用于指定UUID字段在JSON序列化/反序列化时的格式
*
* @property value UUID格式类型默认为 NO_UPPER_SPACE
* @property base 基数类型默认为 BASE16
*/
@Target(AnnotationTarget.FIELD)
annotation class UUIDJsonFormat(
val value: UUIDFormatType = UUIDFormatType.NO_UPPER_SPACE,

View File

@ -0,0 +1,105 @@
/*
* Copyright 2026 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 AutoServiceProcessor.kt
* LastUpdate 2026-02-08 01:24:16
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.annotation.processor
import com.mingliqiye.utils.annotation.AutoService
import com.mingliqiye.utils.io.IO.println
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.annotation.processing.SupportedAnnotationTypes
import javax.lang.model.element.TypeElement
import javax.lang.model.type.MirroredTypesException
import javax.lang.model.type.TypeMirror
import javax.tools.StandardLocation
@SupportedAnnotationTypes("com.mingliqiye.utils.annotation.AutoService")
class AutoServiceProcessor : AbstractProcessor() {
override fun init(processingEnv: ProcessingEnvironment) {
super.init(processingEnv)
}
override fun process(
annotations: Set<TypeElement>,
roundEnv: RoundEnvironment
): Boolean {
val service = mutableMapOf<String, MutableList<String>>()
val elements = roundEnv.getElementsAnnotatedWith(AutoService::class.java)
if (elements.isEmpty()) return false
for (element in elements) {
val autoServiceAnnotation = element.getAnnotation(AutoService::class.java)
var asd = (try {
autoServiceAnnotation!!.value.map { it.java.name }
} catch (e: MirroredTypesException) {
e.typeMirrors.map(TypeMirror::toString)
})
if (asd.isEmpty()) {
if (element is TypeElement) {
asd = element.interfaces.map { it.toString() }
}
}
for (data in asd) {
var ldata: MutableList<String>? = service[data]
if (ldata == null) {
ldata = mutableListOf()
service[data] = ldata
}
ldata.add(element.toString())
}
}
processClassAnnotation(service)
return true
}
fun processClassAnnotation(map: Map<String, MutableList<String>>) {
map.forEach { (interfaceName, implementations) ->
if (implementations.isEmpty()) {
println("警告: $interfaceName 的实现列表为空!")
return@forEach
}
try {
val serviceFile = processingEnv.filer.createResource(
StandardLocation.CLASS_OUTPUT,
"",
"META-INF/services/$interfaceName"
)
val content = StringBuilder()
serviceFile.openWriter().use { writer ->
implementations.forEach { impl ->
val line = "$impl\n"
content.append(line)
writer.write(line)
}
writer.flush()
}
} catch (e: Exception) {
println("文件创建失败: ${e.javaClass.name} - ${e.message}")
e.printStackTrace()
}
}
}
}

View File

@ -16,373 +16,327 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile ArrayUtils.kt
* LastUpdate 2026-01-28 08:03:28
* LastUpdate 2026-02-06 14:01:56
* UpdateUser MingLiPro
*/
@file:JvmName("ArrayUtils")
package com.mingliqiye.utils.array
import com.mingliqiye.utils.base.BASE16
/**
* 复制数组元素到目标数组
* @param from 源数组
* @param to 目标数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* 将字节数组转换为十六进制字符串
*
* @return 大写的十六进制字符串每两个字符表示一个字节
* @since 4.6.0
* @see toHexByteArray
*/
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun <T> arrayCopy(from: Array<T>, to: Array<T>, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
fun ByteArray.toHexString(): String = BASE16.encode(this).uppercase()
/**
* 将十六进制字符串转换为字节数组
*
* @return 对应的字节数组
* @throws IllegalArgumentException 如果字符串包含非十六进制字符
* @since 4.6.0
* @see toHexString
*/
fun String.toHexByteArray(): ByteArray = BASE16.decode(this.lowercase())
/* ==================== 数组复制扩展函数 ==================== */
/**
* 将当前数组的指定范围复制到目标数组
*
* @param dest 目标数组
* @param srcPos 源数组起始位置包含
* @param distPos 目标数组起始位置包含
* @param len 要复制的元素数量
* @return 源数组自身支持链式调用
* @throws IndexOutOfBoundsException 如果索引超出范围
* @throws IllegalArgumentException 如果参数无效
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun <T> Array<T>.copyTo(dest: Array<T>, srcPos: Int, distPos: Int, len: Int): Array<T> = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 扩展函数将当前数组元素复制到目标数组
* @param to 目标数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* 创建新数组并复制当前数组的指定范围
*
* @param srcPos 源数组起始位置包含
* @param distPos 目标数组起始位置包含
* @param len 要复制的元素数量也作为新数组的长度
* @return 新创建的数组
* @throws IndexOutOfBoundsException 如果索引超出范围
* @since 4.6.2
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun <T> Array<T>.copyTo(to: Array<T>, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
@JvmName("arrayCopy")
fun <T> Array<T>.copyTo(srcPos: Int, distPos: Int, len: Int): Array<T> =
java.lang.reflect.Array.newInstance(this.javaClass.componentType, len).also {
System.arraycopy(this, srcPos, it, distPos, len)
}.let {
@Suppress("UNCHECKED_CAST")
it as Array<T>
}
/**
* 将源数组的指定范围复制到当前数组
*
* @param src 源数组
* @param srcPos 源数组起始位置包含
* @param distPos 当前数组起始位置包含
* @param len 要复制的元素数量
* @return 当前数组自身支持链式调用
* @throws IndexOutOfBoundsException 如果索引超出范围
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun <T> Array<T>.copyFrom(src: Array<T>, srcPos: Int, distPos: Int, len: Int): Array<T> = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== BooleanArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun BooleanArray.copyTo(dest: BooleanArray, srcPos: Int, distPos: Int, len: Int): BooleanArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制整个数组到目标数组重载版本
* @param from 源数组
* @param to 目标数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun <T> arrayCopy(from: Array<T>, to: Array<T>) {
return arrayCopy(from, to, 0, 0, from.size)
@JvmName("arrayCopy")
fun BooleanArray.copyTo(srcPos: Int, distPos: Int, len: Int): BooleanArray =
BooleanArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun BooleanArray.copyFrom(src: BooleanArray, srcPos: Int, distPos: Int, len: Int): BooleanArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== ByteArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun ByteArray.copyTo(dest: ByteArray, srcPos: Int, distPos: Int, len: Int): ByteArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制字节数组元素到目标数组
* @param from 源字节数组
* @param to 目标字节数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: ByteArray, to: ByteArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
@JvmName("arrayCopy")
fun ByteArray.copyTo(srcPos: Int, distPos: Int, len: Int): ByteArray =
ByteArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun ByteArray.copyFrom(src: ByteArray, srcPos: Int, distPos: Int, len: Int): ByteArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== CharArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun CharArray.copyTo(dest: CharArray, srcPos: Int, distPos: Int, len: Int): CharArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 扩展函数将当前字节数组元素复制到目标数组
* @param to 目标字节数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun ByteArray.copyTo(to: ByteArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
@JvmName("arrayCopy")
fun CharArray.copyTo(srcPos: Int, distPos: Int, len: Int): CharArray =
CharArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun CharArray.copyFrom(src: CharArray, srcPos: Int, distPos: Int, len: Int): CharArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== DoubleArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun DoubleArray.copyTo(dest: DoubleArray, srcPos: Int, distPos: Int, len: Int): DoubleArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制整个字节数组到目标数组重载版本
* @param from 源字节数组
* @param to 目标字节数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: ByteArray, to: ByteArray) {
arrayCopy(from, to, 0, 0, from.size)
@JvmName("arrayCopy")
fun DoubleArray.copyTo(srcPos: Int, distPos: Int, len: Int): DoubleArray =
DoubleArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun DoubleArray.copyFrom(src: DoubleArray, srcPos: Int, distPos: Int, len: Int): DoubleArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== FloatArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun FloatArray.copyTo(dest: FloatArray, srcPos: Int, distPos: Int, len: Int): FloatArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制短整型数组元素到目标数组
* @param from 源短整型数组
* @param to 目标短整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: ShortArray, to: ShortArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
@JvmName("arrayCopy")
fun FloatArray.copyTo(srcPos: Int, distPos: Int, len: Int): FloatArray =
FloatArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun FloatArray.copyFrom(src: FloatArray, srcPos: Int, distPos: Int, len: Int): FloatArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== IntArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun IntArray.copyTo(dest: IntArray, srcPos: Int, distPos: Int, len: Int): IntArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 扩展函数将当前短整型数组元素复制到目标数组
* @param to 目标短整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun ShortArray.copyTo(to: ShortArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
@JvmName("arrayCopy")
fun IntArray.copyTo(srcPos: Int, distPos: Int, len: Int): IntArray =
IntArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun IntArray.copyFrom(src: IntArray, srcPos: Int, distPos: Int, len: Int): IntArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== LongArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun LongArray.copyTo(dest: LongArray, srcPos: Int, distPos: Int, len: Int): LongArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制整个短整型数组到目标数组重载版本
* @param from 源短整型数组
* @param to 目标短整型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: ShortArray, to: ShortArray) {
arrayCopy(from, to, 0, 0, from.size)
@JvmName("arrayCopy")
fun LongArray.copyTo(srcPos: Int, distPos: Int, len: Int): LongArray =
LongArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmName("arrayCopyFrom")
fun LongArray.copyFrom(src: LongArray, srcPos: Int, distPos: Int, len: Int): LongArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}
/* ==================== ShortArray 扩展 ==================== */
/**
* @see Array.copyTo
* @since 4.6.0
*/
@JvmName("arrayCopy")
fun ShortArray.copyTo(dest: ShortArray, srcPos: Int, distPos: Int, len: Int): ShortArray = this.also {
System.arraycopy(this, srcPos, dest, distPos, len)
}
/**
* 复制整型数组元素到目标数组
* @param from 源整型数组
* @param to 目标整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @see Array.copyTo
* @since 4.6.2
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: IntArray, to: IntArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
}
@JvmName("arrayCopy")
fun ShortArray.copyTo(srcPos: Int, distPos: Int, len: Int): ShortArray =
ShortArray(len).also { newArray ->
System.arraycopy(this, srcPos, newArray, distPos, len)
}
/**
* 扩展函数将当前整型数组元素复制到目标数组
* @param to 目标整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
* @see Array.copyFrom
* @since 4.6.1
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun IntArray.copyTo(to: IntArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个整型数组到目标数组重载版本
* @param from 源整型数组
* @param to 目标整型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: IntArray, to: IntArray) {
arrayCopy(from, to, 0, 0, from.size)
}
/**
* 复制长整型数组元素到目标数组
* @param from 源长整型数组
* @param to 目标长整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: LongArray, to: LongArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
}
/**
* 扩展函数将当前长整型数组元素复制到目标数组
* @param to 目标长整型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun LongArray.copyTo(to: LongArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个长整型数组到目标数组重载版本
* @param from 源长整型数组
* @param to 目标长整型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: LongArray, to: LongArray) {
arrayCopy(from, to, 0, 0, from.size)
}
/**
* 复制浮点型数组元素到目标数组
* @param from 源浮点型数组
* @param to 目标浮点型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: FloatArray, to: FloatArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
}
/**
* 扩展函数将当前浮点型数组元素复制到目标数组
* @param to 目标浮点型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun FloatArray.copyTo(to: FloatArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个浮点型数组到目标数组重载版本
* @param from 源浮点型数组
* @param to 目标浮点型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: FloatArray, to: FloatArray) {
arrayCopy(from, to, 0, 0, from.size)
}
/**
* 复制双精度浮点型数组元素到目标数组
* @param from 源双精度浮点型数组
* @param to 目标双精度浮点型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: DoubleArray, to: DoubleArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
}
/**
* 扩展函数将当前双精度浮点型数组元素复制到目标数组
* @param to 目标双精度浮点型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun DoubleArray.copyTo(to: DoubleArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个双精度浮点型数组到目标数组重载版本
* @param from 源双精度浮点型数组
* @param to 目标双精度浮点型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: DoubleArray, to: DoubleArray) {
arrayCopy(from, to, 0, 0, from.size)
}
/**
* 复制布尔型数组元素到目标数组
* @param from 源布尔型数组
* @param to 目标布尔型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(
from: BooleanArray, to: BooleanArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos
) {
System.arraycopy(from, fromPos, to, toPos, length)
}
/**
* 扩展函数将当前布尔型数组元素复制到目标数组
* @param to 目标布尔型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun BooleanArray.copyTo(to: BooleanArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个布尔型数组到目标数组重载版本
* @param from 源布尔型数组
* @param to 目标布尔型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: BooleanArray, to: BooleanArray) {
arrayCopy(from, to, 0, 0, from.size)
}
/**
* 复制字符型数组元素到目标数组
* @param from 源字符型数组
* @param to 目标字符型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: CharArray, to: CharArray, fromPos: Int = 0, toPos: Int = 0, length: Int = from.size - fromPos) {
System.arraycopy(from, fromPos, to, toPos, length)
}
/**
* 扩展函数将当前字符型数组元素复制到目标数组
* @param to 目标字符型数组
* @param fromPos 源数组起始位置默认为0
* @param toPos 目标数组起始位置默认为0
* @param length 要复制的元素数量默认为源数组从起始位置到末尾的长度
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
* @throws ArrayStoreException 当类型不匹配时抛出
*/
@JvmSynthetic
@Throws(IndexOutOfBoundsException::class, ArrayStoreException::class)
fun CharArray.copyTo(to: CharArray, fromPos: Int = 0, toPos: Int = 0, length: Int = this.size - fromPos) {
System.arraycopy(this, fromPos, to, toPos, length)
}
/**
* 复制整个字符型数组到目标数组重载版本
* @param from 源字符型数组
* @param to 目标字符型数组
* @throws IndexOutOfBoundsException 当索引超出数组边界时抛出
*/
@Throws(IndexOutOfBoundsException::class)
fun arrayCopy(from: CharArray, to: CharArray) {
arrayCopy(from, to, 0, 0, from.size)
@JvmName("arrayCopyFrom")
fun ShortArray.copyFrom(src: ShortArray, srcPos: Int, distPos: Int, len: Int): ShortArray = this.also {
System.arraycopy(src, srcPos, this, distPos, len)
}

View File

@ -0,0 +1,68 @@
/*
* Copyright 2026 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 Base10.kt
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.base
import java.math.BigInteger
internal class Base10 : BaseCodec {
/**
* 将字节数组编码为Base10字符串十进制
*
* @param bytes 需要编码的字节数组
* @return 编码后的Base10字符串十进制数字
*/
override fun encode(bytes: ByteArray): String {
if (bytes.isEmpty()) return "0"
// 将字节数组转换为正的大整数
val bigInt = BigInteger(1, bytes) // 参数1表示正数
return bigInt.toString(10) // 转换为10进制字符串
}
/**
* 将Base10字符串解码为字节数组
*
* @param string 需要解码的Base10字符串十进制数字
* @return 解码后的字节数组
*/
override fun decode(string: String): ByteArray {
// 验证输入是否为有效的十进制数字
if (!string.matches(Regex("\\d+"))) {
throw IllegalArgumentException("Base10字符串只能包含数字0-9")
}
val bigInt = BigInteger(string, 10) // 从10进制解析
// 转换为字节数组,并确保保留前导零
var byteArray = bigInt.toByteArray()
// BigInteger.toByteArray() 可能会添加一个符号字节
// 对于正数如果第一个字节是0需要移除它
if (byteArray.isNotEmpty() && byteArray[0] == 0.toByte()) {
byteArray = byteArray.copyOfRange(1, byteArray.size)
}
return byteArray
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base16.kt
* LastUpdate 2025-09-17 10:56:07
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
@ -26,7 +26,7 @@ package com.mingliqiye.utils.base
* Base16编解码器实现类
* 提供字节数组与十六进制字符串之间的相互转换功能
*/
class Base16 : BaseCodec {
internal class Base16 : BaseCodec {
/**
* 将字节数组编码为十六进制字符串
* @param bytes 待编码的字节数组

View File

@ -0,0 +1,59 @@
/*
* Copyright 2026 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 Base2.kt
* LastUpdate 2026-02-08 03:06:23
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.base
internal class Base2 : BaseCodec {
override fun encode(bytes: ByteArray): String {
if (bytes.isEmpty()) return ""
val result = StringBuilder()
for ((index, byte) in bytes.withIndex()) {
val unsignedByte = byte.toInt() and 0xFF
val binary = unsignedByte.toString(2).padStart(8, '0')
result.append(binary)
}
return result.toString()
}
override fun decode(string: String): ByteArray {
if (string.length % 8 != 0) {
throw IllegalArgumentException(
"BASE1字符串长度必须是8的倍数当前长度: ${string.length}"
)
}
if (!string.matches(Regex("[01]+"))) {
throw IllegalArgumentException(
"BASE1字符串只能包含字符'0'和'1'"
)
}
val byteCount = string.length / 8
val result = ByteArray(byteCount)
for (i in 0 until byteCount) {
val startIndex = i * 8
val endIndex = startIndex + 8
val binaryStr = string.substring(startIndex, endIndex)
val byteValue = binaryStr.toInt(2)
result[i] = byteValue.toByte()
}
return result
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base256.kt
* LastUpdate 2025-09-20 14:01:29
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
@ -30,7 +30,7 @@ package com.mingliqiye.utils.base
* !#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~§±×÷
*
*/
class Base256 : BaseCodec {
internal class Base256 : BaseCodec {
companion object {
val code = arrayOf(

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base64.kt
* LastUpdate 2025-09-17 10:56:32
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
@ -26,7 +26,7 @@ package com.mingliqiye.utils.base
* Base64编解码工具类
* 提供Base64编码和解码功能的实现
*/
class Base64 : BaseCodec {
internal class Base64 : BaseCodec {
/*
* Base64编码器实例

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Base91.kt
* LastUpdate 2025-09-19 20:08:46
* LastUpdate 2026-02-08 03:08:10
* UpdateUser MingLiPro
*/
@ -27,7 +27,7 @@ package com.mingliqiye.utils.base
*
* Base91 是一种高效的二进制到文本的编码方式相较于 Base64它使用更少的字符来表示相同的数据
*/
class Base91 : BaseCodec {
internal class Base91 : BaseCodec {
companion object {
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2025 mingliqiye
* Copyright 2026 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseUtils.kt
* LastUpdate 2025-09-19 20:18:09
* LastUpdate 2026-02-08 03:00:37
* UpdateUser MingLiPro
*/
@ -24,40 +24,49 @@
package com.mingliqiye.utils.base
/**
* Base64编解码器实例
* 使用懒加载方式初始化Base64编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE64: BaseCodec by lazy {
Base64()
}
/**
* Base91编解码器实例
* 使用懒加载方式初始化Base91编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE91: BaseCodec by lazy {
Base91()
}
/**
* Base91编解码器实例
* 使用懒加载方式初始化Base91编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE16: BaseCodec by lazy {
Base16()
}
/**
* Base256编解码器实例
* 使用懒加载方式初始化Base256编解码器对象
* 保证线程安全且只在首次访问时创建实例
*/
val BASE256: BaseCodec by lazy {
Base256()
}
import com.mingliqiye.utils.base.code.Base10
import com.mingliqiye.utils.base.code.Base16
import com.mingliqiye.utils.base.code.Base256
import com.mingliqiye.utils.base.code.Base64
import com.mingliqiye.utils.base.code.Base91
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base10", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE10: BaseCodec
get() = Base10
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base16", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE16: BaseCodec
get() = Base16
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base64", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE64: BaseCodec
get() = Base64
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base91", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE91: BaseCodec
get() = Base91
@Deprecated(
"重命名", replaceWith = ReplaceWith(
expression = "Base256", imports = ["com.mingliqiye.utils.base.code"]
)
)
val BASE256: BaseCodec
get() = Base256

View File

@ -0,0 +1,81 @@
/*
* Copyright 2026 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 BaseCodes.kt
* LastUpdate 2026-02-08 03:10:03
* UpdateUser MingLiPro
*/
@file:JvmName("BaseCodes")
package com.mingliqiye.utils.base.code
import com.mingliqiye.utils.base.*
/**
* 提供Base2编码器的懒加载实例
* 该编码器用于将数据编码为二进制格式
*/
@get:JvmName("Base2")
val Base2: BaseCodec by lazy {
Base2()
}
/**
* 提供Base10编码器的懒加载实例
* 该编码器用于将数据编码为十进制格式
*/
@get:JvmName("Base10")
val Base10: BaseCodec by lazy {
Base10()
}
/**
* 提供Base16编码器的懒加载实例
* 该编码器用于将数据编码为十六进制格式
*/
@get:JvmName("Base16")
val Base16: BaseCodec by lazy {
Base16()
}
/**
* 提供Base64编码器的懒加载实例
* 该编码器用于将数据编码为Base64格式常用于URL安全传输或存储
*/
@get:JvmName("Base64")
val Base64: BaseCodec by lazy {
Base64()
}
/**
* 提供Base91编码器的懒加载实例
* 该编码器用于将数据编码为Base91格式具有较高的压缩效率
*/
@get:JvmName("Base91")
val Base91: BaseCodec by lazy {
Base91()
}
/**
* 提供Base256编码器的懒加载实例
* 该编码器用于将数据编码为Base256格式适用于字节级数据处理
*/
@get:JvmName("Base256")
val Base256: BaseCodec by lazy {
Base256()
}

View File

@ -16,15 +16,15 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile CloneUtils.kt
* LastUpdate 2026-02-04 21:00:48
* LastUpdate 2026-02-05 14:41:27
* UpdateUser MingLiPro
*/
@file:JvmName("CloneUtils")
package com.mingliqiye.utils.clone
import com.mingliqiye.utils.exception.JsonException
import com.mingliqiye.utils.json.api.base.JsonApi
import com.mingliqiye.utils.json.api.exception.JsonException
import java.io.*

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 BadGatewayException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 502 Bad Gateway 异常
*
* @param message 异常信息默认为 "Bad Gateway"
* @param cause 异常原因默认为 null
*/
class BadGatewayException(
override val message: String? = "Bad Gateway",
override val cause: Throwable? = null,
) : HttpStatusException(502, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 BadRequestException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 400 Bad Request 异常
*
* @param message 异常信息默认为 "Bad Request"
* @param cause 异常原因默认为 null
*/
class BadRequestException(
override val message: String? = "Bad Request",
override val cause: Throwable? = null,
) : HttpStatusException(400, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 ConflictException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 409 Conflict 异常
*
* @param message 异常信息默认为 "Conflict"
* @param cause 异常原因默认为 null
*/
class ConflictException(
override val message: String? = "Conflict",
override val cause: Throwable? = null,
) : HttpStatusException(409, message, cause)

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 EmptyJsonException.kt
* LastUpdate 2026-02-07 14:45:12
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class EmptyJsonException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 ForbiddenException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 403 Forbidden 异常
*
* @param message 异常信息默认为 "Forbidden"
* @param cause 异常原因默认为 null
*/
class ForbiddenException(
override val message: String? = "Forbidden",
override val cause: Throwable? = null,
) : HttpStatusException(403, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 FoundException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 302 Found 异常
*
* @param message 异常信息默认为 "Found"
* @param cause 异常原因默认为 null
*/
class FoundException(
override val message: String? = "Found",
override val cause: Throwable? = null,
) : HttpStatusException(302, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 GatewayTimeoutException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 504 Gateway Timeout 异常
*
* @param message 异常信息默认为 "Gateway Timeout"
* @param cause 异常原因默认为 null
*/
class GatewayTimeoutException(
override val message: String? = "Gateway Timeout",
override val cause: Throwable? = null,
) : HttpStatusException(504, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 GoneException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 410 Gone 异常
*
* @param message 异常信息默认为 "Gone"
* @param cause 异常原因默认为 null
*/
class GoneException(
override val message: String? = "Gone",
override val cause: Throwable? = null,
) : HttpStatusException(410, message, cause)

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 HttpException.kt
* LastUpdate 2026-02-05 14:44:15
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class HttpException : MingLiUtilsBaseException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 HttpStatusException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 异常的基类继承自 [RuntimeException]
*
* @param statusCode HTTP 状态码
* @param message 异常信息默认为 null
* @param cause 异常原因默认为 null
*/
sealed class HttpStatusException(
open val statusCode: Int,
override val message: String? = null,
override val cause: Throwable? = null
) : MingLiUtilsBaseException(message, cause)

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 HttpUrlException.kt
* LastUpdate 2026-02-05 15:21:48
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class HttpUrlException : HttpException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 HttpVersionNotSupportedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 505 HTTP Version Not Supported 异常
*
* @param message 异常信息默认为 "HTTP Version Not Supported"
* @param cause 异常原因默认为 null
*/
class HttpVersionNotSupportedException(
override val message: String? = "HTTP Version Not Supported",
override val cause: Throwable? = null,
) : HttpStatusException(505, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 InternalServerErrorException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 500 Internal Server Error 异常
*
* @param message 异常信息默认为 "Internal Server Error"
* @param cause 异常原因默认为 null
*/
class InternalServerErrorException(
override val message: String? = "Internal Server Error",
override val cause: Throwable? = null,
) : HttpStatusException(500, message, cause)

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 InvalidJsonException.kt
* LastUpdate 2026-02-07 13:18:32
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class InvalidJsonException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -16,11 +16,11 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonException.kt
* LastUpdate 2026-02-05 11:12:36
* LastUpdate 2026-02-07 13:17:50
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.api.exception
package com.mingliqiye.utils.exception
/**
* 自定义异常类用于处理 JSON 相关操作中出现的错误
@ -30,27 +30,15 @@ package com.mingliqiye.utils.json.api.exception
* 2. 包含错误信息和原因Throwable的构造函数
* 3. 仅包含原因Throwable的构造函数
*/
class JsonException : RuntimeException {
/**
* 构造函数创建一个带有指定错误信息的 [JsonException] 实例
*
* @param message 错误信息描述
*/
open class JsonException : MingLiUtilsBaseException {
constructor()
constructor(message: String) : super(message)
/**
* 构造函数创建一个带有指定错误信息和原因的 [JsonException] 实例
*
* @param message 错误信息描述
* @param cause 导致此异常的根本原因
*/
constructor(message: String, cause: Throwable) : super(message, cause)
/**
* 构造函数创建一个由指定原因引发的 [JsonException] 实例
*
* @param cause 导致此异常的根本原因
*/
constructor(cause: Throwable) : super(cause)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 JsonObjectCastException.kt
* LastUpdate 2026-02-07 15:11:42
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonObjectCastException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 JsonParserException.kt
* LastUpdate 2026-02-07 14:45:12
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonParserException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2026 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 JsonTypeException.kt
* LastUpdate 2026-02-07 13:28:02
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
class JsonTypeException : JsonException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 LengthRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 411 Length Required 异常
*
* @param message 异常信息默认为 "Length Required"
* @param cause 异常原因默认为 null
*/
class LengthRequiredException(
override val message: String? = "Length Required",
override val cause: Throwable? = null,
) : HttpStatusException(411, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 MethodNotAllowedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 405 Method Not Allowed 异常
*
* @param message 异常信息默认为 "Method Not Allowed"
* @param cause 异常原因默认为 null
*/
class MethodNotAllowedException(
override val message: String? = "Method Not Allowed",
override val cause: Throwable? = null,
) : HttpStatusException(405, message, cause)

View File

@ -0,0 +1,37 @@
/*
* Copyright 2026 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 MingLiUtilsBaseException.kt
* LastUpdate 2026-02-05 14:41:27
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
open class MingLiUtilsBaseException : RuntimeException {
constructor()
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(throwable)
constructor(message: String, throwable: Throwable) : super(message, throwable)
constructor(
message: String? = null,
throwable: Throwable? = null,
enableSuppression: Boolean = false,
writableStackTrace: Boolean = false
) : super(message, throwable, enableSuppression, writableStackTrace)
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 MovedPermanentlyException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 301 Moved Permanently 异常
*
* @param message 异常信息默认为 "Moved Permanently"
* @param cause 异常原因默认为 null
*/
class MovedPermanentlyException(
override val message: String? = "Moved Permanently",
override val cause: Throwable? = null,
) : HttpStatusException(301, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 MultipleChoicesException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 300 Multiple Choices 异常
*
* @param message 异常信息默认为 "Multiple Choices"
* @param cause 异常原因默认为 null
*/
class MultipleChoicesException(
override val message: String? = "Multiple Choices",
override val cause: Throwable? = null,
) : HttpStatusException(300, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 NotAcceptableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 406 Not Acceptable 异常
*
* @param message 异常信息默认为 "Not Acceptable"
* @param cause 异常原因默认为 null
*/
class NotAcceptableException(
override val message: String? = "Not Acceptable",
override val cause: Throwable? = null,
) : HttpStatusException(406, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 NotFoundException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 404 Not Found 异常
*
* @param message 异常信息默认为 "Not Found"
* @param cause 异常原因默认为 null
*/
class NotFoundException(
override val message: String? = "Not Found",
override val cause: Throwable? = null,
) : HttpStatusException(404, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 NotImplementedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 501 Not Implemented 异常
*
* @param message 异常信息默认为 "Not Implemented"
* @param cause 异常原因默认为 null
*/
class NotImplementedException(
override val message: String? = "Not Implemented",
override val cause: Throwable? = null,
) : HttpStatusException(501, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 NotModifiedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 304 Not Modified 异常
*
* @param message 异常信息默认为 "Not Modified"
* @param cause 异常原因默认为 null
*/
class NotModifiedException(
override val message: String? = "Not Modified",
override val cause: Throwable? = null,
) : HttpStatusException(304, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 PaymentRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 402 Payment Required 异常
*
* @param message 异常信息默认为 "Payment Required"
* @param cause 异常原因默认为 null
*/
class PaymentRequiredException(
override val message: String? = "Payment Required",
override val cause: Throwable? = null,
) : HttpStatusException(402, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 PreconditionFailedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 412 Precondition Failed 异常
*
* @param message 异常信息默认为 "Precondition Failed"
* @param cause 异常原因默认为 null
*/
class PreconditionFailedException(
override val message: String? = "Precondition Failed",
override val cause: Throwable? = null,
) : HttpStatusException(412, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 ProxyAuthenticationRequiredException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 407 Proxy Authentication Required 异常
*
* @param message 异常信息默认为 "Proxy Authentication Required"
* @param cause 异常原因默认为 null
*/
class ProxyAuthenticationRequiredException(
override val message: String? = "Proxy Authentication Required",
override val cause: Throwable? = null,
) : HttpStatusException(407, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 RequestEntityTooLargeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 413 Request Entity Too Large 异常
*
* @param message 异常信息默认为 "Request Entity Too Large"
* @param cause 异常原因默认为 null
*/
class RequestEntityTooLargeException(
override val message: String? = "Request Entity Too Large",
override val cause: Throwable? = null,
) : HttpStatusException(413, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 RequestTimeoutException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 408 Request Timeout 异常
*
* @param message 异常信息默认为 "Request Timeout"
* @param cause 异常原因默认为 null
*/
class RequestTimeoutException(
override val message: String? = "Request Timeout",
override val cause: Throwable? = null,
) : HttpStatusException(408, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 RequestUriTooLargeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 414 Request URI Too Large 异常
*
* @param message 异常信息默认为 "Request URI Too Large"
* @param cause 异常原因默认为 null
*/
class RequestUriTooLargeException(
override val message: String? = "Request URI Too Large",
override val cause: Throwable? = null,
) : HttpStatusException(414, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 RequestedRangeNotSatisfiableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 416 Requested Range Not Satisfiable 异常
*
* @param message 异常信息默认为 "Requested Range Not Satisfiable"
* @param cause 异常原因默认为 null
*/
class RequestedRangeNotSatisfiableException(
override val message: String? = "Requested Range Not Satisfiable",
override val cause: Throwable? = null,
) : HttpStatusException(416, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 SeeOtherException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 303 See Other 异常
*
* @param message 异常信息默认为 "See Other"
* @param cause 异常原因默认为 null
*/
class SeeOtherException(
override val message: String? = "See Other",
override val cause: Throwable? = null,
) : HttpStatusException(303, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 ServiceUnavailableException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 503 Service Unavailable 异常
*
* @param message 异常信息默认为 "Service Unavailable"
* @param cause 异常原因默认为 null
*/
class ServiceUnavailableException(
override val message: String? = "Service Unavailable",
override val cause: Throwable? = null,
) : HttpStatusException(503, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 TemporaryRedirectException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 307 Temporary Redirect 异常
*
* @param message 异常信息默认为 "Temporary Redirect"
* @param cause 异常原因默认为 null
*/
class TemporaryRedirectException(
override val message: String? = "Temporary Redirect",
override val cause: Throwable? = null,
) : HttpStatusException(307, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 UnauthorizedException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 401 Unauthorized 异常
*
* @param message 异常信息默认为 "Unauthorized"
* @param cause 异常原因默认为 null
*/
class UnauthorizedException(
override val message: String? = "Unauthorized",
override val cause: Throwable? = null,
) : HttpStatusException(401, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 UnsupportedMediaTypeException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 415 Unsupported Media Type 异常
*
* @param message 异常信息默认为 "Unsupported Media Type"
* @param cause 异常原因默认为 null
*/
class UnsupportedMediaTypeException(
override val message: String? = "Unsupported Media Type",
override val cause: Throwable? = null,
) : HttpStatusException(415, message, cause)

View File

@ -0,0 +1,34 @@
/*
* Copyright 2026 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 UseProxyException.kt
* LastUpdate 2026-02-05 14:55:04
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.exception
/**
* 表示 HTTP 305 Use Proxy 异常
*
* @param message 异常信息默认为 "Use Proxy"
* @param cause 异常原因默认为 null
*/
class UseProxyException(
override val message: String? = "Use Proxy",
override val cause: Throwable? = null,
) : HttpStatusException(305, message, cause)

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Pipeline.kt
* LastUpdate 2026-02-05 09:53:44
* LastUpdate 2026-02-05 15:22:21
* UpdateUser MingLiPro
*/
@ -174,7 +174,7 @@ class Pipeline<T>(private val value: T) {
fun require(
any: Any, message: String
): Pipeline<T> {
Require.require(any == value, message)
Require.RequireLayz.require(any == value, message)
return this
}

View File

@ -16,12 +16,15 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Response.kt
* LastUpdate 2026-02-03 20:09:10
* LastUpdate 2026-02-07 22:18:42
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.http
import com.mingliqiye.utils.annotation.DateTimeJsonFormat
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
import com.mingliqiye.utils.time.DateTime
/**
@ -35,8 +38,13 @@ import com.mingliqiye.utils.time.DateTime
* @property statusCode 状态码
*/
data class Response<T>(
private var time: DateTime, private var message: String, private var data: T?, private var statusCode: Int
private var time: DateTime,
private var message: String,
private var data: T?,
private var statusCode: Int,
) {
private var timeFormat: DateTimeJsonFormat = DateTimeJsonFormat()
companion object {
/**
@ -124,20 +132,22 @@ data class Response<T>(
/**
* 获取响应时间
* 获取格式化后的时间字符串
*
* @return DateTime 响应时间
* @return 格式化后的时间字符串使用 [DateTimeJsonConverter] [timeFormat] 注解进行转换
*/
fun getTime(): DateTime = time
fun getTime(): String =
DateTimeJsonConverter.getJsonConverter().convert(time, AnnotationGetter.oneGetter(timeFormat))!!
/**
* 设置响应时间
* 设置时间字段的值
*
* @param dateTime 响应时间
* @return Response<T> 当前响应对象用于链式调用
* @param dateTime 格式化后的时间字符串将被反序列化为内部时间对象
* @return 返回当前对象实例支持链式调用
*/
fun setTime(dateTime: DateTime): Response<T> {
time = dateTime
fun setTime(dateTime: String): Response<T> {
// 使用 DateTimeJsonConverter 将输入的字符串反序列化为时间对象,并更新内部 time 字段
time = DateTimeJsonConverter.getJsonConverter().deConvert(dateTime, AnnotationGetter.oneGetter(timeFormat))!!
return this
}
@ -250,6 +260,13 @@ data class Response<T>(
return this
}
fun writeTimeFormat(timeFormat: DateTimeJsonFormat): Response<T> {
this.timeFormat = timeFormat
return this
}
fun readTimeFormat(): DateTimeJsonFormat = timeFormat
/**
* 返回响应对象的字符串表示
*/

View File

@ -1,372 +0,0 @@
/*
* Copyright 2026 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 Exceptions.kt
* LastUpdate 2026-02-05 11:12:36
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.http.exception
/**
* 表示 HTTP 异常的基类继承自 [RuntimeException]
*
* @param statusCode HTTP 状态码
* @param message 异常信息默认为 null
* @param cause 异常原因默认为 null
*/
sealed class HttpException(
open val statusCode: Int,
override val message: String? = null,
override val cause: Throwable? = null
) : RuntimeException(message, cause)
// 3xx - 重定向异常
/**
* 表示 HTTP 300 Multiple Choices 异常
*
* @param message 异常信息默认为 "Multiple Choices"
* @param cause 异常原因默认为 null
*/
class MultipleChoicesException(
override val message: String? = "Multiple Choices",
override val cause: Throwable? = null,
) : HttpException(300, message, cause)
/**
* 表示 HTTP 301 Moved Permanently 异常
*
* @param message 异常信息默认为 "Moved Permanently"
* @param cause 异常原因默认为 null
*/
class MovedPermanentlyException(
override val message: String? = "Moved Permanently",
override val cause: Throwable? = null,
) : HttpException(301, message, cause)
/**
* 表示 HTTP 302 Found 异常
*
* @param message 异常信息默认为 "Found"
* @param cause 异常原因默认为 null
*/
class FoundException(
override val message: String? = "Found",
override val cause: Throwable? = null,
) : HttpException(302, message, cause)
/**
* 表示 HTTP 303 See Other 异常
*
* @param message 异常信息默认为 "See Other"
* @param cause 异常原因默认为 null
*/
class SeeOtherException(
override val message: String? = "See Other",
override val cause: Throwable? = null,
) : HttpException(303, message, cause)
/**
* 表示 HTTP 304 Not Modified 异常
*
* @param message 异常信息默认为 "Not Modified"
* @param cause 异常原因默认为 null
*/
class NotModifiedException(
override val message: String? = "Not Modified",
override val cause: Throwable? = null,
) : HttpException(304, message, cause)
/**
* 表示 HTTP 305 Use Proxy 异常
*
* @param message 异常信息默认为 "Use Proxy"
* @param cause 异常原因默认为 null
*/
class UseProxyException(
override val message: String? = "Use Proxy",
override val cause: Throwable? = null,
) : HttpException(305, message, cause)
/**
* 表示 HTTP 307 Temporary Redirect 异常
*
* @param message 异常信息默认为 "Temporary Redirect"
* @param cause 异常原因默认为 null
*/
class TemporaryRedirectException(
override val message: String? = "Temporary Redirect",
override val cause: Throwable? = null,
) : HttpException(307, message, cause)
// 4xx - 客户端错误异常
/**
* 表示 HTTP 400 Bad Request 异常
*
* @param message 异常信息默认为 "Bad Request"
* @param cause 异常原因默认为 null
*/
class BadRequestException(
override val message: String? = "Bad Request",
override val cause: Throwable? = null,
) : HttpException(400, message, cause)
/**
* 表示 HTTP 401 Unauthorized 异常
*
* @param message 异常信息默认为 "Unauthorized"
* @param cause 异常原因默认为 null
*/
class UnauthorizedException(
override val message: String? = "Unauthorized",
override val cause: Throwable? = null,
) : HttpException(401, message, cause)
/**
* 表示 HTTP 402 Payment Required 异常
*
* @param message 异常信息默认为 "Payment Required"
* @param cause 异常原因默认为 null
*/
class PaymentRequiredException(
override val message: String? = "Payment Required",
override val cause: Throwable? = null,
) : HttpException(402, message, cause)
/**
* 表示 HTTP 403 Forbidden 异常
*
* @param message 异常信息默认为 "Forbidden"
* @param cause 异常原因默认为 null
*/
class ForbiddenException(
override val message: String? = "Forbidden",
override val cause: Throwable? = null,
) : HttpException(403, message, cause)
/**
* 表示 HTTP 404 Not Found 异常
*
* @param message 异常信息默认为 "Not Found"
* @param cause 异常原因默认为 null
*/
class NotFoundException(
override val message: String? = "Not Found",
override val cause: Throwable? = null,
) : HttpException(404, message, cause)
/**
* 表示 HTTP 405 Method Not Allowed 异常
*
* @param message 异常信息默认为 "Method Not Allowed"
* @param cause 异常原因默认为 null
*/
class MethodNotAllowedException(
override val message: String? = "Method Not Allowed",
override val cause: Throwable? = null,
) : HttpException(405, message, cause)
/**
* 表示 HTTP 406 Not Acceptable 异常
*
* @param message 异常信息默认为 "Not Acceptable"
* @param cause 异常原因默认为 null
*/
class NotAcceptableException(
override val message: String? = "Not Acceptable",
override val cause: Throwable? = null,
) : HttpException(406, message, cause)
/**
* 表示 HTTP 407 Proxy Authentication Required 异常
*
* @param message 异常信息默认为 "Proxy Authentication Required"
* @param cause 异常原因默认为 null
*/
class ProxyAuthenticationRequiredException(
override val message: String? = "Proxy Authentication Required",
override val cause: Throwable? = null,
) : HttpException(407, message, cause)
/**
* 表示 HTTP 408 Request Timeout 异常
*
* @param message 异常信息默认为 "Request Timeout"
* @param cause 异常原因默认为 null
*/
class RequestTimeoutException(
override val message: String? = "Request Timeout",
override val cause: Throwable? = null,
) : HttpException(408, message, cause)
/**
* 表示 HTTP 409 Conflict 异常
*
* @param message 异常信息默认为 "Conflict"
* @param cause 异常原因默认为 null
*/
class ConflictException(
override val message: String? = "Conflict",
override val cause: Throwable? = null,
) : HttpException(409, message, cause)
/**
* 表示 HTTP 410 Gone 异常
*
* @param message 异常信息默认为 "Gone"
* @param cause 异常原因默认为 null
*/
class GoneException(
override val message: String? = "Gone",
override val cause: Throwable? = null,
) : HttpException(410, message, cause)
/**
* 表示 HTTP 411 Length Required 异常
*
* @param message 异常信息默认为 "Length Required"
* @param cause 异常原因默认为 null
*/
class LengthRequiredException(
override val message: String? = "Length Required",
override val cause: Throwable? = null,
) : HttpException(411, message, cause)
/**
* 表示 HTTP 412 Precondition Failed 异常
*
* @param message 异常信息默认为 "Precondition Failed"
* @param cause 异常原因默认为 null
*/
class PreconditionFailedException(
override val message: String? = "Precondition Failed",
override val cause: Throwable? = null,
) : HttpException(412, message, cause)
/**
* 表示 HTTP 413 Request Entity Too Large 异常
*
* @param message 异常信息默认为 "Request Entity Too Large"
* @param cause 异常原因默认为 null
*/
class RequestEntityTooLargeException(
override val message: String? = "Request Entity Too Large",
override val cause: Throwable? = null,
) : HttpException(413, message, cause)
/**
* 表示 HTTP 414 Request URI Too Large 异常
*
* @param message 异常信息默认为 "Request URI Too Large"
* @param cause 异常原因默认为 null
*/
class RequestUriTooLargeException(
override val message: String? = "Request URI Too Large",
override val cause: Throwable? = null,
) : HttpException(414, message, cause)
/**
* 表示 HTTP 415 Unsupported Media Type 异常
*
* @param message 异常信息默认为 "Unsupported Media Type"
* @param cause 异常原因默认为 null
*/
class UnsupportedMediaTypeException(
override val message: String? = "Unsupported Media Type",
override val cause: Throwable? = null,
) : HttpException(415, message, cause)
/**
* 表示 HTTP 416 Requested Range Not Satisfiable 异常
*
* @param message 异常信息默认为 "Requested Range Not Satisfiable"
* @param cause 异常原因默认为 null
*/
class RequestedRangeNotSatisfiableException(
override val message: String? = "Requested Range Not Satisfiable",
override val cause: Throwable? = null,
) : HttpException(416, message, cause)
// 5xx - 服务器错误异常
/**
* 表示 HTTP 500 Internal Server Error 异常
*
* @param message 异常信息默认为 "Internal Server Error"
* @param cause 异常原因默认为 null
*/
class InternalServerErrorException(
override val message: String? = "Internal Server Error",
override val cause: Throwable? = null,
) : HttpException(500, message, cause)
/**
* 表示 HTTP 501 Not Implemented 异常
*
* @param message 异常信息默认为 "Not Implemented"
* @param cause 异常原因默认为 null
*/
class NotImplementedException(
override val message: String? = "Not Implemented",
override val cause: Throwable? = null,
) : HttpException(501, message, cause)
/**
* 表示 HTTP 502 Bad Gateway 异常
*
* @param message 异常信息默认为 "Bad Gateway"
* @param cause 异常原因默认为 null
*/
class BadGatewayException(
override val message: String? = "Bad Gateway",
override val cause: Throwable? = null,
) : HttpException(502, message, cause)
/**
* 表示 HTTP 503 Service Unavailable 异常
*
* @param message 异常信息默认为 "Service Unavailable"
* @param cause 异常原因默认为 null
*/
class ServiceUnavailableException(
override val message: String? = "Service Unavailable",
override val cause: Throwable? = null,
) : HttpException(503, message, cause)
/**
* 表示 HTTP 504 Gateway Timeout 异常
*
* @param message 异常信息默认为 "Gateway Timeout"
* @param cause 异常原因默认为 null
*/
class GatewayTimeoutException(
override val message: String? = "Gateway Timeout",
override val cause: Throwable? = null,
) : HttpException(504, message, cause)
/**
* 表示 HTTP 505 HTTP Version Not Supported 异常
*
* @param message 异常信息默认为 "HTTP Version Not Supported"
* @param cause 异常原因默认为 null
*/
class HttpVersionNotSupportedException(
override val message: String? = "HTTP Version Not Supported",
override val cause: Throwable? = null,
) : HttpException(505, message, cause)

View File

@ -0,0 +1,964 @@
/*
* Copyright 2026 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 I18N.kt
* LastUpdate 2026-02-05 22:39:07
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.i18n
import com.fasterxml.jackson.databind.ObjectMapper
import org.slf4j.Logger
object I18N {
@JvmStatic
private var _Internationalization: Internationalization = Internationalization(
clazz = I18N::class.java,
objectMapper = ObjectMapper(),
isloadSlef = true
)
fun setInternationalization(value: Internationalization) {
this._Internationalization = value
}
fun getInternationalization() = _Internationalization
@JvmStatic
fun getString(string: String, vararg any: Any): String = _Internationalization.getString(string, *any)
@JvmStatic
fun getString(string: String): String = _Internationalization.getString(string)
@JvmStatic
fun getKeyString(key: String): String = _Internationalization.getKeyString(key)
fun Logger.infoTranslater(string: String, vararg any: Any) = this.info(getString(string, *any))
fun Logger.warnTranslater(string: String, vararg any: Any) = this.warn(getString(string, *any))
fun Logger.debugTranslater(string: String, vararg any: Any) = this.debug(getString(string, *any))
fun Logger.traceTranslater(string: String, vararg any: Any) = this.trace(getString(string, *any))
// 0 个参数
fun Logger.errorTranslater(string: String, any1: Any) {
this.error(getString(string))
}
fun Logger.errorTranslater(string: String) {
this.error(getString(string))
}
// 2 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any) {
this.error(getString(string, any1, any2))
}
// 3 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, any3: Any) {
this.error(getString(string, any1, any2, any3))
}
// 4 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
) {
this.error(getString(string, any1, any2, any3, any4))
}
// 5 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5))
}
// 6 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6))
}
// 7 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7))
}
// 8 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8))
}
// 9 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9))
}
// 10 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10))
}
// 11 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any,
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11))
}
// 12 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any,
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12)
)
}
// 13 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any, any13: Any,
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13),
)
}
// 14 个参数
fun Logger.errorTranslater(
string: String,
any1: Any, any2: Any, any3: Any, any4: Any, any5: Any,
any6: Any, any7: Any, any8: Any, any9: Any, any10: Any, any11: Any, any12: Any, any13: Any, any14: Any,
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14
)
)
}
// 15 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14, any15
)
)
}
// 16 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16
)
)
}
// 17 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17
)
)
}
// 18 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18
)
)
}
// 19 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19
)
)
}
// 20 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
any20: Any,
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19,
any20
)
)
}
fun Logger.errorTranslater(string: String, throwable: Throwable) {
this.error(getString(string), throwable)
}
// 1 个参数
fun Logger.errorTranslater(string: String, any1: Any, throwable: Throwable) {
this.error(getString(string, any1), throwable)
}
// 2 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, throwable: Throwable) {
this.error(getString(string, any1, any2), throwable)
}
// 3 个参数
fun Logger.errorTranslater(string: String, any1: Any, any2: Any, any3: Any, throwable: Throwable) {
this.error(getString(string, any1, any2, any3), throwable)
}
// 4 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4), throwable)
}
// 5 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, any5: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5), throwable)
}
// 6 个参数
fun Logger.errorTranslater(
string: String, any1: Any, any2: Any, any3: Any, any4: Any, any5: Any, any6: Any, throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6), throwable)
}
// 7 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7), throwable)
}
// 8 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8), throwable)
}
// 9 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9), throwable)
}
// 10 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10), throwable)
}
// 11 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
throwable: Throwable
) {
this.error(getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11), throwable)
}
// 12 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
throwable: Throwable
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12), throwable
)
}
// 13 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
throwable: Throwable
) {
this.error(
getString(string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13),
throwable
)
}
// 14 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
throwable: Throwable
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14
), throwable
)
}
// 15 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
throwable: Throwable
) {
this.error(
getString(
string, any1, any2, any3, any4, any5, any6, any7, any8, any9, any10, any11, any12, any13, any14, any15
), throwable
)
}
// 16 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16
), throwable
)
}
// 17 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17
), throwable
)
}
// 18 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18
), throwable
)
}
// 19 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19
), throwable
)
}
// 20 个参数
fun Logger.errorTranslater(
string: String,
any1: Any,
any2: Any,
any3: Any,
any4: Any,
any5: Any,
any6: Any,
any7: Any,
any8: Any,
any9: Any,
any10: Any,
any11: Any,
any12: Any,
any13: Any,
any14: Any,
any15: Any,
any16: Any,
any17: Any,
any18: Any,
any19: Any,
any20: Any,
throwable: Throwable
) {
this.error(
getString(
string,
any1,
any2,
any3,
any4,
any5,
any6,
any7,
any8,
any9,
any10,
any11,
any12,
any13,
any14,
any15,
any16,
any17,
any18,
any19,
any20
), throwable
)
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright 2026 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 Internationalization.kt
* LastUpdate 2026-02-06 08:47:26
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.i18n
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import org.slf4j.Logger
import java.net.URL
import java.util.*
class Internationalization {
var clazz: Class<*>
var objectMapper: ObjectMapper
var locale: Locale
var backLocale: Locale
val langPath: String
val thisName: String
val thisBackName: String
private var log: Logger = MingLiLoggerFactory.getLogger<Internationalization>()
constructor(
clazz: Class<*>,
objectMapper: ObjectMapper,
locale: Locale = Locale.getDefault(),
backLocale: Locale = Locale.US,
langPath: String = "/lang",
isloadSlef: Boolean = false
) {
this.clazz = clazz
this.objectMapper = objectMapper
this.locale = locale
this.backLocale = backLocale
this.langPath = langPath
thisName = getLanguageName(locale)
thisBackName = getLanguageName(backLocale)
readJson("/assets/mingli-utils/lang/${thisName}.json", Internationalization::class.java, thisName)
if (!isloadSlef) {
if (!readJson(fileName = "$langPath/${thisName}.json", lang = thisName)) {
log.warn(getString("com.mingliqiye.utils.i18n.readjson.error", "$langPath/${thisName}.json"))
}
}
if (thisName != thisBackName) {
readJson("/assets/mingli-utils/lang/${thisBackName}.json", Internationalization::class.java, thisBackName)
if (!isloadSlef) {
if (!readJson(fileName = "$langPath/${thisBackName}.json", lang = thisBackName)) {
log.warn(getString("com.mingliqiye.utils.i18n.readjson.error", "$langPath/${thisBackName}.json"))
}
}
}
}
fun getString(string: String, vararg any: Any): String {
return getString(string).format(*any)
}
fun getString(string: String): String {
return getKeyString(string)
}
fun getKeyString(key: String): String {
val s = localesData[thisName]?.get(key) ?: localesData[thisBackName]?.get(key)
if (s == null) {
return key
}
return s
}
fun getLanguageName(locale: Locale): String =
if (locale.country == null || locale.language == null) locale.country + locale.language else locale.language + '_' + locale.country
constructor(
clazz: Class<*>,
objectMapper: ObjectMapper,
) : this(
locale = Locale.getDefault(), clazz = clazz, objectMapper = objectMapper
)
constructor(
clazz: Class<*>, objectMapper: ObjectMapper, langPath: String = "/lang"
) : this(
locale = Locale.getDefault(), clazz = clazz, langPath = langPath, objectMapper = objectMapper
)
val localesData: MutableMap<String, MutableMap<String, String>> = mutableMapOf()
fun getlangFile(
clazzd: Class<*>, fileName: String
): URL? {
return clazzd.getResource(fileName)
}
fun readJson(
fileName: String, clazzd: Class<*> = clazz, lang: String
): Boolean {
val byteArray: ByteArray? = getlangFile(clazzd, fileName)?.openStream()?.use { it.readBytes() }
if (byteArray == null) return false
val node: JsonNode = objectMapper.readTree(byteArray)
if (node.isArray) return false
if (node.isEmpty) return false
var m = localesData[lang]
if (m == null) {
m = mutableMapOf()
localesData[lang] = m
}
readJsonNode(node, "", m)
return true
}
fun readJsonNode(node: JsonNode, path: String, map: MutableMap<String, String>) {
val fields = node.properties().iterator()
while (fields.hasNext()) {
val (k, v) = fields.next()
val pathName = if (path.isEmpty()) path + k else "$path.$k"
if (v.isTextual) {
map[pathName] = v.asText()
} else if (v.isObject) {
readJsonNode(v, pathName, map)
}
}
}
}

View File

@ -16,12 +16,13 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile IO.kt
* LastUpdate 2026-02-04 13:12:57
* LastUpdate 2026-02-06 13:21:33
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.io
import com.mingliqiye.utils.array.toHexString
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import com.mingliqiye.utils.string.join
import org.slf4j.Logger
@ -35,7 +36,13 @@ import java.io.PrintStream
object IO {
@JvmStatic
fun <T : List<*>> T.println(): T {
fun ByteArray.println(): ByteArray {
this.toHexString().chunked(2).println()
return this
}
@JvmStatic
fun <T> List<T>.println(): List<T> {
println("{" + ",".join(this) + "}")
return this
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JacksonJsonApi.kt
* LastUpdate 2026-02-05 10:31:14
* LastUpdate 2026-02-05 14:41:27
* UpdateUser MingLiPro
*/
@ -28,8 +28,8 @@ 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.exception.JsonException
import com.mingliqiye.utils.json.api.base.JsonApi
import com.mingliqiye.utils.json.api.exception.JsonException
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.converters.base.BaseJsonConverter
@ -63,7 +63,7 @@ class JacksonJsonApi : JsonApi {
* @param clazz 目标对象类型
* @param <T> 泛型参数表示目标对象类型
* @return 解析后的对象
* @throws com.mingliqiye.utils.json.api.exception.JsonException 当解析失败时抛出异常
* @throws JsonException 当解析失败时抛出异常
*/
override fun <T> parse(json: String, clazz: Class<T>): T {
return try {

View File

@ -16,12 +16,13 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile DateTimeJsonConverter.kt
* LastUpdate 2026-02-05 11:18:57
* LastUpdate 2026-02-07 22:13:41
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters
import com.mingliqiye.utils.annotation.DateTimeJsonFormat
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
import com.mingliqiye.utils.json.converters.base.AnnotationGetter.Companion.get
@ -29,7 +30,6 @@ import com.mingliqiye.utils.json.converters.base.BaseJsonStringConverter
import com.mingliqiye.utils.objects.isNull
import com.mingliqiye.utils.string.isNullish
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.DateTimeJsonFormat
import com.mingliqiye.utils.time.Formatter
@ -37,7 +37,17 @@ import com.mingliqiye.utils.time.Formatter
* DateTimeJsonConverter 是一个用于处理 DateTime 类型与 JSON 字符串之间转换的类
* 它继承自 BaseJsonStringConverter提供了序列化convert和反序列化deConvert的功能
*/
class DateTimeJsonConverter : BaseJsonStringConverter<DateTime> {
class DateTimeJsonConverter private constructor() : BaseJsonStringConverter<DateTime> {
companion object {
private val dateTimeJsonConverter by lazy {
DateTimeJsonConverter()
}
@JvmStatic
fun getJsonConverter(): DateTimeJsonConverter = dateTimeJsonConverter
}
/**
* DateTime 对象转换为 JSON 字符串

View File

@ -16,12 +16,13 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUIDJsonConverter.kt
* LastUpdate 2026-02-05 11:19:45
* LastUpdate 2026-02-08 01:37:00
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters
import com.mingliqiye.utils.annotation.UUIDJsonFormat
import com.mingliqiye.utils.base.BaseType
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import com.mingliqiye.utils.json.converters.base.AnnotationGetter
@ -31,14 +32,22 @@ import com.mingliqiye.utils.objects.isNull
import com.mingliqiye.utils.string.isNullish
import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUIDFormatType
import com.mingliqiye.utils.uuid.UUIDJsonFormat
/**
* UUIDJsonConverter 是一个用于处理 UUID 类型与 JSON 字符串之间转换的类
* 它继承自 BaseJsonStringConverter并实现了 convert deConvert 方法
* 分别用于将 UUID 对象序列化为字符串以及反序列化字符串为 UUID 对象
*/
class UUIDJsonConverter : BaseJsonStringConverter<UUID> {
class UUIDJsonConverter private constructor() : BaseJsonStringConverter<UUID> {
companion object {
private val uuidJsonConverter by lazy {
UUIDJsonConverter()
}
@JvmStatic
fun getJsonConverter(): UUIDJsonConverter = uuidJsonConverter
}
/**
* UUID 对象转换为字符串形式

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile AnnotationGetter.kt
* LastUpdate 2026-02-05 11:12:36
* LastUpdate 2026-02-06 16:57:45
* UpdateUser MingLiPro
*/
@ -58,5 +58,24 @@ interface AnnotationGetter {
*/
override fun <T : Annotation> get(clazz: Class<T>): T? = null
}
/**
* 创建一个AnnotationGetter对象用于根据指定的注解类型获取对应的注解实例
*
* @param annotation 要包装的注解实例作为内部逻辑的来源
* @return 返回一个实现了AnnotationGetter接口的匿名对象
*/
fun oneGetter(annotation: Annotation) = object : AnnotationGetter {
/**
* 根据传入的注解类型clazz尝试返回与annotation匹配的注解实例
*
* @param clazz 目标注解类型的Class对象
* @return 如果annotation的类型与clazz一致则返回annotation转换为T类型的实例否则返回null
*/
override fun <T : Annotation> get(clazz: Class<T>): T? =
if (annotation.javaClass == clazz) annotation as T else null
}
}
}

View File

@ -16,195 +16,19 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BaseJsonConverter.kt
* LastUpdate 2026-02-05 11:16:12
* LastUpdate 2026-02-08 01:22:35
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.deser.ContextualDeserializer
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.ser.ContextualSerializer
import com.mingliqiye.utils.json.api.type.JsonTypeReference
import java.math.BigDecimal
import java.math.BigInteger
/**
* BaseJsonConverter 是一个通用的 JSON 转换器接口用于定义对象之间的双向转换逻辑
* BaseJsonConverter 是一个泛型接口用于定义 JSON 转换器的基本行为
*
* @param F 源类型表示需要被转换的对象类型
* @param T 目标类型表示转换后的对象类型
* 该接口继承自 JackSonJsonConverter并通过泛型参数 F T 定义了转换的源类型和目标类型
* 实现该接口的类需要提供具体的 JSON 转换逻辑
*
* @param F 源类型表示需要被转换的数据类型
* @param T 目标类型表示转换后的数据类型
*/
interface BaseJsonConverter<F, T> {
/**
* 将源对象转换为目标对象
*
* @param obj 源对象可能为 null
* @param annotationGetter 注解获取器用于获取字段上的注解信息
* @return 转换后的目标对象可能为 null
* @throws Exception 转换过程中可能抛出的异常
*/
@Throws(Exception::class)
fun convert(obj: F?, annotationGetter: AnnotationGetter): T?
/**
* 将目标对象反向转换为源对象
*
* @param obj 目标对象可能为 null
* @param annotationGetter 注解获取器用于获取字段上的注解信息
* @return 反向转换后的源对象可能为 null
* @throws Exception 转换过程中可能抛出的异常
*/
@Throws(Exception::class)
fun deConvert(obj: T?, annotationGetter: AnnotationGetter): F?
/**
* 获取源类型的类型引用
*
* @return 源类型的 JsonTypeReference 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getFromType(): JsonTypeReference<F>
/**
* 获取目标类型的类型引用
*
* @return 目标类型的 JsonTypeReference 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getToType(): JsonTypeReference<T>
/**
* 获取源类型的原始类
*
* @return 源类型的 Class 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getFromClass() = getFromType().getRawType()
/**
* 获取目标类型的原始类
*
* @return 目标类型的 Class 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getToClass() = getToType().getRawType()
/**
* 创建并返回一个 Jackson 模块该模块包含自定义的序列化器和反序列化器
*
* @return 配置了自定义序列化器和反序列化器的 SimpleModule 对象
*/
fun getJacksonModule(): SimpleModule {
// 创建一个 Jackson 模块,名称由源类型和目标类型组成
val module = SimpleModule("${getFromClass().name}To${getToClass().name}")
// 定义自定义序列化器
val serializer = object : JsonSerializer<F>(), ContextualSerializer {
var property: BeanProperty? = null
/**
* 序列化方法将源对象转换为目标对象并根据目标对象的类型写入 JSON
*
* @param value 源对象可能为 null
* @param gen JSON 生成器用于写入 JSON 数据
* @param provider 序列化提供者可选参数
*/
override fun serialize(
value: F?,
gen: JsonGenerator,
provider: SerializerProvider?
) {
// 执行转换逻辑
val data: T? = convert(value, object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
// 根据目标对象的类型写入对应的 JSON 值
when (data) {
null -> gen.writeNull()
is String -> gen.writeString(data)
is Long -> gen.writeNumber(data)
is Short -> gen.writeNumber(data)
is Byte -> gen.writeNumber(data.toShort())
is Int -> gen.writeNumber(data)
is BigDecimal -> gen.writeNumber(data)
is BigInteger -> gen.writeNumber(data)
is Float -> gen.writeNumber(data)
is Double -> gen.writeNumber(data)
is Boolean -> gen.writeBoolean(data)
else -> throw IllegalArgumentException("not sport data type ${data.javaClass} $data")
}
}
/**
* 上下文感知方法设置当前属性信息
*
* @param prov 序列化提供者可选参数
* @param property 当前属性信息
* @return 返回当前序列化器实例
*/
override fun createContextual(
prov: SerializerProvider?,
property: BeanProperty?
): JsonSerializer<F> {
this.property = property
return this
}
}
// 定义自定义反序列化器
val deserializer = object : JsonDeserializer<F>(), ContextualDeserializer {
/**
* 反序列化方法 JSON 解析数据并转换回源对象
*
* @param p JSON 解析器
* @param ctxt 反序列化上下文可选参数
* @return 转换后的源对象可能为 null
*/
override fun deserialize(
p: JsonParser,
ctxt: DeserializationContext?
): F? {
// 处理 null 值情况
if (p.currentToken == JsonToken.VALUE_NULL) return null
// 执行反向转换逻辑
return deConvert(p.readValueAs(getToClass()), object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
}
var property: BeanProperty? = null
/**
* 上下文感知方法设置当前属性信息
*
* @param ctxt 反序列化上下文可选参数
* @param property 当前属性信息
* @return 返回当前反序列化器实例
*/
override fun createContextual(
ctxt: DeserializationContext?,
property: BeanProperty?
): JsonDeserializer<F> {
this.property = property
return this
}
}
// 将自定义序列化器和反序列化器注册到模块中
return module
.addSerializer(getFromClass(), serializer)
.addDeserializer(getFromClass(), deserializer)
}
}
interface BaseJsonConverter<F, T> : JackSonJsonConverter<F, T>

View File

@ -0,0 +1,59 @@
/*
* Copyright 2026 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 JackJsonDeserializer.kt
* LastUpdate 2026-02-08 02:22:46
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
import com.fasterxml.jackson.databind.BeanProperty
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.deser.ContextualDeserializer
class JackJsonDeserializer<F, T>(
val property: BeanProperty? = null,
val jsonConverter: JsonConverter<F, T>
) : JsonDeserializer<F>(), ContextualDeserializer {
override fun deserialize(
p: JsonParser,
ctxt: DeserializationContext?
): F? {
if (p.currentToken == JsonToken.VALUE_NULL) return null
return jsonConverter.deConvert(p.readValueAs(jsonConverter.getToClass()), object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
}
/**
* 上下文感知方法设置当前属性信息
*
* @param ctxt 反序列化上下文可选参数
* @param property 当前属性信息
* @return 返回当前反序列化器实例
*/
override fun createContextual(
ctxt: DeserializationContext?,
property: BeanProperty?
): JackJsonDeserializer<F, T> {
return JackJsonDeserializer(property, jsonConverter)
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2026 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 JackJsonSerializer.kt
* LastUpdate 2026-02-08 02:27:52
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.BeanProperty
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.ContextualSerializer
import java.math.BigDecimal
import java.math.BigInteger
class JackJsonSerializer<F, T>(
val property: BeanProperty?,
val jsonConverter: JsonConverter<F, T>
) : JsonSerializer<F>(), ContextualSerializer {
/**
* 序列化方法将源对象转换为目标对象并根据目标对象的类型写入 JSON
*
* @param value 源对象可能为 null
* @param gen JSON 生成器用于写入 JSON 数据
* @param provider 序列化提供者可选参数
*/
override fun serialize(
value: F?,
gen: JsonGenerator,
provider: SerializerProvider?
) {
// 执行转换逻辑
val data: T? = jsonConverter.convert(value, object : AnnotationGetter {
override fun <T : Annotation> get(clazz: Class<T>): T? = property?.getAnnotation(clazz)
})
// 根据目标对象的类型写入对应的 JSON 值
when (data) {
null -> gen.writeNull()
is String -> gen.writeString(data)
is Long -> gen.writeNumber(data)
is Short -> gen.writeNumber(data)
is Byte -> gen.writeNumber(data.toShort())
is Int -> gen.writeNumber(data)
is BigDecimal -> gen.writeNumber(data)
is BigInteger -> gen.writeNumber(data)
is Float -> gen.writeNumber(data)
is Double -> gen.writeNumber(data)
is Boolean -> gen.writeBoolean(data)
else -> throw IllegalArgumentException("not sport data type ${data.javaClass} $data")
}
}
/**
* 上下文感知方法设置当前属性信息
*
* @param prov 序列化提供者可选参数
* @param property 当前属性信息
* @return 返回当前序列化器实例
*/
override fun createContextual(
prov: SerializerProvider?,
property: BeanProperty?
): JsonSerializer<F> {
return JackJsonSerializer(property, jsonConverter)
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2026 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 JackSonJsonConverter.kt
* LastUpdate 2026-02-08 02:28:49
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule
interface JackSonJsonConverter<F, T> : JsonConverter<F, T> {
companion object {
/**
* 扩展ObjectMapper用于注册指定类型的模块
*
* 此函数通过反射创建指定类型的实例并调用其getJacksonModule方法来获取Jackson模块
* 然后将该模块注册到当前ObjectMapper实例中
*
* @param T 必须继承自BaseJsonConverter的泛型类型
* @return 返回注册了模块后的ObjectMapper实例
*/
inline fun <reified T : BaseJsonConverter<*, *>> ObjectMapper.addJsonConverter(): ObjectMapper =
this.registerModule(getJsonConverter<T>().getJacksonModule())
@JvmStatic
fun <T : BaseJsonConverter<*, *>> ObjectMapper.addJsonConverter(clazz: Class<T>): ObjectMapper =
this.registerModule(getJsonConverter(clazz).getJacksonModule())
}
/**
* 创建并返回一个 Jackson 模块该模块包含自定义的序列化器和反序列化器
*
* @return 配置了自定义序列化器和反序列化器的 SimpleModule 对象
*/
fun getJacksonModule(): SimpleModule =
SimpleModule("${getFromClass().name}To${getToClass().name}")
.addSerializer(getFromClass(), JackJsonSerializer(null, this))
.addDeserializer(getFromClass(), JackJsonDeserializer(null, this))
}

View File

@ -16,44 +16,76 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JsonConverter.kt
* LastUpdate 2026-02-05 11:18:33
* LastUpdate 2026-02-07 22:30:18
* UpdateUser MingLiPro
*/
@file:JvmName("JsonConverter")
package com.mingliqiye.utils.json.converters.base
import com.fasterxml.jackson.databind.ObjectMapper
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import com.mingliqiye.utils.json.api.type.JsonTypeReference
/**
* 获取给定类型的实际类对象
* BaseJsonConverter 是一个通用的 JSON 转换器接口用于定义对象之间的双向转换逻辑
*
* @param type 类型对象可以是ClassParameterizedType或其他Type的实现
* @return 返回与给定类型对应的Class对象如果无法解析则返回null
* @param F 源类型表示需要被转换的对象类型
* @param T 目标类型表示转换后的对象类型
*/
fun getClass(type: Type?): Class<*>? {
// 尝试将type直接转换为Class类型如果失败则检查是否为ParameterizedType
val clazz: Class<*>? = type as? Class<*> ?: if (type is ParameterizedType) {
// 如果是ParameterizedType则递归获取其原始类型
getClass(type.rawType)
} else {
// 其他情况返回null
null
}
return clazz
interface JsonConverter<F, T> {
/**
* 将源对象转换为目标对象
*
* @param obj 源对象可能为 null
* @param annotationGetter 注解获取器用于获取字段上的注解信息
* @return 转换后的目标对象可能为 null
* @throws Exception 转换过程中可能抛出的异常
*/
@Throws(Exception::class)
fun convert(obj: F?, annotationGetter: AnnotationGetter): T?
/**
* 将目标对象反向转换为源对象
*
* @param obj 目标对象可能为 null
* @param annotationGetter 注解获取器用于获取字段上的注解信息
* @return 反向转换后的源对象可能为 null
* @throws Exception 转换过程中可能抛出的异常
*/
@Throws(Exception::class)
fun deConvert(obj: T?, annotationGetter: AnnotationGetter): F?
/**
* 获取源类型的类型引用
*
* @return 源类型的 JsonTypeReference 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getFromType(): JsonTypeReference<F>
/**
* 获取目标类型的类型引用
*
* @return 目标类型的 JsonTypeReference 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getToType(): JsonTypeReference<T>
/**
* 获取源类型的原始类
*
* @return 源类型的 Class 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getFromClass() = getFromType().getRawType()
/**
* 获取目标类型的原始类
*
* @return 目标类型的 Class 对象
* @throws Exception 获取过程中可能抛出的异常
*/
@Throws(Exception::class)
fun getToClass() = getToType().getRawType()
}
/**
* 扩展ObjectMapper用于注册指定类型的模块
*
* 此函数通过反射创建指定类型的实例并调用其getJacksonModule方法来获取Jackson模块
* 然后将该模块注册到当前ObjectMapper实例中
*
* @param T 必须继承自BaseJsonConverter的泛型类型
* @return 返回注册了模块后的ObjectMapper实例
*/
inline fun <reified T : BaseJsonConverter<*, *>> ObjectMapper.registerModule(): ObjectMapper =
this.registerModule(T::class.java.newInstance().getJacksonModule())

View File

@ -0,0 +1,61 @@
/*
* Copyright 2026 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 JsonConverterUtils.kt
* LastUpdate 2026-02-07 22:33:09
* UpdateUser MingLiPro
*/
@file:JvmName("JsonConverterUtils")
package com.mingliqiye.utils.json.converters.base
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
val log = MingLiLoggerFactory.getLogger("com.mingliqiye.utils.json.converters.base.JsonConverterUtils")
/**
* 获取给定类型的实际类对象
*
* @param type 类型对象可以是ClassParameterizedType或其他Type的实现
* @return 返回与给定类型对应的Class对象如果无法解析则返回null
*/
fun getClass(type: Type?): Class<*>? {
// 尝试将type直接转换为Class类型如果失败则检查是否为ParameterizedType
val clazz: Class<*>? = type as? Class<*> ?: if (type is ParameterizedType) {
// 如果是ParameterizedType则递归获取其原始类型
getClass(type.rawType)
} else {
null
}
return clazz
}
inline fun <reified T : JsonConverter<*, *>> getJsonConverter(): T = getJsonConverter(T::class.java)
fun <T : JsonConverter<*, *>> getJsonConverter(clazz: Class<T>): T {
try {
return clazz.getDeclaredMethod(
"getJsonConverter"
).invoke(null) as T
} catch (e: Exception) {
log.error("实现于 JsonConverter<*, *> 的类 必须实现静态方法 JsonConverter<*, *> getJsonConverter()", e)
throw e
}
}

View File

@ -15,27 +15,16 @@
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Loggers.kt
* LastUpdate 2026-02-05 10:20:31
* CurrentFile MingLiLogger.kt
* LastUpdate 2026-02-06 08:27:44
* UpdateUser MingLiPro
*/
@file:JvmName("Loggers")
package com.mingliqiye.utils.logger
import org.slf4j.Logger
import org.slf4j.Marker
enum class MingLiLoggerLevel {
TRACE,
DEBUG,
INFO,
WARN,
ERROR
}
class MingLiLogger(private val name: String) : Logger {
override fun getName(): String {
return name
@ -312,8 +301,7 @@ class MingLiLogger(private val name: String) : Logger {
override fun error(msg: String?, t: Throwable?) {
msg?.let {
val message = if (t != null) "$it: ${t.message}" else it
toPrintln(message, MingLiLoggerLevel.ERROR)
toPrintln(it, MingLiLoggerLevel.ERROR)
}
}

View File

@ -15,15 +15,17 @@
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile StreamEmptyException.kt
* LastUpdate 2026-01-07 19:13:29
* CurrentFile MingLiLoggerLevel.kt
* LastUpdate 2026-02-06 08:27:44
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.stream
package com.mingliqiye.utils.logger
class StreamEmptyException : RuntimeException {
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
enum class MingLiLoggerLevel {
TRACE,
DEBUG,
INFO,
WARN,
ERROR
}

View File

@ -15,8 +15,8 @@
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile QueryWrapper.kt
* LastUpdate 2026-02-03 12:03:27
* CurrentFile BaseMapperQuery.kt
* LastUpdate 2026-02-06 13:15:11
* UpdateUser MingLiPro
*/
@ -27,41 +27,52 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper
@Deprecated(
"rename to FastBaseMapper",
replaceWith = ReplaceWith(
expression = "FastBaseMapper<*>",
imports = ["com.mingliqiye.utils.mybatisplus.FastBaseMapper"]
),
level = DeprecationLevel.WARNING
)
/**
* BaseMapperQuery接口扩展了BaseMapper提供了通用的查询包装器功能
*
* @param T 实体类类型
* @since 4.6.1
* 已经重命名 [FastBaseMapper]
*/
interface BaseMapperQuery<T> : BaseMapper<T> {
interface BaseMapperQuery<T> : FastBaseMapper<T>
/**
* 扩展[BaseMapper]接口提供便捷的查询和更新包装器创建方法
* 包含普通包装器`Lambda`包装器和`Kotlin`专用包装器的创建方法
*/
interface FastBaseMapper<T> : BaseMapper<T> {
/**
* 创建并返回一个新的QueryWrapper实例
*
* @return QueryWrapper<T> 返回类型化的查询包装器实例
* 创建[QueryWrapper]实例
* @return QueryWrapper<T> 查询包装器实例
*/
fun queryWrapper() = QueryWrapper<T>()
/**
* 创建并返回一个新的UpdateWrapper实例
*
* @return UpdateWrapper<T> 返回类型化的更新包装器实例
* 创建[UpdateWrapper]实例
* @return UpdateWrapper<T> 更新包装器实例
*/
fun updateWrapper() = UpdateWrapper<T>()
/**
* 创建并返回一个新的LambdaQueryWrapper实例
*
* @return LambdaQueryWrapper<T> 返回类型化的Lambda查询包装器实例
* 创建[LambdaQueryWrapper]实例
* @return LambdaQueryWrapper<T> Lambda查询包装器实例
*/
fun lambdaQueryWrapper() = LambdaQueryWrapper<T>()
/**
* 创建并返回一个新的LambdaUpdateWrapper实例
*
* @return LambdaUpdateWrapper<T> 返回类型化的Lambda更新包装器实例
* 创建[LambdaUpdateWrapper]实例
* @return LambdaUpdateWrapper<T> Lambda更新包装器实例
*/
fun lambdaUpdateWrapper() = LambdaUpdateWrapper<T>()
@ -69,56 +80,77 @@ interface BaseMapperQuery<T> : BaseMapper<T> {
companion object {
/**
* 创建并返回一个新的QueryWrapper实例
*
* @return QueryWrapper<T> 返回类型化的查询包装器实例
* [BaseMapper]创建[QueryWrapper]实例
* @param T 范型类型通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return QueryWrapper<T> 查询包装器实例使用T类作为参数
*/
inline fun <reified T> BaseMapper<T>.queryWrapper(): QueryWrapper<T> = QueryWrapper<T>()
inline fun <reified T> BaseMapper<T>.queryWrapper(): QueryWrapper<T> = QueryWrapper<T>(T::class.java)
/**
* 创建并返回一个新的UpdateWrapper实例
*
* @return UpdateWrapper<T> 返回类型化的更新包装器实例
* [BaseMapper]创建[UpdateWrapper]实例
* @param T 范型类型通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return UpdateWrapper<T> 更新包装器实例
*/
inline fun <reified T> BaseMapper<T>.updateWrapper(): UpdateWrapper<T> = UpdateWrapper<T>()
/**
* 创建并返回一个新的LambdaQueryWrapper实例
*
* @return LambdaQueryWrapper<T> 返回类型化的Lambda查询包装器实例
* [BaseMapper]创建[LambdaQueryWrapper]实例
* @param T 范型类型通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return LambdaQueryWrapper<T> Lambda查询包装器实例使用T类作为参数
*/
inline fun <reified T> BaseMapper<T>.lambdaQueryWrapper(): LambdaQueryWrapper<T> =
LambdaQueryWrapper<T>(T::class.java)
/**
* 创建并返回一个新的LambdaUpdateWrapper实例
*
* @return LambdaUpdateWrapper<T> 返回类型化的Lambda更新包装器实例
* [BaseMapper]创建[LambdaUpdateWrapper]实例
* @param T 范型类型通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return LambdaUpdateWrapper<T> Lambda更新包装器实例使用T类作为参数
*/
inline fun <reified T> BaseMapper<T>.lambdaUpdateWrapper(): LambdaUpdateWrapper<T> =
LambdaUpdateWrapper<T>(T::class.java)
/**
* 创建并返回一个新的KtUpdateWrapper实例
*
* @return KtUpdateWrapper<T> 返回类型化的Kotlin更新包装器实例
* [BaseMapper]创建[KtQueryWrapper]实例
* @param T 范型类型必须继承自Any通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return KtQueryWrapper<T> Kotlin查询包装器实例使用T类作为参数
*/
inline fun <reified T : Any> BaseMapper<T>.ktQueryWrapper(): KtQueryWrapper<T> = KtQueryWrapper(T::class.java)
/**
* [BaseMapper]创建[KtQueryChainWrapper]实例
* @param T 范型类型必须继承自Any通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return KtQueryChainWrapper<T> Kotlin查询链式包装器实例使用T类作为参数
*/
inline fun <reified T : Any> BaseMapper<T>.ktQueryChainWrapper(): KtQueryChainWrapper<T> =
KtQueryChainWrapper(T::class.java)
/**
* [BaseMapper]创建[KtUpdateWrapper]实例
* @param T 范型类型必须继承自Any通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return KtUpdateWrapper<T> Kotlin更新包装器实例使用T类作为参数
*/
inline fun <reified T : Any> BaseMapper<T>.ktUpdateWrapper(): KtUpdateWrapper<T> =
KtUpdateWrapper(T::class.java)
/**
* 创建并返回一个新的KtQueryWrapper实例
*
* @return KtQueryWrapper<T> 返回类型化的Kotlin查询包装器实例
*/
inline fun <reified T : Any> BaseMapper<T>.ktQueryWrapper(): KtQueryWrapper<T> = KtQueryWrapper(T::class.java)
/**
* 创建并返回一个新的KtUpdateChainWrapper实例
*
* @return KtUpdateChainWrapper<T> 返回类型化的Kotlin更新链式包装器实例
* [BaseMapper]创建[KtUpdateChainWrapper]实例
* @param T 范型类型必须继承自Any通过reified获取实际类型
* @receiver BaseMapper<T> 基础映射器实例
* @return KtUpdateChainWrapper<T> Kotlin更新链式包装器实例使用T类作为参数
*/
inline fun <reified T : Any> BaseMapper<T>.ktUpdateChainWrapper(): KtUpdateChainWrapper<T> =
KtUpdateChainWrapper(T::class.java)
}
}

View File

@ -16,12 +16,13 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile Require.kt
* LastUpdate 2026-02-05 11:08:03
* LastUpdate 2026-02-06 08:27:44
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.require
import com.mingliqiye.utils.exception.InternalServerErrorException
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import org.slf4j.Logger
import java.lang.reflect.Constructor
@ -32,19 +33,136 @@ import kotlin.contracts.contract
* 工具对象用于提供条件检查功能
* 支持抛出自定义异常延迟消息构造以及日志记录等功能
*/
object Require {
class Require(val defaultException: Class<out Throwable>) {
/**
* 日志记录器实例用于记录错误信息
*/
@JvmStatic
var logger: Logger? = MingLiLoggerFactory.getLogger<Require>()
companion object {
@JvmStatic
val RequireLayz by lazy {
Require(IllegalArgumentException::class.java)
}
/**
* 控制是否在抛出异常时记录错误日志
*/
@JvmStatic
var isLogError = true
@JvmStatic
val RequireHttpLayz by lazy {
Require(InternalServerErrorException::class.java)
}
@JvmStatic
var logger: Logger? = MingLiLoggerFactory.getLogger<Require>()
@JvmStatic
var isLogError = true
/**
* 检查给定条件是否为真如果为假则使用延迟消息构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param throwable 异常类型
* @param layzMessage 延迟消息构造器
*/
@OptIn(ExperimentalContracts::class)
fun require(value: Boolean, throwable: Class<out Throwable>, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
require(value, layzMessage.call(), throwable)
}
/**
* 检查给定条件是否为真如果为假则使用延迟异常构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param layzThrowable 延迟异常构造器
*/
@JvmStatic
@OptIn(ExperimentalContracts::class)
fun require(value: Boolean, layzThrowable: RequireLayzExceptionConstructor) {
contract {
returns() implies value
}
if (!value) throwThrowable(layzThrowable.call())
}
/**
* 检查给定条件是否为真如果为假则根据指定的异常类型和消息生成异常并抛出
*
* @param value 需要检查的布尔值
* @param message 异常消息
* @param throwable 异常类型
*/
@JvmStatic
@OptIn(ExperimentalContracts::class)
fun require(value: Boolean, message: String, throwable: Class<out Throwable>) {
contract {
returns() implies value
}
if (!value) throwThrowable(getExceptionConstructor(throwable).newInstance(message))
}
/**
* 抛出指定的异常并在启用日志记录时记录错误信息
*
* @param throwable 需要抛出的异常
*/
@JvmStatic
fun throwThrowable(throwable: Throwable) {
if (isLogError && logger != null) logger!!.error(throwable.message, throwable)
throw throwable
}
/**
* 检查给定条件是否为真如果为假则根据指定的异常类型抛出异常
*
* @param value 需要检查的布尔值
* @param message 异常消息
* @param T 异常类型
*/
@OptIn(ExperimentalContracts::class)
@JvmName("__inline_Require")
inline fun <reified T : Throwable> require(value: Boolean, message: String) {
contract {
returns() implies value
}
require(value, message, T::class.java)
}
/**
* 检查给定条件是否为真如果为假则根据指定的异常类型和延迟消息构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param layzMessage 延迟消息构造器
* @param T 异常类型
*/
@OptIn(ExperimentalContracts::class)
@JvmName("__inline_Require")
inline fun <reified T : Throwable> require(value: Boolean, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
if (!value) throwThrowable(getExceptionConstructor<T>().newInstance(layzMessage.call()))
}
/**
* 获取指定异常类型的构造函数带字符串参数
*
* @param T 异常类型
* @return 异常类型的构造函数
*/
@JvmName("__inline_GetExceptionConstructor")
inline fun <reified T : Throwable> getExceptionConstructor(): Constructor<out T> =
getExceptionConstructor(T::class.java)
/**
* 获取指定异常类型的构造函数带字符串参数
*
* @param throwable 异常类型
* @return 异常类型的构造函数
*/
@JvmStatic
@JvmName("__GetExceptionConstructor")
fun <T : Throwable> getExceptionConstructor(throwable: Class<out T>): Constructor<out T> =
throwable.getConstructor(String::class.java)
}
/**
* 检查给定条件是否为真如果为假则抛出 [IllegalArgumentException] 异常
@ -52,28 +170,25 @@ object Require {
* @param value 需要检查的布尔值
*/
@OptIn(ExperimentalContracts::class)
@JvmStatic
fun require(value: Boolean) {
contract {
returns() implies value
}
require<IllegalArgumentException>(value, "the require conditions are not met.")
require(value, "the require conditions are not met.")
}
/**
* 检查给定条件是否为真如果为假根据指定的异常类型抛出异常
* 检查给定条件是否为真如果为假使用延迟消息构造器生成 [IllegalArgumentException] 并抛出
*
* @param value 需要检查的布尔值
* @param message 异常消息
* @param T 异常类型
* @param layzMessage 延迟消息构造器
*/
@OptIn(ExperimentalContracts::class)
@JvmName("__inline_Require")
inline fun <reified T : Throwable> require(value: Boolean, message: String) {
fun requireLayzMessage(value: Boolean, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
require(value, message, T::class.java)
require(value, defaultException, layzMessage)
}
/**
@ -87,114 +202,6 @@ object Require {
contract {
returns() implies value
}
if (!value) throwThrowable(getExceptionConstructor<IllegalArgumentException>().newInstance(message))
if (!value) throwThrowable(getExceptionConstructor(defaultException).newInstance(message))
}
/**
* 检查给定条件是否为真如果为假则使用延迟消息构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param throwable 异常类型
* @param layzMessage 延迟消息构造器
*/
@OptIn(ExperimentalContracts::class)
@JvmStatic
fun require(value: Boolean, throwable: Class<out Throwable>, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
require(value, layzMessage.call(), throwable)
}
/**
* 检查给定条件是否为真如果为假则使用延迟异常构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param layzThrowable 延迟异常构造器
*/
@OptIn(ExperimentalContracts::class)
@JvmStatic
fun require(value: Boolean, layzThrowable: RequireLayzExceptionConstructor) {
contract {
returns() implies value
}
if (!value) throwThrowable(layzThrowable.call())
}
/**
* 检查给定条件是否为真如果为假则使用延迟消息构造器生成 [IllegalArgumentException] 并抛出
*
* @param value 需要检查的布尔值
* @param layzMessage 延迟消息构造器
*/
@OptIn(ExperimentalContracts::class)
@JvmStatic
fun requireLayzMessage(value: Boolean, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
require<IllegalArgumentException>(value, layzMessage)
}
/**
* 检查给定条件是否为真如果为假则根据指定的异常类型和延迟消息构造器生成异常并抛出
*
* @param value 需要检查的布尔值
* @param layzMessage 延迟消息构造器
* @param T 异常类型
*/
@OptIn(ExperimentalContracts::class)
@JvmName("__inline_Require")
inline fun <reified T : Throwable> require(value: Boolean, layzMessage: RequireLayzMessageConstructor) {
contract {
returns() implies value
}
if (!value) throwThrowable(getExceptionConstructor<T>().newInstance(layzMessage.call()))
}
/**
* 检查给定条件是否为真如果为假则根据指定的异常类型和消息生成异常并抛出
*
* @param value 需要检查的布尔值
* @param message 异常消息
* @param throwable 异常类型
*/
@OptIn(ExperimentalContracts::class)
@JvmStatic
fun require(value: Boolean, message: String, throwable: Class<out Throwable>) {
contract {
returns() implies value
}
if (!value) throwThrowable(getExceptionConstructor(throwable).newInstance(message))
}
/**
* 抛出指定的异常并在启用日志记录时记录错误信息
*
* @param throwable 需要抛出的异常
*/
fun throwThrowable(throwable: Throwable) {
if (isLogError && logger != null) logger!!.error(throwable.message, throwable)
throw throwable
}
/**
* 获取指定异常类型的构造函数带字符串参数
*
* @param T 异常类型
* @return 异常类型的构造函数
*/
@JvmName("__inline_GetExceptionConstructor")
inline fun <reified T : Throwable> getExceptionConstructor(): Constructor<out T> =
getExceptionConstructor(T::class.java)
/**
* 获取指定异常类型的构造函数带字符串参数
*
* @param throwable 异常类型
* @return 异常类型的构造函数
*/
@JvmName("__GetExceptionConstructor")
fun <T : Throwable> getExceptionConstructor(throwable: Class<out T>): Constructor<out T> =
throwable.getConstructor(String::class.java)
}

View File

@ -16,12 +16,14 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile AutoConfiguration.kt
* LastUpdate 2026-02-05 10:45:05
* LastUpdate 2026-02-06 15:15:46
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.springboot.autoconfigure
import com.mingliqiye.utils.i18n.I18N
import com.mingliqiye.utils.i18n.I18N.infoTranslater
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import com.mingliqiye.utils.system.computerName
import com.mingliqiye.utils.system.getPid
@ -50,15 +52,14 @@ open class AutoConfiguration {
* 启动横幅字符串包含艺术字体和占位符
*/
private const val BANNER =
"---------------------------------------------------------\n" +
"| $$\\ $$\\ $$\\ $$\\ $$\\ $$$$$$$$\\ $$$$$$\\ |\n" +
"| $$$\\ $$$ |$$ | $$ | $$ |\\__$$ __|$$ __$$\\ |\n" +
"| $$$$\\ $$$$ |$$ | $$ | $$ | $$ | $$ / \\__| |\n" +
"| $$\\$$\\$$ $$ |$$ | $$ | $$ | $$ | \\$$$$$$\\ |\n" +
"| $$ \\$$$ $$ |$$ | $$ | $$ | $$ | \\____$$\\ |\n" +
"| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | |\n" +
"| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ | |\n" +
"| \\__| \\__|\\________|\\______/ \\__| \\______/ |\n"
" | $$\\ $$\\ $$\\ $$\\ $$\\ $$$$$$$$\\ $$$$$$\\ \n" +
"| $$$\\ $$$ |$$ | $$ | $$ |\\__$$ __|$$ __$$\\ \n" +
"| $$$$\\ $$$$ |$$ | $$ | $$ | $$ | $$ / \\__| \n" +
"| $$\\$$\\$$ $$ |$$ | $$ | $$ | $$ | \\$$$$$$\\ \n" +
"| $$ \\$$$ $$ |$$ | $$ | $$ | $$ | \\____$$\\ \n" +
"| $$ |\\$ /$$ |$$ | $$ | $$ | $$ | $$\\ $$ | \n" +
"| $$ | \\_/ $$ |$$$$$$$$\\\\$$$$$$ | $$ | \\$$$$$$ \n" +
"| \\__| \\__|\\________|\\______/ \\__| \\______/ \n|\n"
/**
* 打印启动横幅包含系统元数据如JDK版本进程ID计算机名等
@ -84,22 +85,25 @@ open class AutoConfiguration {
// 解析元数据并添加额外的系统信息
val da = metaData.toString().split("\n").toMutableList()
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, false))
da.add("${I18N.getString("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.jdkRuntime")}=$jdkVersion")
da.add("${I18N.getString("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.pid")}=$getPid")
da.add("${I18N.getString("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.computerName")}=$computerName")
da.add("${I18N.getString("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.userName")}=$userName")
da.add(
"${I18N.getString("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.time")}=" + DateTime.now()
.format(Formatter.STANDARD_DATETIME_MILLISECOUND7, false)
)
// 格式化每条元数据并追加到横幅中
da.forEach { s: String ->
val d = s.trim { it <= ' ' }.split("=".toRegex(), 2).toTypedArray()
if (d.size >= 2) {
val content = "| " + d[0] + ": " + d[1]
val content = "| -> " + I18N.getString(d[0]) + ": " + d[1]
val targetLength = 56
if (content.length < targetLength) {
bannerBuilder.append(
String.format(
"%-" + targetLength + "s|\n",
"%-${targetLength}s\n",
content
)
)
@ -117,8 +121,9 @@ open class AutoConfiguration {
}
// 输出最终构建的横幅
println("")
println(bannerBuilder.toString().trim())
println("---------------------------------------------------------")
println("")
}
}
@ -129,6 +134,6 @@ open class AutoConfiguration {
*/
init {
printBanner()
log.info("MingliUtils AutoConfigurationBean succeed")
log.infoTranslater("com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.bean")
}
}

View File

@ -16,19 +16,20 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile JacksonAutoConfiguration.kt
* LastUpdate 2026-02-05 10:45:19
* LastUpdate 2026-02-08 01:29:21
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.springboot.autoconfigure
import com.fasterxml.jackson.databind.ObjectMapper
import com.mingliqiye.utils.i18n.I18N.infoTranslater
import com.mingliqiye.utils.json.api.JSONA
import com.mingliqiye.utils.json.api.JacksonJsonApi
import com.mingliqiye.utils.json.api.base.JsonApi
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter
import com.mingliqiye.utils.json.converters.UUIDJsonConverter
import com.mingliqiye.utils.json.converters.base.registerModule
import com.mingliqiye.utils.json.converters.base.JackSonJsonConverter.Companion.addJsonConverter
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import org.slf4j.Logger
import org.springframework.boot.autoconfigure.AutoConfigureAfter
@ -76,10 +77,10 @@ open class JacksonAutoConfiguration(objectMapper: ObjectMapper) {
* 注册自定义的 UUID DateTime JSON 转换器模块到 ObjectMapper
*/
init {
log.info("MingliUtils Jackson Serializers created")
log.infoTranslater("com.mingliqiye.utils.springboot.autoconfigure.JsonApiAutoConfiguration.jacksonserializers")
objectMapper
.registerModule<UUIDJsonConverter>()
.registerModule<DateTimeJsonConverter>()
.addJsonConverter<UUIDJsonConverter>()
.addJsonConverter<DateTimeJsonConverter>()
}
/*
@ -93,13 +94,16 @@ open class JacksonAutoConfiguration(objectMapper: ObjectMapper) {
@Primary
@ConditionalOnMissingBean
open fun jsonApi(objectMapper: ObjectMapper): JsonApi {
log.info("MingliUtils-JsonApiAutoConfiguration: JacksonJsonApi bean is created.")
return JacksonJsonApi(objectMapper).also {
log.infoTranslater("com.mingliqiye.utils.springboot.autoconfigure.JsonApiAutoConfiguration.jsonapiconfiged")
try {
JSONA.getJsonApi()
} catch (_: NullPointerException) {
JSONA.setJsonApi(it)
log.info("JSONA Use {}", it.javaClass.name)
log.infoTranslater(
"com.mingliqiye.utils.springboot.autoconfigure.JsonApiAutoConfiguration.jsonause",
it.javaClass.name
)
}
}
}

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile StringUtils.kt
* LastUpdate 2026-02-05 11:05:33
* LastUpdate 2026-02-06 08:35:07
* UpdateUser MingLiPro
*/
@file:JvmName("StringUtils")
@ -24,6 +24,7 @@
package com.mingliqiye.utils.string
import com.mingliqiye.utils.base.BASE16
import com.mingliqiye.utils.i18n.I18N.warnTranslater
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import com.mingliqiye.utils.objects.isNull
import java.net.URLDecoder
@ -99,15 +100,18 @@ fun format(str: String, vararg args: Any?): String {
// 检查参数数量
val placeholderCount = matches.count()
if (placeholderCount != args.size) {
log.warn("Placeholder count: $placeholderCount, Argument count: ${args.size}")
log.warn("template : $str")
log.warn(
"Arguments : [${
", ".join(args) {
if (it.isNull()) return@join "null:null"
"${it.javaClass.simpleName}:$it"
}
}]")
log.warnTranslater(
"com.mingliqiye.utils.string.StringUtils.format.warn.placeholder",
placeholderCount, args.size
)
log.warnTranslater("com.mingliqiye.utils.string.StringUtils.format.warn.template", str)
log.warnTranslater(
"com.mingliqiye.utils.string.StringUtils.format.warn.arguments",
", ".join(args) {
if (it.isNull()) return@join "null:null"
"${it.javaClass.simpleName}:$it"
}
)
}
return finalResult

View File

@ -16,38 +16,47 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile MysqlUUIDv1.kt
* LastUpdate 2026-01-08 08:22:14
* LastUpdate 2026-02-06 14:52:40
* UpdateUser MingLiPro
*/
@file:JvmName("MysqlUUIDConvertor")
package com.mingliqiye.utils.uuid
import com.mingliqiye.utils.array.copyTo
/**
* 将标准UUID字节数组转换为MySQL存储格式的字节数组
* MySQL中UUID的存储格式与标准UUID的字节顺序不同需要重新排列字节顺序
*
* @param uuid 标准UUID格式的字节数组16字节
* @return 转换后的MySQL存储格式字节数组16字节
* @since 4.6.2
*/
fun uuidToMysql(uuid: ByteArray): ByteArray {
val reuuid = ByteArray(16)
reuuid[4] = uuid[0]
reuuid[5] = uuid[1]
reuuid[6] = uuid[2]
reuuid[7] = uuid[3]
reuuid[2] = uuid[4]
reuuid[3] = uuid[5]
reuuid[0] = uuid[6]
reuuid[1] = uuid[7]
System.arraycopy(uuid, 8, reuuid, 8, 8)
return reuuid
return ByteArray(16).also {
// 按照MySQL UUID存储格式重新排列字节前4字节、中间2字节、后2字节、最后8字节
uuid.copyTo(it, 0, 4, 4)
.copyTo(it, 4, 2, 2)
.copyTo(it, 6, 0, 2)
.copyTo(it, 8, 8, 8)
}
}
/**
* 将MySQL存储格式的UUID字节数组转换回标准UUID格式
* MySQL中UUID的存储格式与标准UUID的字节顺序不同需要恢复原始字节顺序
*
* @param uuid MySQL存储格式的字节数组16字节
* @return 转换后的标准UUID格式字节数组16字节
* @since 4.6.2
*/
fun mysqlToUuid(uuid: ByteArray): ByteArray {
val reuuid = ByteArray(16)
reuuid[6] = uuid[0]
reuuid[7] = uuid[1]
reuuid[4] = uuid[2]
reuuid[5] = uuid[3]
reuuid[0] = uuid[4]
reuuid[1] = uuid[5]
reuuid[2] = uuid[6]
reuuid[3] = uuid[7]
System.arraycopy(uuid, 8, reuuid, 8, 8)
return reuuid
return ByteArray(16).also {
// 按照标准UUID格式恢复字节顺序第6-7字节、第4-5字节、第0-3字节、第8-15字节
uuid.copyTo(it, 0, 6, 2)
.copyTo(it, 2, 4, 2)
.copyTo(it, 4, 0, 4)
.copyTo(it, 8, 8, 8)
}
}

View File

@ -16,13 +16,14 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUID.kt
* LastUpdate 2026-02-05 11:20:59
* LastUpdate 2026-02-06 14:33:24
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.uuid
import com.mingliqiye.utils.base.*
import com.mingliqiye.utils.io.IO.println
import com.mingliqiye.utils.random.randomByte
import com.mingliqiye.utils.random.secureRandom
import com.mingliqiye.utils.system.macAddressBytes
@ -570,8 +571,11 @@ class UUID : Serializable {
* @return 如果相等则返回 true否则返回 false
*/
override fun equals(other: Any?): Boolean {
if (this === other) return true
return when (other) {
is UUID -> {
this.println()
other.println()
this.data.contentEquals(other.data)
}

View File

@ -16,15 +16,41 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile UUIDFormatType.kt
* LastUpdate 2026-02-04 21:54:04
* LastUpdate 2026-02-06 14:53:47
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils.uuid
/**
* UUID格式类型枚举
* 定义了四种不同的UUID格式化选项包括大小写和是否包含空格的组合
*
* @property isUpper 是否使用大写字母
* @property isnotSpace 是否不包含空格true表示无空格false表示有空格
*/
enum class UUIDFormatType(val isUpper: Boolean, val isnotSpace: Boolean) {
/**
* 大写带分隔符
* 使用大写字母并保留空格分隔符
*/
UPPER_SPACE(true, false),
/**
* 小写带分隔符
* 使用小写字母并保留空格分隔符
*/
NO_UPPER_SPACE(false, false),
/**
* 小写无分隔符
* 使用小写字母且不包含空格分隔符
*/
NO_UPPER_NO_SPACE(false, true),
/**
* 大写无分隔符
* 使用大写字母且不包含空格分隔符
*/
UPPER_NO_SPACE(true, true),
}

View File

@ -1,7 +1,7 @@
buildTime=$buildTime
groupId=$GROUPSID
artifactId=$ARTIFACTID
version=$VERSIONS
buildJdkVersion=$JDKVERSIONS
author=MingLiPro
website=https://mingli-utils.mingliqiye.com
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.buildTime=$buildTime
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.groupId=$GROUPSID
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.artifactId=$ARTIFACTID
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.version=$VERSIONS
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.buildJdkVersion=$JDKVERSIONS
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.author=MingLiPro
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.website=https://mingli-utils.mingliqiye.com

View File

@ -0,0 +1,23 @@
#
# Copyright 2026 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 javax.annotation.processing.Processor
# LastUpdate 2026-02-07 09:22:22
# UpdateUser MingLiPro
#
com.mingliqiye.utils.annotation.processor.AutoServiceProcessor

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -0,0 +1,42 @@
{
"com.mingliqiye.utils": {
"i18n": {
"readjson": {
"error": "Failed to load language file %s"
}
},
"springboot.autoconfigure": {
"AutoConfiguration": {
"jdkRuntime": "JDK Runtime Environment Version",
"pid": "Process PID",
"computerName": "Computer Name",
"userName": "User Name",
"time": "Current Time",
"buildTime": "Build Time",
"groupId": "Group ID",
"artifactId": "Artifact ID",
"version": "Version",
"buildJdkVersion": "Build JDK Version",
"author": "Author",
"website": "Official Website",
"bean": "MingliUtils Auto Configuration Bean Success"
},
"JsonApiAutoConfiguration": {
"jsonause": "JSONA Using %s",
"jsonapiconfiged": "JsonApi Bean Auto Configuration Success",
"jacksonserializers": "MingliUtils Jackson Serializers created"
}
},
"string": {
"StringUtils": {
"format": {
"warn": {
"placeholder": "Placeholder Count: %s, Argument Count: %s",
"template": "Template: %s",
"arguments": "Arguments: [%s]"
}
}
}
}
}
}

View File

@ -0,0 +1,42 @@
{
"com.mingliqiye.utils": {
"i18n": {
"readjson": {
"error": "加载语言文件失败 %s"
}
},
"springboot.autoconfigure": {
"AutoConfiguration": {
"jdkRuntime": "Jdk运行环境版本",
"pid": "程序Pid",
"computerName": "计算机名",
"userName": "用户名",
"time": "当前时间",
"buildTime": "编译时间",
"groupId": "组Id",
"artifactId": "组件Id",
"version": "版本",
"buildJdkVersion": "编译Jdk版本",
"author": "作者",
"website": "官方网址",
"bean": "MingliUtils 自动配置 Bean 成功"
},
"JsonApiAutoConfiguration": {
"jsonause": "JSONA 使用 %s",
"jsonapiconfiged": "JsonApi Bean 自动配置成功",
"jacksonserializers": "MingliUtils Jackson 序列化器注册成功"
}
},
"string": {
"StringUtils": {
"format": {
"warn": {
"placeholder": "占位符数量: %s, 参数数量: %s",
"template": "模板: %s",
"arguments": "参数: [%s]"
}
}
}
}
}
}

View File

@ -0,0 +1,27 @@
{
"schemaVersion": 1,
"id": "mingli-utils",
"groupsId": "${GROUPSID}",
"artifactId": "${ARTIFACTID}",
"name": "Mingli-Utils",
"version": "${VERSIONS}",
"environment": "*",
"license": "Apache-2.0",
"icon": "assets/mingli-utils/icon.png",
"contact": {
"homepage": "https://git.mingliqiye.com/minglipro/mingli-utils",
"issues": "https://git.mingliqiye.com/minglipro/mingli-utils/issues",
"sources": "https://git.mingliqiye.com/minglipro/mingli-utils"
},
"buildTime": "${buildTime}",
"jdk": {
"version": "${JDKVERSIONS}"
},
"authors": [
"minglipro"
],
"depends": {
"fabricloader": "*"
},
"description": "A Java/kotlin Utils"
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 2026 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.test
* CurrentFile BaseTest.kt
* LastUpdate 2026-02-08 03:05:52
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils
import com.mingliqiye.utils.base.code.*
import com.mingliqiye.utils.uuid.UUID
import org.junit.jupiter.api.Test
class BaseTest {
@Test
fun testBase2() {
val uuid = UUID.getV7()
val s = Base2.encode(uuid.toBytes())
assert(uuid == UUID.of(Base2.decode(s)))
}
@Test
fun testBase10() {
val uuid = UUID.getV7()
val s = Base10.encode(uuid.toBytes())
assert(uuid == UUID.of(Base10.decode(s)))
}
@Test
fun testBase16() {
val uuid = UUID.getV7()
val s = Base16.encode(uuid.toBytes())
assert(uuid == UUID.of(Base16.decode(s)))
}
@Test
fun testBase91() {
val uuid = UUID.getV7()
val s = Base91.encode(uuid.toBytes())
assert(uuid == UUID.of(Base91.decode(s)))
}
@Test
fun testBase256() {
val uuid = UUID.getV7()
val s = Base256.encode(uuid.toBytes())
assert(uuid == UUID.of(Base256.decode(s)))
}
}

View File

@ -16,28 +16,33 @@
* ProjectName mingli-utils
* ModuleName mingli-utils.test
* CurrentFile JsonTest.kt
* LastUpdate 2026-02-05 10:57:18
* LastUpdate 2026-02-08 02:29:27
* UpdateUser MingLiPro
*/
package com.mingliqiye.utils
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.mingliqiye.utils.annotation.UUIDJsonFormat
import com.mingliqiye.utils.array.toHexString
import com.mingliqiye.utils.base.BaseType
import com.mingliqiye.utils.io.IO.println
import com.mingliqiye.utils.json.api.JSONA
import com.mingliqiye.utils.json.api.JacksonJsonApi
import com.mingliqiye.utils.json.converters.DateTimeJsonConverter
import com.mingliqiye.utils.json.converters.UUIDJsonConverter
import com.mingliqiye.utils.json.converters.base.JackSonJsonConverter.Companion.addJsonConverter
import com.mingliqiye.utils.json.converters.base.getJsonConverter
import com.mingliqiye.utils.logger.MingLiLoggerFactory
import com.mingliqiye.utils.string.formatd
import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.DateTimeJsonFormat
import com.mingliqiye.utils.time.Formatter
import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUIDFormatType
import com.mingliqiye.utils.uuid.UUIDJsonFormat
import com.mingliqiye.utils.uuid.mysqlToUuid
import com.mingliqiye.utils.uuid.uuidToMysql
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class JsonTest {
@Test
fun testJSONA() {
@ -55,28 +60,72 @@ class JsonTest {
@Test
fun testBANNER() {
val log = MingLiLoggerFactory.getLogger<JsonTest>()
com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration.printBanner()
}
@Test
fun testMysqld() {
val v = UUID.of("c3efb797-0323-11f1-8791-3aff070ec47d")
val ba = uuidToMysql(v.toBytes())
val ca = mysqlToUuid(ba)
assertEquals(
"11F10323C3EFB79787913AFF070EC47D",
ba.toHexString().println()
)
assertEquals(
"C3EFB797032311F187913AFF070EC47D",
ca.toHexString().println()
)
}
@Test
fun testGson2() {
getJsonConverter<UUIDJsonConverter>()
getJsonConverter<DateTimeJsonConverter>()
}
@Test
fun testGson() {
val obm = jacksonObjectMapper()
.addJsonConverter<UUIDJsonConverter>()
.addJsonConverter<DateTimeJsonConverter>()
obm.readValue<AC<CC<ZZ<UUID>>>>(
obm.writeValueAsString(
AC(c = CC(b = ZZ(b = UUID.getV7())))
).println()
).println()
}
}
data class AC<T>(
var a: String = "AC",
@field:DateTimeJsonFormat(Formatter.ISO8601, repcZero = false)
var time: DateTime = DateTime.now(),
@field:UUIDJsonFormat(
base = BaseType.BASE256,
value = UUIDFormatType.UPPER_NO_SPACE
)
var uuid: UUID = UUID.getV4(),
var b: T
var b: BC = BC(),
var c: T
)
data class BC<T>(
data class BC(
var a: String = "BC",
var b: T
)
data class CC<T>(
var a: String = "BC",
var b: T
)
data class ZZ<T>(
var a: String = "ZZ",
@field:UUIDJsonFormat(
base = BaseType.BASE256,
value = UUIDFormatType.UPPER_NO_SPACE
)
var b: T
)

View File

@ -0,0 +1,23 @@
{
"a": {
"b": {
"c": {
"d": "from {} d"
}
}
},
"b": {
"b": {
"c": {
"d": "from {} d"
}
}
},
"c": {
"b": {
"c": {
"d": "from {} d"
}
}
}
}