Merge pull request 'dev' (#11) from dev into master

Reviewed-on: #11
This commit is contained in:
Armamem0t 2025-09-17 21:20:20 +08:00 committed by git.mingliqiye.com
commit 9002f41c63
Signed by: git.mingliqiye.com
GPG Key ID: F810443113074559
10 changed files with 138 additions and 40 deletions

25
NOTICE Normal file
View File

@ -0,0 +1,25 @@
mingli-utils
Copyright 2025 mingliqiye
This product includes software developed by third parties.
The original copyright notices and licenses are reproduced below.
------------------------------------------------------------
https://github.com/jeremyh/jBCrypt (org.mindrot:jbcrypt@0.4)
Copyright (c) 2006 Damien Miller <djm@mindrot.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
------------------------------------------------------------

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils * ModuleName mingli-utils
* CurrentFile build.gradle.kts * CurrentFile build.gradle.kts
* LastUpdate 2025-09-17 11:11:57 * LastUpdate 2025-09-17 12:08:42
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -65,21 +65,19 @@ java {
} }
dependencies { dependencies {
annotationProcessor("org.jetbrains:annotations:24.0.0")
annotationProcessor("org.projectlombok:lombok:1.18.38") implementation("org.slf4j:slf4j-api:2.0.17")
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
// https://github.com/jeremyh/jBCrypt
implementation("org.mindrot:jbcrypt:0.4")
compileOnly("org.springframework.boot:spring-boot-starter:2.7.14") compileOnly("org.springframework.boot:spring-boot-starter:2.7.14")
compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2") compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2")
compileOnly("com.google.code.gson:gson:2.13.1") compileOnly("com.google.code.gson:gson:2.13.1")
compileOnly("org.mybatis:mybatis:3.5.19") compileOnly("org.mybatis:mybatis:3.5.19")
compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58") compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58")
compileOnly("org.projectlombok:lombok:1.18.38")
implementation("org.bouncycastle:bcprov-jdk18on:1.81")
implementation("org.mindrot:jbcrypt:0.4")
implementation("org.jetbrains:annotations:24.0.0")
compileOnly("net.java.dev.jna:jna:5.17.0") compileOnly("net.java.dev.jna:jna:5.17.0")
implementation("org.slf4j:slf4j-api:2.0.17")
implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1")
} }
@ -96,7 +94,8 @@ tasks.withType<JavaExec>().configureEach {
tasks.withType<org.gradle.jvm.tasks.Jar> { tasks.withType<org.gradle.jvm.tasks.Jar> {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from("LICENSE") { into(".") } from("LICENSE") { into("META-INF") }
from("NOTICE") { into("META-INF") }
manifest { manifest {
attributes( attributes(
mapOf( mapOf(

View File

@ -16,13 +16,13 @@
# ProjectName mingli-utils # ProjectName mingli-utils
# ModuleName mingli-utils # ModuleName mingli-utils
# CurrentFile gradle.properties # CurrentFile gradle.properties
# LastUpdate 2025-09-17 11:07:06 # LastUpdate 2025-09-17 21:09:18
# UpdateUser MingLiPro # UpdateUser MingLiPro
# #
JDKVERSIONS=1.8 JDKVERSIONS=1.8
GROUPSID=com.mingliqiye.utils GROUPSID=com.mingliqiye.utils
ARTIFACTID=mingli-utils ARTIFACTID=mingli-utils
VERSIONS=4.1.0 VERSIONS=4.1.4
signing.keyId=B22AA93B signing.keyId=B22AA93B
signing.password= signing.password=
signing.secretKeyRingFile=secret.gpg signing.secretKeyRingFile=secret.gpg

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile Main.kt * CurrentFile Main.kt
* LastUpdate 2025-09-17 10:59:04 * LastUpdate 2025-09-17 19:07:01
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("Main") @file:JvmName("Main")

View File

@ -0,0 +1,60 @@
/*
* Copyright 2025 mingliqiye
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ProjectName mingli-utils
* ModuleName mingli-utils.main
* CurrentFile BCrypt.kt
* LastUpdate 2025-09-17 16:20:30
* UpdateUser MingLiPro
*/
@file:JvmName("BCrypt")
package com.mingliqiye.utils.bcrypt
import java.security.SecureRandom
import org.mindrot.jbcrypt.BCrypt as JBCrypt
fun hashpw(string: String): String {
return hashpw(string, gensalt())
}
fun hashpw(string: String, salt: String = gensalt()): String {
return JBCrypt.hashpw(string, salt)
}
fun checkpw(string: String, bcrypted: String): Boolean {
return JBCrypt.checkpw(string, bcrypted)
}
fun gensalt(): String {
return JBCrypt.gensalt()
}
fun gensalt(long: Int): String {
return JBCrypt.gensalt(long)
}
fun gensalt(long: Int, secureRandom: SecureRandom): String {
return JBCrypt.gensalt(long, secureRandom)
}

View File

@ -16,25 +16,21 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile HashUtils.kt * CurrentFile HashUtils.kt
* LastUpdate 2025-09-15 09:38:04 * LastUpdate 2025-09-17 16:20:57
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("HashUtils") @file:JvmName("HashUtils")
package com.mingliqiye.utils.hash package com.mingliqiye.utils.hash
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.mindrot.jbcrypt.BCrypt import com.mingliqiye.utils.bcrypt.checkpw
import com.mingliqiye.utils.bcrypt.hashpw
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.IOException import java.io.IOException
import java.security.MessageDigest import java.security.MessageDigest
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
import java.security.Security
private val _addProvider = run {
Security.addProvider(BouncyCastleProvider())
}
/** /**
* 计算指定文件的哈希值 * 计算指定文件的哈希值
@ -92,7 +88,7 @@ private fun bytesToHex(bytes: ByteArray): String {
* @return 加密后的 BCrypt 哈希字符串 * @return 加密后的 BCrypt 哈希字符串
*/ */
fun bcrypt(string: String): String { fun bcrypt(string: String): String {
return BCrypt.hashpw(string, BCrypt.gensalt()) return hashpw(string)
} }
/** /**
@ -103,5 +99,5 @@ fun bcrypt(string: String): String {
* @return 如果匹配返回 true否则返回 false * @return 如果匹配返回 true否则返回 false
*/ */
fun checkBcrypt(string: String, bcrypted: String): Boolean { fun checkBcrypt(string: String, bcrypted: String): Boolean {
return BCrypt.checkpw(string, bcrypted) return checkpw(string, bcrypted)
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile JsonStringConverter.kt * CurrentFile JsonStringConverter.kt
* LastUpdate 2025-09-15 11:03:53 * LastUpdate 2025-09-17 19:09:17
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -35,7 +35,6 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import com.mingliqiye.utils.time.DateTime import com.mingliqiye.utils.time.DateTime
import com.mingliqiye.utils.time.DateTime.Companion.parse import com.mingliqiye.utils.time.DateTime.Companion.parse
import com.mingliqiye.utils.time.Formatter
import com.mingliqiye.utils.uuid.UUID import com.mingliqiye.utils.uuid.UUID
import com.mingliqiye.utils.uuid.UUID.Companion.of import com.mingliqiye.utils.uuid.UUID.Companion.of
import java.io.IOException import java.io.IOException
@ -219,7 +218,7 @@ class DateTimeJsonConverter : JsonStringConverter<DateTime>() {
if (obj == null) { if (obj == null) {
return null return null
} }
return obj.format(Formatter.STANDARD_DATETIME) return obj.format()
} }
override fun deConvert(obj: String?): DateTime? { override fun deConvert(obj: String?): DateTime? {
@ -227,9 +226,7 @@ class DateTimeJsonConverter : JsonStringConverter<DateTime>() {
return null return null
} }
return parse( return parse(
obj, obj
Formatter.STANDARD_DATETIME_MILLISECOUND7,
true
) )
} }
} }

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile StringUtils.kt * CurrentFile StringUtils.kt
* LastUpdate 2025-09-15 22:32:50 * LastUpdate 2025-09-17 21:09:10
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@file:JvmName("StringUtils") @file:JvmName("StringUtils")
@ -28,14 +28,17 @@ import com.mingliqiye.utils.logger.mingLiLoggerFactory
val log = mingLiLoggerFactory.getLogger("StringUtils") val log = mingLiLoggerFactory.getLogger("StringUtils")
val NULLISH_STRINGS = setOf("null", "NaN", "undefined", "None", "none")
/** /**
* 判断`字符串`是否为空 * 判断`字符串`是否为空
* *
* @param str 待判断的字符串 * @param str 待判断的字符串
* @return `true`: `false`: 非空 * @return `true`: `false`: 非空
*/ */
fun isEmpty(str: String?): Boolean { @JvmName("isEmpty")
return str?.isEmpty() != null fun String?.isNullish(): Boolean {
return this == null || this.isBlank() || this in NULLISH_STRINGS
} }
/** /**

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile DateTime.kt * CurrentFile DateTime.kt
* LastUpdate 2025-09-17 08:40:14 * LastUpdate 2025-09-17 19:06:39
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -95,6 +95,8 @@ enum class Formatter(private val value: String) {
* 标准日期时间格式(7位毫秒)yyyy-MM-dd HH:mm:ss.SSSSSSS * 标准日期时间格式(7位毫秒)yyyy-MM-dd HH:mm:ss.SSSSSSS
*/ */
STANDARD_DATETIME_MILLISECOUND7("yyyy-MM-dd HH:mm:ss.SSSSSSS"), STANDARD_DATETIME_MILLISECOUND7("yyyy-MM-dd HH:mm:ss.SSSSSSS"),
STANDARD_DATETIME_MILLISECOUND8("yyyy-MM-dd HH:mm:ss.SSSSSSSS"),
STANDARD_DATETIME_MILLISECOUND9("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"),
/** /**
* 标准日期时间格式(6位毫秒)yyyy-MM-dd HH:mm:ss.SSSSSS * 标准日期时间格式(6位毫秒)yyyy-MM-dd HH:mm:ss.SSSSSS
@ -151,6 +153,7 @@ enum class Formatter(private val value: String) {
*/ */
COMPACT_DATETIME("yyyyMMddHHmmss"); COMPACT_DATETIME("yyyyMMddHHmmss");
private val len: Int = value.length private val len: Int = value.length
fun getLen(): Int { fun getLen(): Int {
@ -276,6 +279,20 @@ class DateTime private constructor(
) )
} }
@JvmStatic
fun parse(
timestr: String
): DateTime {
val formatterString = Formatter.STANDARD_DATETIME_MILLISECOUND9.getValue()
return DateTime(
LocalDateTime.parse(
getFillZeroByLen(timestr, formatterString),
DateTimeFormatter.ofPattern(formatterString)
)
)
}
/** /**
* 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例 * 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例
* *
@ -332,7 +349,7 @@ class DateTime private constructor(
modifiedDstr += "." modifiedDstr += "."
} }
val sb = StringBuilder(modifiedDstr) val sb = StringBuilder(modifiedDstr)
for (i in 0 until formats.length - dstr.length) { for (i in 0 until formats.length - sb.length) {
sb.append("0") sb.append("0")
} }
return sb.toString() return sb.toString()
@ -533,6 +550,10 @@ class DateTime private constructor(
return format(formatter.getValue()) return format(formatter.getValue())
} }
fun format(): String {
return format(Formatter.STANDARD_DATETIME_MILLISECOUND9.getValue(), true)
}
/** /**
* 使用指定格式化模板将当前时间格式化为字符串并可选择是否去除末尾多余的零 * 使用指定格式化模板将当前时间格式化为字符串并可选择是否去除末尾多余的零
* *
@ -569,9 +590,7 @@ class DateTime private constructor(
* @return 返回标准格式的时间字符串 * @return 返回标准格式的时间字符串
*/ */
override fun toString(): String { override fun toString(): String {
return String.format( return "DateTime(${format()})"
"DateTime(%s)", format(Formatter.STANDARD_DATETIME_MILLISECOUND7, true)
)
} }
/** /**

View File

@ -16,7 +16,7 @@
* ProjectName mingli-utils * ProjectName mingli-utils
* ModuleName mingli-utils.main * ModuleName mingli-utils.main
* CurrentFile UUID.kt * CurrentFile UUID.kt
* LastUpdate 2025-09-17 11:04:08 * LastUpdate 2025-09-17 16:27:32
* UpdateUser MingLiPro * UpdateUser MingLiPro
*/ */
@ -183,7 +183,6 @@ class UUID : Serializable {
@JvmStatic @JvmStatic
fun getV7(): UUID { fun getV7(): UUID {
val instant = DateTime.now().toMillisecondTime() val instant = DateTime.now().toMillisecondTime()
println(instant.toString(16))
val buffer = ByteBuffer.allocate(16) val buffer = ByteBuffer.allocate(16)
buffer.putInt((instant shr 16).toInt()) buffer.putInt((instant shr 16).toInt())
buffer.putShort((instant).toShort()) buffer.putShort((instant).toShort())