ludc
2024-04-08 197a03ea2d5e38496d5495ee8bc0d4e127f233cf
工具类添加
已修改4个文件
已添加22个文件
8113 ■■■■■ 文件已修改
Source/platformProject/pom.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/pom.xml 401 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/service/impl/UIDataServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/service/impl/UIEngineServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/support/StrSpliter.java 501 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Base64Util.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/CharPool.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Charsets.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/CollectionUtil.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/ConcurrentDateFormat.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DatatypeConverterUtil.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DateTimeUtil.java 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DateUtil.java 634 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DigestUtil.java 433 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Exceptions.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/FileUtil.java 383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Func.java 2144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Holder.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/IoUtil.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/NumberUtil.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/ObjectUtil.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/RandomType.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/StringPool.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/StringUtil.java 1560 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/jackson/BladeJavaTimeModule.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/jackson/JsonUtil.java 705 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/platformProject/pom.xml
@@ -20,6 +20,8 @@
        <old.spring.version>3.2.0.RELEASE</old.spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <lombok.version>1.18.22</lombok.version>
        <jackson.version>2.13.3</jackson.version>
    </properties>
    <!-- <distributionManagement>
Source/platformProject/vci-platform-web/pom.xml
@@ -12,183 +12,192 @@
    <artifactId>vci-platform-web</artifactId>
    <dependencies>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-starter-parent</artifactId>
           <version>1.0-SNAPSHOT</version>
           <type>pom</type>
       </dependency>
       <dependency>
           <groupId>com.vci.corba</groupId>
           <artifactId>plt-slice</artifactId>
           <version>1.0.RELEASE</version>
       </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-starter-parent</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.vci.corba</groupId>
            <artifactId>plt-slice</artifactId>
            <version>1.0.RELEASE</version>
        </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-starter-web</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>org.apache.logging.log4j</groupId>
                   <artifactId>*</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>com.google.guava</groupId>
                   <artifactId>guava</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-starter-corba</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency><!--文件的信息-->
           <groupId>com.vci</groupId>
           <artifactId>vci-file-api</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>org.apache.logging.log4j</groupId>
                   <artifactId>*</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-file-integration</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-starter-word</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>com.vci</groupId>
                   <artifactId>vci-starter-web</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-starter-poi</artifactId>
           <version>1.0-SNAPSHOT</version>
           <exclusions>
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-thymeleaf</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>com.vci</groupId>
                   <artifactId>vci-starter-web</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>eu.bitwalker</groupId>
           <artifactId>UserAgentUtils</artifactId>
           <version>1.20</version>
       </dependency>
       <!--开启 cache ç¼“å­˜ -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-cache</artifactId>
           <version>2.1.3.RELEASE</version>
       </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-starter-web</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-starter-corba</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency><!--文件的信息-->
            <groupId>com.vci</groupId>
            <artifactId>vci-file-api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-file-integration</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-starter-word</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.vci</groupId>
                    <artifactId>vci-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-starter-poi</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-thymeleaf</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.vci</groupId>
                    <artifactId>vci-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.20</version>
        </dependency>
        <!--开启 cache ç¼“å­˜ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
       <!-- ehcache缓存 -->
       <dependency>
           <groupId>net.sf.ehcache</groupId>
           <artifactId>ehcache</artifactId>
           <version>2.9.1</version><!--$NO-MVN-MAN-VER$ -->
       </dependency>
        <!-- ehcache缓存 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.9.1</version><!--$NO-MVN-MAN-VER$ -->
        </dependency>
       <dependency><!--java bean å’Œxml转换-->
           <groupId>com.thoughtworks.xstream</groupId>
           <artifactId>xstream</artifactId>
           <version>1.4.10</version>
       </dependency>
       <dependency><!--代码生成器所需模板-->
           <artifactId>velocity</artifactId>
           <groupId>org.apache.velocity</groupId>
           <version>1.7</version>
       </dependency>
       <dependency><!--数据库操作工具-->
           <groupId>com.vci.platform</groupId>
           <artifactId>ddlTool-client</artifactId>
           <version>${vciplt.version}</version>
       </dependency>
       <dependency><!--数据库操作工具-->
           <groupId>com.vci.platform</groupId>
           <artifactId>ddlTool-common</artifactId>
           <version>${vciplt.version}</version>
       </dependency>
       <dependency>
           <groupId>com.vci.client</groupId>
           <artifactId>plt-clientbase</artifactId>
           <version>1.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>com.zeroc</groupId>
           <artifactId>icegridgui</artifactId>
           <version>1.0.RELEASE</version>
       </dependency>
        <dependency><!--java bean å’Œxml转换-->
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.10</version>
        </dependency>
        <dependency><!--代码生成器所需模板-->
            <artifactId>velocity</artifactId>
            <groupId>org.apache.velocity</groupId>
            <version>1.7</version>
        </dependency>
        <dependency><!--数据库操作工具-->
            <groupId>com.vci.platform</groupId>
            <artifactId>ddlTool-client</artifactId>
            <version>${vciplt.version}</version>
        </dependency>
        <dependency><!--数据库操作工具-->
            <groupId>com.vci.platform</groupId>
            <artifactId>ddlTool-common</artifactId>
            <version>${vciplt.version}</version>
        </dependency>
        <dependency>
            <groupId>com.vci.client</groupId>
            <artifactId>plt-clientbase</artifactId>
            <version>1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.zeroc</groupId>
            <artifactId>icegridgui</artifactId>
            <version>1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.vci.common</groupId>
            <artifactId>plt-common</artifactId>
            <version>1.0.RELEASE</version>
        </dependency>
       <dependency>
           <groupId>com.vci</groupId>
           <artifactId>vci-platform-starter</artifactId>
           <version>2022.1-SNAPSHOT</version>
       </dependency>
        <dependency>
            <groupId>com.vci</groupId>
            <artifactId>vci-platform-starter</artifactId>
            <version>2022.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
       <dependency>
           <groupId>org.reflections</groupId>
           <artifactId>reflections</artifactId>
           <version>0.9.11</version>
       </dependency>
       <!--redis start-->
       <dependency>
           <groupId>org.springframework.data</groupId>
           <artifactId>spring-data-redis</artifactId>
           <version>2.1.5.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>2.9.0</version>
       </dependency>
       <!--redis end-->
   </dependencies>
        <!--redis start-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!--redis end-->
    </dependencies>
    <build>
        <finalName>vci-platform-web</finalName>
@@ -211,34 +220,34 @@
                    </excludes>
                </configuration>
            </plugin>
<!--            <plugin>-->
<!--                <groupId>org.springframework.boot</groupId>-->
<!--                <artifactId>spring-boot-maven-plugin</artifactId>-->
<!--                <configuration>-->
<!--                    &lt;!&ndash;重写包含依赖,包含不存在的依赖,jar里没有pom里的依赖&ndash;&gt;-->
<!--                    <includes>-->
<!--                        <include>-->
<!--                            <groupId>null</groupId>-->
<!--                            <artifactId>null</artifactId>-->
<!--                        </include>-->
<!--                    </includes>-->
<!--                    <layout>ZIP</layout>-->
<!--                    &lt;!&ndash;使用外部配置文件,jar包里没有资源文件&ndash;&gt;-->
<!--                    <addResources>true</addResources>-->
<!--                </configuration>-->
<!--                <executions>-->
<!--                    <execution>-->
<!--                        <goals>-->
<!--                            <goal>repackage</goal>-->
<!--                        </goals>-->
<!--                        <configuration>-->
<!--                            &lt;!&ndash;配置jar包特殊标识 é…ç½®åŽï¼Œä¿ç•™åŽŸæ–‡ä»¶ï¼Œç”Ÿæˆæ–°æ–‡ä»¶ *-run.jar &ndash;&gt;-->
<!--                            &lt;!&ndash;配置jar包特殊标识 ä¸é…ç½®ï¼ŒåŽŸæ–‡ä»¶å‘½åä¸º *.jar.original,生成新文件 *.jar &ndash;&gt;-->
<!--                            &lt;!&ndash;<classifier>run</classifier>&ndash;&gt;-->
<!--                        </configuration>-->
<!--                    </execution>-->
<!--                </executions>-->
<!--            </plugin>-->
            <!--            <plugin>-->
            <!--                <groupId>org.springframework.boot</groupId>-->
            <!--                <artifactId>spring-boot-maven-plugin</artifactId>-->
            <!--                <configuration>-->
            <!--                    &lt;!&ndash;重写包含依赖,包含不存在的依赖,jar里没有pom里的依赖&ndash;&gt;-->
            <!--                    <includes>-->
            <!--                        <include>-->
            <!--                            <groupId>null</groupId>-->
            <!--                            <artifactId>null</artifactId>-->
            <!--                        </include>-->
            <!--                    </includes>-->
            <!--                    <layout>ZIP</layout>-->
            <!--                    &lt;!&ndash;使用外部配置文件,jar包里没有资源文件&ndash;&gt;-->
            <!--                    <addResources>true</addResources>-->
            <!--                </configuration>-->
            <!--                <executions>-->
            <!--                    <execution>-->
            <!--                        <goals>-->
            <!--                            <goal>repackage</goal>-->
            <!--                        </goals>-->
            <!--                        <configuration>-->
            <!--                            &lt;!&ndash;配置jar包特殊标识 é…ç½®åŽï¼Œä¿ç•™åŽŸæ–‡ä»¶ï¼Œç”Ÿæˆæ–°æ–‡ä»¶ *-run.jar &ndash;&gt;-->
            <!--                            &lt;!&ndash;配置jar包特殊标识 ä¸é…ç½®ï¼ŒåŽŸæ–‡ä»¶å‘½åä¸º *.jar.original,生成新文件 *.jar &ndash;&gt;-->
            <!--                            &lt;!&ndash;<classifier>run</classifier>&ndash;&gt;-->
            <!--                        </configuration>-->
            <!--                    </execution>-->
            <!--                </executions>-->
            <!--            </plugin>-->
        </plugins>
    </build>
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/service/impl/UIDataServiceImpl.java
@@ -5,7 +5,6 @@
import com.vci.frameworkcore.lcstatuspck.FrameworkDataLCStatus;
import com.vci.frameworkcore.lcstatuspck.ReleaseDataLCStatus;
import com.vci.starter.revision.bo.TreeWrapperOptions;
import com.vci.starter.revision.service.RevisionModelUtil;
import com.vci.starter.web.annotation.bus.VciChangeDataAfter;
import com.vci.starter.web.annotation.bus.VciChangeDataBefore;
import com.vci.starter.web.annotation.bus.VciChangeDataPlugin;
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/service/impl/UIEngineServiceImpl.java
@@ -507,7 +507,9 @@
    @Override
    @VciUnLog
    public UITableDefineVO tableDO2VO(PortalVI portal, boolean queryDetail) {
        if(){
        }
        UITableDefineVO tableDefineVO = new UITableDefineVO();
        tableDefineVO.setOid(portal.id);
        tableDefineVO.setId(portal.viName);
@@ -1275,6 +1277,7 @@
                        throw new VciBaseException("{0}里的表格{1}不存在", new String[]{btmType, componentDefineXO.getTemplateId()});
                    }
                    componentVO.setTableDefineVO(tableDefineVOMap.get(key));
                }else{
                    try {
                        componentVO.setTableDefineVO(tableDO2VO(ServiceProvider.getUIService().getPortalVIByTypeNameAndVIName(btmType,componentDefineXO.getTemplateId()),true));
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/support/StrSpliter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,501 @@
package com.vci.web.support;
import com.vci.web.util.StringUtil;
import com.vci.web.util.Func;
import com.vci.web.util.StringPool;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * å­—符串切分器
 *
 * @author Looly
 */
public class StrSpliter {
    //---------------------------------------------------------------------------------------------- Split by char
    /**
     * åˆ‡åˆ†å­—符串路径,仅支持Unix分界符:/
     *
     * @param str è¢«åˆ‡åˆ†çš„字符串
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> splitPath(String str) {
        return splitPath(str, 0);
    }
    /**
     * åˆ‡åˆ†å­—符串路径,仅支持Unix分界符:/
     *
     * @param str è¢«åˆ‡åˆ†çš„字符串
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitPathToArray(String str) {
        return toArray(splitPath(str));
    }
    /**
     * åˆ‡åˆ†å­—符串路径,仅支持Unix分界符:/
     *
     * @param str   è¢«åˆ‡åˆ†çš„字符串
     * @param limit é™åˆ¶åˆ†ç‰‡æ•°
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> splitPath(String str, int limit) {
        return split(str, StringPool.SLASH, limit, true, true);
    }
    /**
     * åˆ‡åˆ†å­—符串路径,仅支持Unix分界符:/
     *
     * @param str   è¢«åˆ‡åˆ†çš„字符串
     * @param limit é™åˆ¶åˆ†ç‰‡æ•°
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitPathToArray(String str, int limit) {
        return toArray(splitPath(str, limit));
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitTrim(String str, char separator, boolean ignoreEmpty) {
        return split(str, separator, 0, true, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, char separator, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, 0, isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串,大小写敏感,去除每个元素两边空白符
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> splitTrim(String str, char separator, int limit, boolean ignoreEmpty) {
        return split(str, separator, limit, true, ignoreEmpty, false);
    }
    /**
     * åˆ‡åˆ†å­—符串,大小写敏感
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, limit, isTrim, ignoreEmpty, false);
    }
    /**
     * åˆ‡åˆ†å­—符串,忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitIgnoreCase(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, limit, isTrim, ignoreEmpty, true);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @param ignoreCase  æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) {
        if (StringUtil.isEmpty(str)) {
            return new ArrayList<String>(0);
        }
        if (limit == 1) {
            return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty);
        }
        final ArrayList<String> list = new ArrayList<>(limit > 0 ? limit : 16);
        int len = str.length();
        int start = 0;
        for (int i = 0; i < len; i++) {
            if (Func.equals(separator, str.charAt(i))) {
                addToList(list, str.substring(start, i), isTrim, ignoreEmpty);
                start = i + 1;
                //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串)
                if (limit > 0 && list.size() > limit - 2) {
                    break;
                }
            }
        }
        return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串为字符串数组
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitToArray(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return toArray(split(str, separator, limit, isTrim, ignoreEmpty));
    }
    //---------------------------------------------------------------------------------------------- Split by String
    /**
     * åˆ‡åˆ†å­—符串,不忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, String separator, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, -1, isTrim, ignoreEmpty, false);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除每个元素两边空格,忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitTrim(String str, String separator, boolean ignoreEmpty) {
        return split(str, separator, true, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串,不忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, limit, isTrim, ignoreEmpty, false);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除每个元素两边空格,忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitTrim(String str, String separator, int limit, boolean ignoreEmpty) {
        return split(str, separator, limit, true, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串,忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitIgnoreCase(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, limit, isTrim, ignoreEmpty, true);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除每个元素两边空格,忽略大小写
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> splitTrimIgnoreCase(String str, String separator, int limit, boolean ignoreEmpty) {
        return split(str, separator, limit, true, ignoreEmpty, true);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符串
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @param ignoreCase  æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.1
     */
    public static List<String> split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) {
        if (StringUtil.isEmpty(str)) {
            return new ArrayList<String>(0);
        }
        if (limit == 1) {
            return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty);
        }
        if (StringUtil.isEmpty(separator)) {
            return split(str, limit);
        } else if (separator.length() == 1) {
            return split(str, separator.charAt(0), limit, isTrim, ignoreEmpty, ignoreCase);
        }
        final ArrayList<String> list = new ArrayList<>();
        int len = str.length();
        int separatorLen = separator.length();
        int start = 0;
        int i = 0;
        while (i < len) {
            i = StringUtil.indexOf(str, separator, start, ignoreCase);
            if (i > -1) {
                addToList(list, str.substring(start, i), isTrim, ignoreEmpty);
                start = i + separatorLen;
                //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串)
                if (limit > 0 && list.size() > limit - 2) {
                    break;
                }
            } else {
                break;
            }
        }
        return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串为字符串数组
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitToArray(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        return toArray(split(str, separator, limit, isTrim, ignoreEmpty));
    }
    //---------------------------------------------------------------------------------------------- Split by Whitespace
    /**
     * ä½¿ç”¨ç©ºç™½ç¬¦åˆ‡åˆ†å­—符串<br>
     * åˆ‡åˆ†åŽçš„字符串两边不包含空白符,空串或空白符串并不做为元素之一
     *
     * @param str   è¢«åˆ‡åˆ†çš„字符串
     * @param limit é™åˆ¶åˆ†ç‰‡æ•°
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, int limit) {
        if (StringUtil.isEmpty(str)) {
            return new ArrayList<String>(0);
        }
        if (limit == 1) {
            return addToList(new ArrayList<String>(1), str, true, true);
        }
        final ArrayList<String> list = new ArrayList<>();
        int len = str.length();
        int start = 0;
        for (int i = 0; i < len; i++) {
            if (Func.isEmpty(str.charAt(i))) {
                addToList(list, str.substring(start, i), true, true);
                start = i + 1;
                if (limit > 0 && list.size() > limit - 2) {
                    break;
                }
            }
        }
        return addToList(list, str.substring(start, len), true, true);
    }
    /**
     * åˆ‡åˆ†å­—符串为字符串数组
     *
     * @param str   è¢«åˆ‡åˆ†çš„字符串
     * @param limit é™åˆ¶åˆ†ç‰‡æ•°
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitToArray(String str, int limit) {
        return toArray(split(str, limit));
    }
    //---------------------------------------------------------------------------------------------- Split by regex
    /**
     * é€šè¿‡æ­£åˆ™åˆ‡åˆ†å­—符串
     *
     * @param str              å­—符串
     * @param separatorPattern åˆ†éš”符正则{@link Pattern}
     * @param limit            é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim           æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty      æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) {
        if (StringUtil.isEmpty(str)) {
            return new ArrayList<String>(0);
        }
        if (limit == 1) {
            return addToList(new ArrayList<String>(1), str, isTrim, ignoreEmpty);
        }
        if (null == separatorPattern) {
            return split(str, limit);
        }
        final Matcher matcher = separatorPattern.matcher(str);
        final ArrayList<String> list = new ArrayList<>();
        int len = str.length();
        int start = 0;
        while (matcher.find()) {
            addToList(list, str.substring(start, matcher.start()), isTrim, ignoreEmpty);
            start = matcher.end();
            if (limit > 0 && list.size() > limit - 2) {
                break;
            }
        }
        return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);
    }
    /**
     * é€šè¿‡æ­£åˆ™åˆ‡åˆ†å­—符串为字符串数组
     *
     * @param str              è¢«åˆ‡åˆ†çš„字符串
     * @param separatorPattern åˆ†éš”符正则{@link Pattern}
     * @param limit            é™åˆ¶åˆ†ç‰‡æ•°
     * @param isTrim           æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty      æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static String[] splitToArray(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) {
        return toArray(split(str, separatorPattern, limit, isTrim, ignoreEmpty));
    }
    //---------------------------------------------------------------------------------------------- Split by length
    /**
     * æ ¹æ®ç»™å®šé•¿åº¦ï¼Œå°†ç»™å®šå­—符串截取为多个部分
     *
     * @param str å­—符串
     * @param len æ¯ä¸€ä¸ªå°èŠ‚çš„é•¿åº¦
     * @return æˆªå–后的字符串数组
     */
    public static String[] splitByLength(String str, int len) {
        int partCount = str.length() / len;
        int lastPartCount = str.length() % len;
        int fixPart = 0;
        if (lastPartCount != 0) {
            fixPart = 1;
        }
        final String[] strs = new String[partCount + fixPart];
        for (int i = 0; i < partCount + fixPart; i++) {
            if (i == partCount + fixPart - 1 && lastPartCount != 0) {
                strs[i] = str.substring(i * len, i * len + lastPartCount);
            } else {
                strs[i] = str.substring(i * len, i * len + len);
            }
        }
        return strs;
    }
    //---------------------------------------------------------------------------------------------------------- Private method start
    /**
     * å°†å­—符串加入List中
     *
     * @param list        åˆ—表
     * @param part        è¢«åŠ å…¥çš„éƒ¨åˆ†
     * @param isTrim      æ˜¯å¦åŽ»é™¤ä¸¤ç«¯ç©ºç™½ç¬¦
     * @param ignoreEmpty æ˜¯å¦ç•¥è¿‡ç©ºå­—符串(空字符串不做为一个元素)
     * @return åˆ—表
     */
    private static List<String> addToList(List<String> list, String part, boolean isTrim, boolean ignoreEmpty) {
        part = part.toString();
        if (isTrim) {
            part = part.trim();
        }
        if (false == ignoreEmpty || false == part.isEmpty()) {
            list.add(part);
        }
        return list;
    }
    /**
     * List转Array
     *
     * @param list List
     * @return Array
     */
    private static String[] toArray(List<String> list) {
        return list.toArray(new String[list.size()]);
    }
    //---------------------------------------------------------------------------------------------------------- Private method end
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Base64Util.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
/**
 * Base64工具
 *
 * @author L.cm
 */
public class Base64Util extends org.springframework.util.Base64Utils {
    /**
     * ç¼–码
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String encode(String value) {
        return Base64Util.encode(value, Charsets.UTF_8);
    }
    /**
     * ç¼–码
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String encode(String value, java.nio.charset.Charset charset) {
        byte[] val = value.getBytes(charset);
        return new String(Base64Util.encode(val), charset);
    }
    /**
     * ç¼–码URL安全
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String encodeUrlSafe(String value) {
        return Base64Util.encodeUrlSafe(value, Charsets.UTF_8);
    }
    /**
     * ç¼–码URL安全
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String encodeUrlSafe(String value, java.nio.charset.Charset charset) {
        byte[] val = value.getBytes(charset);
        return new String(Base64Util.encodeUrlSafe(val), charset);
    }
    /**
     * è§£ç 
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String decode(String value) {
        return Base64Util.decode(value, Charsets.UTF_8);
    }
    /**
     * è§£ç 
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String decode(String value, java.nio.charset.Charset charset) {
        byte[] val = value.getBytes(charset);
        byte[] decodedValue = Base64Util.decode(val);
        return new String(decodedValue, charset);
    }
    /**
     * è§£ç URL安全
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String decodeUrlSafe(String value) {
        return Base64Util.decodeUrlSafe(value, Charsets.UTF_8);
    }
    /**
     * è§£ç URL安全
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String decodeUrlSafe(String value, java.nio.charset.Charset charset) {
        byte[] val = value.getBytes(charset);
        byte[] decodedValue = Base64Util.decodeUrlSafe(val);
        return new String(decodedValue, charset);
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/CharPool.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.vci.web.util;
/**
 * char å¸¸é‡æ± 
 *
 * @author L.cm
 */
public interface CharPool {
    // @formatter:off
    char UPPER_A          = 'A';
    char LOWER_A          = 'a';
    char UPPER_Z          = 'Z';
    char LOWER_Z          = 'z';
    char DOT              = '.';
    char AT               = '@';
    char LEFT_BRACE       = '{';
    char RIGHT_BRACE      = '}';
    char LEFT_BRACKET     = '(';
    char RIGHT_BRACKET    = ')';
    char DASH             = '-';
    char PERCENT          = '%';
    char PIPE             = '|';
    char PLUS             = '+';
    char QUESTION_MARK    = '?';
    char EXCLAMATION_MARK = '!';
    char EQUALS           = '=';
    char AMPERSAND        = '&';
    char ASTERISK         = '*';
    char STAR             = ASTERISK;
    char BACK_SLASH       = '\\';
    char COLON            = ':';
    char COMMA            = ',';
    char DOLLAR           = '$';
    char SLASH            = '/';
    char HASH             = '#';
    char HAT              = '^';
    char LEFT_CHEV        = '<';
    char NEWLINE          = '\n';
    char N                = 'n';
    char Y                = 'y';
    char QUOTE            = '\"';
    char RETURN           = '\r';
    char TAB              = '\t';
    char RIGHT_CHEV       = '>';
    char SEMICOLON        = ';';
    char SINGLE_QUOTE     = '\'';
    char BACKTICK         = '`';
    char SPACE            = ' ';
    char TILDA            = '~';
    char LEFT_SQ_BRACKET  = '[';
    char RIGHT_SQ_BRACKET = ']';
    char UNDERSCORE       = '_';
    char ONE              = '1';
    char ZERO             = '0';
    // @formatter:on
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Charsets.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
/**
 * å­—符集工具类
 *
 * @author L.cm
 */
public class Charsets {
    /**
     * å­—符集ISO-8859-1
     */
    public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
    public static final String ISO_8859_1_NAME = ISO_8859_1.name();
    /**
     * å­—符集GBK
     */
    public static final Charset GBK = Charset.forName(StringPool.GBK);
    public static final String GBK_NAME = GBK.name();
    /**
     * å­—符集utf-8
     */
    public static final Charset UTF_8 = StandardCharsets.UTF_8;
    public static final String UTF_8_NAME = UTF_8.name();
    /**
     * è½¬æ¢ä¸ºCharset对象
     *
     * @param charsetName å­—符集,为空则返回默认字符集
     * @return Charsets
     * @throws UnsupportedCharsetException ç¼–码不支持
     */
    public static Charset charset(String charsetName) throws UnsupportedCharsetException {
        return StringUtil.isBlank(charsetName) ? Charset.defaultCharset() : Charset.forName(charsetName);
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/CollectionUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,161 @@
package com.vci.web.util;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;
/**
 * é›†åˆå·¥å…·ç±»
 *
 * @author L.cm
 */
public class CollectionUtil extends CollectionUtils {
    /**
     * Return {@code true} if the supplied Collection is not {@code null} or empty.
     * Otherwise, return {@code false}.
     *
     * @param collection the Collection to check
     * @return whether the given Collection is not empty
     */
    public static boolean isNotEmpty(@Nullable Collection<?> collection) {
        return !CollectionUtil.isEmpty(collection);
    }
    /**
     * Return {@code true} if the supplied Map is not {@code null} or empty.
     * Otherwise, return {@code false}.
     *
     * @param map the Map to check
     * @return whether the given Map is not empty
     */
    public static boolean isNotEmpty(@Nullable Map<?, ?> map) {
        return !CollectionUtil.isEmpty(map);
    }
    /**
     * Check whether the given Array contains the given element.
     *
     * @param array   the Array to check
     * @param element the element to look for
     * @param <T>     The generic tag
     * @return {@code true} if found, {@code false} else
     */
    public static <T> boolean contains(@Nullable T[] array, final T element) {
        if (array == null) {
            return false;
        }
        return Arrays.stream(array).anyMatch(x -> ObjectUtil.nullSafeEquals(x, element));
    }
    /**
     * Concatenates 2 arrays
     *
     * @param one   æ•°ç»„1
     * @param other æ•°ç»„2
     * @return æ–°æ•°ç»„
     */
    public static String[] concat(String[] one, String[] other) {
        return concat(one, other, String.class);
    }
    /**
     * Concatenates 2 arrays
     *
     * @param one   æ•°ç»„1
     * @param other æ•°ç»„2
     * @param clazz æ•°ç»„ç±»
     * @return æ–°æ•°ç»„
     */
    public static <T> T[] concat(T[] one, T[] other, Class<T> clazz) {
        T[] target = (T[]) Array.newInstance(clazz, one.length + other.length);
        System.arraycopy(one, 0, target, 0, one.length);
        System.arraycopy(other, 0, target, one.length, other.length);
        return target;
    }
    /**
     * å¯¹è±¡æ˜¯å¦ä¸ºæ•°ç»„对象
     *
     * @param obj å¯¹è±¡
     * @return æ˜¯å¦ä¸ºæ•°ç»„对象,如果为{@code null} è¿”回false
     */
    public static boolean isArray(Object obj) {
        if (null == obj) {
            return false;
        }
        return obj.getClass().isArray();
    }
    /**
     * ä¸å¯å˜ Set
     *
     * @param es  å¯¹è±¡
     * @param <E> æ³›åž‹
     * @return é›†åˆ
     */
    @SafeVarargs
    public static <E> Set<E> ofImmutableSet(E... es) {
        Objects.requireNonNull(es, "args es is null.");
        return Arrays.stream(es).collect(Collectors.toSet());
    }
    /**
     * ä¸å¯å˜ List
     *
     * @param es  å¯¹è±¡
     * @param <E> æ³›åž‹
     * @return é›†åˆ
     */
    @SafeVarargs
    public static <E> List<E> ofImmutableList(E... es) {
        Objects.requireNonNull(es, "args es is null.");
        return Arrays.stream(es).collect(Collectors.toList());
    }
    /**
     * Iterable è½¬æ¢ä¸ºList集合
     *
     * @param elements Iterable
     * @param <E>      æ³›åž‹
     * @return é›†åˆ
     */
    public static <E> List<E> toList(Iterable<E> elements) {
        Objects.requireNonNull(elements, "elements es is null.");
        if (elements instanceof Collection) {
            return new ArrayList((Collection) elements);
        }
        Iterator<E> iterator = elements.iterator();
        List<E> list = new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }
    /**
     * å°†key value æ•°ç»„转为 map
     *
     * @param keysValues key value æ•°ç»„
     * @param <K>        key
     * @param <V>        value
     * @return map é›†åˆ
     */
    public static <K, V> Map<K, V> toMap(Object... keysValues) {
        int kvLength = keysValues.length;
        if (kvLength % 2 != 0) {
            throw new IllegalArgumentException("wrong number of arguments for met, keysValues length can not be odd");
        }
        Map<K, V> keyValueMap = new HashMap<>(kvLength);
        for (int i = kvLength - 2; i >= 0; i -= 2) {
            Object key = keysValues[i];
            Object value = keysValues[i + 1];
            keyValueMap.put((K) key, (V) value);
        }
        return keyValueMap;
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/ConcurrentDateFormat.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,87 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Queue;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
 * å‚考tomcat8中的并发DateFormat
 * <p>
 * {@link SimpleDateFormat}的线程安全包装器。
 * ä¸ä½¿ç”¨ThreadLocal,创建足够的SimpleDateFormat对象来满足并发性要求。
 * </p>
 *
 * @author L.cm
 */
public class ConcurrentDateFormat {
    private final String format;
    private final Locale locale;
    private final TimeZone timezone;
    private final Queue<SimpleDateFormat> queue = new ConcurrentLinkedQueue<>();
    private ConcurrentDateFormat(String format, Locale locale, TimeZone timezone) {
        this.format = format;
        this.locale = locale;
        this.timezone = timezone;
        SimpleDateFormat initial = createInstance();
        queue.add(initial);
    }
    public static ConcurrentDateFormat of(String format) {
        return new ConcurrentDateFormat(format, Locale.getDefault(), TimeZone.getDefault());
    }
    public static ConcurrentDateFormat of(String format, TimeZone timezone) {
        return new ConcurrentDateFormat(format, Locale.getDefault(), timezone);
    }
    public static ConcurrentDateFormat of(String format, Locale locale, TimeZone timezone) {
        return new ConcurrentDateFormat(format, locale, timezone);
    }
    public String format(Date date) {
        SimpleDateFormat sdf = queue.poll();
        if (sdf == null) {
            sdf = createInstance();
        }
        String result = sdf.format(date);
        queue.add(sdf);
        return result;
    }
    public Date parse(String source) throws ParseException {
        SimpleDateFormat sdf = queue.poll();
        if (sdf == null) {
            sdf = createInstance();
        }
        Date result = sdf.parse(source);
        queue.add(sdf);
        return result;
    }
    private SimpleDateFormat createInstance() {
        SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
        sdf.setTimeZone(timezone);
        return sdf;
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DatatypeConverterUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
package com.vci.web.util;
/**
 * æ•°æ®ç±»åž‹è½¬æ¢å·¥å…·ç±»
 *
 * @author Chill
 */
public class DatatypeConverterUtil {
    /**
     * hex文本转换为二进制
     *
     * @param hexStr hex文本
     * @return byte[]
     */
    public static byte[] parseHexBinary(String hexStr) {
        final int len = hexStr.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("hexBinary needs to be even-length: " + hexStr);
        }
        byte[] out = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            int h = hexToBin(hexStr.charAt(i));
            int l = hexToBin(hexStr.charAt(i + 1));
            if (h == -1 || l == -1) {
                throw new IllegalArgumentException("contains illegal character for hexBinary: " + hexStr);
            }
            out[i / 2] = (byte) (h * 16 + l);
        }
        return out;
    }
    /**
     * hex文本转换为int
     *
     * @param ch hex文本
     * @return int
     */
    private static int hexToBin(char ch) {
        if ('0' <= ch && ch <= '9') {
            return ch - '0';
        }
        if ('A' <= ch && ch <= 'F') {
            return ch - 'A' + 10;
        }
        if ('a' <= ch && ch <= 'f') {
            return ch - 'a' + 10;
        }
        return -1;
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DateTimeUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,226 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
/**
 * DateTime å·¥å…·ç±»
 *
 * @author L.cm
 */
public class DateTimeUtil {
    public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME);
    public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE);
    public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_TIME);
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DATETIME_FORMAT.format(temporal);
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DATE_FORMAT.format(temporal);
    }
    /**
     * æ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return TIME_FORMAT.format(temporal);
    }
    /**
     * æ—¥æœŸæ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @param pattern  è¡¨è¾¾å¼
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(temporal);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern è¡¨è¾¾å¼
     * @return æ—¶é—´
     */
    public static LocalDateTime parseDateTime(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateTimeUtil.parseDateTime(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalDateTime parseDateTime(String dateStr, DateTimeFormatter formatter) {
        return LocalDateTime.parse(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalDateTime parseDateTime(String dateStr) {
        return DateTimeUtil.parseDateTime(dateStr, DateTimeUtil.DATETIME_FORMAT);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern è¡¨è¾¾å¼
     * @return æ—¶é—´
     */
    public static LocalDate parseDate(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateTimeUtil.parseDate(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalDate parseDate(String dateStr, DateTimeFormatter formatter) {
        return LocalDate.parse(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为日期
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalDate parseDate(String dateStr) {
        return DateTimeUtil.parseDate(dateStr, DateTimeUtil.DATE_FORMAT);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern æ—¶é—´æ­£åˆ™
     * @return æ—¶é—´
     */
    public static LocalTime parseTime(String dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateTimeUtil.parseTime(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalTime parseTime(String dateStr, DateTimeFormatter formatter) {
        return LocalTime.parse(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalTime parseTime(String dateStr) {
        return DateTimeUtil.parseTime(dateStr, DateTimeUtil.TIME_FORMAT);
    }
    /**
     * æ—¶é—´è½¬ Instant
     *
     * @param dateTime æ—¶é—´
     * @return Instant
     */
    public static Instant toInstant(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant();
    }
    /**
     * Instant è½¬ æ—¶é—´
     *
     * @param instant Instant
     * @return Instant
     */
    public static LocalDateTime toDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
    /**
     * è½¬æ¢æˆ date
     *
     * @param dateTime LocalDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(DateTimeUtil.toInstant(dateTime));
    }
    /**
     * æ¯”较2个时间差,跨度比较小
     *
     * @param startInclusive å¼€å§‹æ—¶é—´
     * @param endExclusive   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Duration between(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive);
    }
    /**
     * æ¯”较2个时间差,跨度比较大,年月日为单位
     *
     * @param startDate å¼€å§‹æ—¶é—´
     * @param endDate   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Period between(LocalDate startDate, LocalDate endDate) {
        return Period.between(startDate, endDate);
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DateUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,634 @@
package com.vci.web.util;
import org.springframework.util.Assert;
import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalQuery;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
 * æ—¥æœŸå·¥å…·ç±»
 *
 * @author L.cm
 */
public class DateUtil {
    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATETIME_MINI = "yyyyMMddHHmmss";
    public static final String PATTERN_DATE = "yyyy-MM-dd";
    public static final String PATTERN_TIME = "HH:mm:ss";
    /**
     * è€ date æ ¼å¼åŒ–
     */
    public static final ConcurrentDateFormat DATETIME_FORMAT = ConcurrentDateFormat.of(PATTERN_DATETIME);
    public static final ConcurrentDateFormat DATETIME_MINI_FORMAT = ConcurrentDateFormat.of(PATTERN_DATETIME_MINI);
    public static final ConcurrentDateFormat DATE_FORMAT = ConcurrentDateFormat.of(PATTERN_DATE);
    public static final ConcurrentDateFormat TIME_FORMAT = ConcurrentDateFormat.of(PATTERN_TIME);
    /**
     * java 8 æ—¶é—´æ ¼å¼åŒ–
     */
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME);
    public static final DateTimeFormatter DATETIME_MINI_FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME_MINI);
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE);
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(DateUtil.PATTERN_TIME);
    /**
     * èŽ·å–å½“å‰æ—¥æœŸ
     *
     * @return å½“前日期
     */
    public static Date now() {
        return new Date();
    }
    /**
     * æ·»åŠ å¹´
     *
     * @param date       æ—¶é—´
     * @param yearsToAdd æ·»åŠ çš„å¹´æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusYears(Date date, int yearsToAdd) {
        return DateUtil.set(date, Calendar.YEAR, yearsToAdd);
    }
    /**
     * æ·»åŠ æœˆ
     *
     * @param date        æ—¶é—´
     * @param monthsToAdd æ·»åŠ çš„æœˆæ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusMonths(Date date, int monthsToAdd) {
        return DateUtil.set(date, Calendar.MONTH, monthsToAdd);
    }
    /**
     * æ·»åР呍
     *
     * @param date       æ—¶é—´
     * @param weeksToAdd æ·»åŠ çš„å‘¨æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusWeeks(Date date, int weeksToAdd) {
        return DateUtil.plus(date, Period.ofWeeks(weeksToAdd));
    }
    /**
     * æ·»åР天
     *
     * @param date      æ—¶é—´
     * @param daysToAdd æ·»åŠ çš„å¤©æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusDays(Date date, long daysToAdd) {
        return DateUtil.plus(date, Duration.ofDays(daysToAdd));
    }
    /**
     * æ·»åŠ å°æ—¶
     *
     * @param date       æ—¶é—´
     * @param hoursToAdd æ·»åŠ çš„å°æ—¶æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusHours(Date date, long hoursToAdd) {
        return DateUtil.plus(date, Duration.ofHours(hoursToAdd));
    }
    /**
     * æ·»åŠ åˆ†é’Ÿ
     *
     * @param date         æ—¶é—´
     * @param minutesToAdd æ·»åŠ çš„åˆ†é’Ÿæ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusMinutes(Date date, long minutesToAdd) {
        return DateUtil.plus(date, Duration.ofMinutes(minutesToAdd));
    }
    /**
     * æ·»åŠ ç§’
     *
     * @param date         æ—¶é—´
     * @param secondsToAdd æ·»åŠ çš„ç§’æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusSeconds(Date date, long secondsToAdd) {
        return DateUtil.plus(date, Duration.ofSeconds(secondsToAdd));
    }
    /**
     * æ·»åŠ æ¯«ç§’
     *
     * @param date        æ—¶é—´
     * @param millisToAdd æ·»åŠ çš„æ¯«ç§’æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusMillis(Date date, long millisToAdd) {
        return DateUtil.plus(date, Duration.ofMillis(millisToAdd));
    }
    /**
     * æ·»åŠ çº³ç§’
     *
     * @param date       æ—¶é—´
     * @param nanosToAdd æ·»åŠ çš„çº³ç§’æ•°
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plusNanos(Date date, long nanosToAdd) {
        return DateUtil.plus(date, Duration.ofNanos(nanosToAdd));
    }
    /**
     * æ—¥æœŸæ·»åŠ æ—¶é—´é‡
     *
     * @param date   æ—¶é—´
     * @param amount æ—¶é—´é‡
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date plus(Date date, TemporalAmount amount) {
        Instant instant = date.toInstant();
        return Date.from(instant.plus(amount));
    }
    /**
     * å‡å°‘å¹´
     *
     * @param date  æ—¶é—´
     * @param years å‡å°‘的年数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusYears(Date date, int years) {
        return DateUtil.set(date, Calendar.YEAR, -years);
    }
    /**
     * å‡å°‘月
     *
     * @param date   æ—¶é—´
     * @param months å‡å°‘的月数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusMonths(Date date, int months) {
        return DateUtil.set(date, Calendar.MONTH, -months);
    }
    /**
     * å‡å°‘周
     *
     * @param date  æ—¶é—´
     * @param weeks å‡å°‘的周数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusWeeks(Date date, int weeks) {
        return DateUtil.minus(date, Period.ofWeeks(weeks));
    }
    /**
     * å‡å°‘天
     *
     * @param date æ—¶é—´
     * @param days å‡å°‘的天数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusDays(Date date, long days) {
        return DateUtil.minus(date, Duration.ofDays(days));
    }
    /**
     * å‡å°‘小时
     *
     * @param date  æ—¶é—´
     * @param hours å‡å°‘的小时数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusHours(Date date, long hours) {
        return DateUtil.minus(date, Duration.ofHours(hours));
    }
    /**
     * å‡å°‘分钟
     *
     * @param date    æ—¶é—´
     * @param minutes å‡å°‘的分钟数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusMinutes(Date date, long minutes) {
        return DateUtil.minus(date, Duration.ofMinutes(minutes));
    }
    /**
     * å‡å°‘ç§’
     *
     * @param date    æ—¶é—´
     * @param seconds å‡å°‘的秒数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusSeconds(Date date, long seconds) {
        return DateUtil.minus(date, Duration.ofSeconds(seconds));
    }
    /**
     * å‡å°‘毫秒
     *
     * @param date   æ—¶é—´
     * @param millis å‡å°‘的毫秒数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusMillis(Date date, long millis) {
        return DateUtil.minus(date, Duration.ofMillis(millis));
    }
    /**
     * å‡å°‘纳秒
     *
     * @param date  æ—¶é—´
     * @param nanos å‡å°‘的纳秒数
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minusNanos(Date date, long nanos) {
        return DateUtil.minus(date, Duration.ofNanos(nanos));
    }
    /**
     * æ—¥æœŸå‡å°‘时间量
     *
     * @param date   æ—¶é—´
     * @param amount æ—¶é—´é‡
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    public static Date minus(Date date, TemporalAmount amount) {
        Instant instant = date.toInstant();
        return Date.from(instant.minus(amount));
    }
    /**
     * è®¾ç½®æ—¥æœŸå±žæ€§
     *
     * @param date          æ—¶é—´
     * @param calendarField æ›´æ”¹çš„属性
     * @param amount        æ›´æ”¹æ•°ï¼Œ-1表示减少
     * @return è®¾ç½®åŽçš„æ—¶é—´
     */
    private static Date set(Date date, int calendarField, int amount) {
        Assert.notNull(date, "The date must not be null");
        Calendar c = Calendar.getInstance();
        c.setLenient(false);
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTime(Date date) {
        return DATETIME_FORMAT.format(date);
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTimeMini(Date date) {
        return DATETIME_MINI_FORMAT.format(date);
    }
    /**
     * æ—¥æœŸæ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDate(Date date) {
        return DATE_FORMAT.format(date);
    }
    /**
     * æ—¶é—´æ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatTime(Date date) {
        return TIME_FORMAT.format(date);
    }
    /**
     * æ—¥æœŸæ ¼å¼åŒ–
     *
     * @param date    æ—¶é—´
     * @param pattern è¡¨è¾¾å¼
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String format(Date date, String pattern) {
        return ConcurrentDateFormat.of(pattern).format(date);
    }
    /**
     * java8 æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DATETIME_FORMATTER.format(temporal);
    }
    /**
     * java8 æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTimeMini(TemporalAccessor temporal) {
        return DATETIME_MINI_FORMATTER.format(temporal);
    }
    /**
     * java8 æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DATE_FORMATTER.format(temporal);
    }
    /**
     * java8 æ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return TIME_FORMATTER.format(temporal);
    }
    /**
     * java8 æ—¥æœŸæ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @param pattern  è¡¨è¾¾å¼
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(temporal);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern è¡¨è¾¾å¼
     * @return æ—¶é—´
     */
    public static Date parse(String dateStr, String pattern) {
        ConcurrentDateFormat format = ConcurrentDateFormat.of(pattern);
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param format  ConcurrentDateFormat
     * @return æ—¶é—´
     */
    public static Date parse(String dateStr, ConcurrentDateFormat format) {
        try {
            return format.parse(dateStr);
        } catch (ParseException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern è¡¨è¾¾å¼
     * @return æ—¶é—´
     */
    public static <T> T parse(String dateStr, String pattern, TemporalQuery<T> query) {
        return DateTimeFormatter.ofPattern(pattern).parse(dateStr, query);
    }
    /**
     * æ—¶é—´è½¬ Instant
     *
     * @param dateTime æ—¶é—´
     * @return Instant
     */
    public static Instant toInstant(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant();
    }
    /**
     * Instant è½¬ æ—¶é—´
     *
     * @param instant Instant
     * @return Instant
     */
    public static LocalDateTime toDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
    /**
     * è½¬æ¢æˆ date
     *
     * @param dateTime LocalDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(DateUtil.toInstant(dateTime));
    }
    /**
     * è½¬æ¢æˆ date
     *
     * @param localDate LocalDate
     * @return Date
     */
    public static Date toDate(final LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }
    /**
     * Converts local date time to Calendar.
     */
    public static Calendar toCalendar(final LocalDateTime localDateTime) {
        return GregorianCalendar.from(ZonedDateTime.of(localDateTime, ZoneId.systemDefault()));
    }
    /**
     * localDateTime è½¬æ¢æˆæ¯«ç§’æ•°
     *
     * @param localDateTime LocalDateTime
     * @return long
     */
    public static long toMilliseconds(final LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
    /**
     * localDate è½¬æ¢æˆæ¯«ç§’æ•°
     *
     * @param localDate LocalDate
     * @return long
     */
    public static long toMilliseconds(LocalDate localDate) {
        return toMilliseconds(localDate.atStartOfDay());
    }
    /**
     * è½¬æ¢æˆjava8 æ—¶é—´
     *
     * @param calendar æ—¥åކ
     * @return LocalDateTime
     */
    public static LocalDateTime fromCalendar(final Calendar calendar) {
        TimeZone tz = calendar.getTimeZone();
        ZoneId zid = tz == null ? ZoneId.systemDefault() : tz.toZoneId();
        return LocalDateTime.ofInstant(calendar.toInstant(), zid);
    }
    /**
     * è½¬æ¢æˆjava8 æ—¶é—´
     *
     * @param instant Instant
     * @return LocalDateTime
     */
    public static LocalDateTime fromInstant(final Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
    /**
     * è½¬æ¢æˆjava8 æ—¶é—´
     *
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime fromDate(final Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }
    /**
     * è½¬æ¢æˆjava8 æ—¶é—´
     *
     * @param milliseconds æ¯«ç§’æ•°
     * @return LocalDateTime
     */
    public static LocalDateTime fromMilliseconds(final long milliseconds) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneId.systemDefault());
    }
    /**
     * æ¯”较2个时间差,跨度比较小
     *
     * @param startInclusive å¼€å§‹æ—¶é—´
     * @param endExclusive   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Duration between(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive);
    }
    /**
     * æ¯”较2个时间差,跨度比较大,年月日为单位
     *
     * @param startDate å¼€å§‹æ—¶é—´
     * @param endDate   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Period between(LocalDate startDate, LocalDate endDate) {
        return Period.between(startDate, endDate);
    }
    /**
     * æ¯”较2个 æ—¶é—´å·®
     *
     * @param startDate å¼€å§‹æ—¶é—´
     * @param endDate   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Duration between(Date startDate, Date endDate) {
        return Duration.between(startDate.toInstant(), endDate.toInstant());
    }
    /**
     * å°†ç§’数转换为日时分秒
     *
     * @param second ç§’æ•°
     * @return æ—¶é—´
     */
    public static String secondToTime(Long second) {
        // åˆ¤æ–­æ˜¯å¦ä¸ºç©º
        if (second == null || second == 0L) {
            return StringPool.EMPTY;
        }
        //转换天数
        long days = second / 86400;
        //剩余秒数
        second = second % 86400;
        //转换小时
        long hours = second / 3600;
        //剩余秒数
        second = second % 3600;
        //转换分钟
        long minutes = second / 60;
        //剩余秒数
        second = second % 60;
        if (days > 0) {
            return StringUtil.format("{}天{}小时{}分{}秒", days, hours, minutes, second);
        } else {
            return StringUtil.format("{}小时{}分{}秒", hours, minutes, second);
        }
    }
    /**
     * èŽ·å–ä»Šå¤©çš„æ—¥æœŸ
     *
     * @return æ—¶é—´
     */
    public static String today() {
        return format(new Date(), "yyyyMMdd");
    }
    /**
     * èŽ·å–ä»Šå¤©çš„æ—¶é—´
     *
     * @return æ—¶é—´
     */
    public static String time() {
        return format(new Date(), PATTERN_DATETIME_MINI);
    }
    /**
     * èŽ·å–ä»Šå¤©çš„å°æ—¶æ•°
     *
     * @return æ—¶é—´
     */
    public static Integer hour() {
        return NumberUtil.toInt(format(new Date(), "HH"));
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/DigestUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,433 @@
package com.vci.web.util;
import org.springframework.lang.Nullable;
import org.springframework.util.DigestUtils;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
 * åŠ å¯†ç›¸å…³å·¥å…·ç±»ç›´æŽ¥ä½¿ç”¨Spring util封装,减少jar依赖
 *
 * @author L.cm
 */
public class DigestUtil extends org.springframework.util.DigestUtils {
    private static final char[] HEX_CODE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * Calculates the MD5 digest and returns the value as a 32 character hex string.
     *
     * @param data Data to digest
     * @return MD5 digest as a hex string
     */
    public static String md5Hex(final String data) {
        return DigestUtils.md5DigestAsHex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * Return a hexadecimal string representation of the MD5 digest of the given bytes.
     *
     * @param bytes the bytes to calculate the digest over
     * @return a hexadecimal digest string
     */
    public static String md5Hex(final byte[] bytes) {
        return DigestUtils.md5DigestAsHex(bytes);
    }
    /**
     * sha1Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha1Hex(String data) {
        return DigestUtil.sha1Hex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * sha1Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha1Hex(final byte[] bytes) {
        return DigestUtil.digestHex("SHA-1", bytes);
    }
    /**
     * SHA224Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha224Hex(String data) {
        return DigestUtil.sha224Hex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * SHA224Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha224Hex(final byte[] bytes) {
        return DigestUtil.digestHex("SHA-224", bytes);
    }
    /**
     * sha256Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha256Hex(String data) {
        return DigestUtil.sha256Hex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * sha256Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha256Hex(final byte[] bytes) {
        return DigestUtil.digestHex("SHA-256", bytes);
    }
    /**
     * sha384Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha384Hex(String data) {
        return DigestUtil.sha384Hex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * sha384Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha384Hex(final byte[] bytes) {
        return DigestUtil.digestHex("SHA-384", bytes);
    }
    /**
     * sha512Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha512Hex(String data) {
        return DigestUtil.sha512Hex(data.getBytes(Charsets.UTF_8));
    }
    /**
     * sha512Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha512Hex(final byte[] bytes) {
        return DigestUtil.digestHex("SHA-512", bytes);
    }
    /**
     * digest Hex
     *
     * @param algorithm ç®—法
     * @param bytes     Data to digest
     * @return digest as a hex string
     */
    public static String digestHex(String algorithm, byte[] bytes) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            return encodeHex(md.digest(bytes));
        } catch (NoSuchAlgorithmException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * hmacMd5 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacMd5Hex(String data, String key) {
        return DigestUtil.hmacMd5Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacMd5 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacMd5Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacMD5", bytes, key);
    }
    /**
     * hmacSha1 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha1Hex(String data, String key) {
        return DigestUtil.hmacSha1Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha1 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha1Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacSHA1", bytes, key);
    }
    /**
     * hmacSha224 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha224Hex(String data, String key) {
        return DigestUtil.hmacSha224Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha224 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha224Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacSHA224", bytes, key);
    }
    /**
     * hmacSha256
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static byte[] hmacSha256(String data, String key) {
        return DigestUtil.hmacSha256(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha256
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a byte array
     */
    public static byte[] hmacSha256(final byte[] bytes, String key) {
        return DigestUtil.digestHMac("HmacSHA256", bytes, key);
    }
    /**
     * hmacSha256 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha256Hex(String data, String key) {
        return DigestUtil.hmacSha256Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha256 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha256Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacSHA256", bytes, key);
    }
    /**
     * hmacSha384 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha384Hex(String data, String key) {
        return DigestUtil.hmacSha384Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha384 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha384Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacSHA384", bytes, key);
    }
    /**
     * hmacSha512 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha512Hex(String data, String key) {
        return DigestUtil.hmacSha512Hex(data.getBytes(Charsets.UTF_8), key);
    }
    /**
     * hmacSha512 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha512Hex(final byte[] bytes, String key) {
        return DigestUtil.digestHMacHex("HmacSHA512", bytes, key);
    }
    /**
     * digest HMac Hex
     *
     * @param algorithm ç®—法
     * @param bytes     Data to digest
     * @return digest as a hex string
     */
    public static String digestHMacHex(String algorithm, final byte[] bytes, String key) {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(Charsets.UTF_8), algorithm);
        try {
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
            return DigestUtil.encodeHex(mac.doFinal(bytes));
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * digest HMac
     *
     * @param algorithm ç®—法
     * @param bytes     Data to digest
     * @return digest as a byte array
     */
    public static byte[] digestHMac(String algorithm, final byte[] bytes, String key) {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(Charsets.UTF_8), algorithm);
        try {
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
            return mac.doFinal(bytes);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * encode Hex
     *
     * @param bytes Data to Hex
     * @return bytes as a hex string
     */
    public static String encodeHex(byte[] bytes) {
        StringBuilder r = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            r.append(HEX_CODE[(b >> 4) & 0xF]);
            r.append(HEX_CODE[(b & 0xF)]);
        }
        return r.toString();
    }
    /**
     * decode Hex
     *
     * @param hexStr Hex string
     * @return decode hex to bytes
     */
    public static byte[] decodeHex(final String hexStr) {
        return DatatypeConverterUtil.parseHexBinary(hexStr);
    }
    /**
     * æ¯”较字符串,避免字符串因为过长,产生耗时
     *
     * @param a String
     * @param b String
     * @return æ˜¯å¦ç›¸åŒ
     */
    public static boolean slowEquals(@Nullable String a, @Nullable String b) {
        if (a == null || b == null) {
            return false;
        }
        return DigestUtil.slowEquals(a.getBytes(Charsets.UTF_8), b.getBytes(Charsets.UTF_8));
    }
    /**
     * æ¯”较 byte æ•°ç»„,避免字符串因为过长,产生耗时
     *
     * @param a byte array
     * @param b byte array
     * @return æ˜¯å¦ç›¸åŒ
     */
    public static boolean slowEquals(@Nullable byte[] a, @Nullable byte[] b) {
        if (a == null || b == null) {
            return false;
        }
        if (a.length != b.length) {
            return false;
        }
        int diff = a.length ^ b.length;
        for (int i = 0; i < a.length; i++) {
            diff |= a[i] ^ b[i];
        }
        return diff == 0;
    }
    /**
     * è‡ªå®šä¹‰åР坆 å°†å‰ç«¯ä¼ é€’的密码再次加密
     *
     * @param data æ•°æ®
     * @return {String}
     */
    public static String hex(String data) {
        if (StringUtil.isBlank(data)) {
            return StringPool.EMPTY;
        }
        return sha1Hex(data);
    }
    /**
     * ç”¨æˆ·å¯†ç åŠ å¯†è§„åˆ™ å…ˆMD5再SHA1
     *
     * @param data æ•°æ®
     * @return {String}
     */
    public static String encrypt(String data) {
        if (StringUtil.isBlank(data)) {
            return StringPool.EMPTY;
        }
        return sha1Hex(md5Hex(data));
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Exceptions.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import cn.hutool.core.io.FastStringWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
/**
 * å¼‚常处理工具类
 *
 * @author L.cm
 */
public class Exceptions {
    /**
     * å°†CheckedException转换为UncheckedException.
     *
     * @param e Throwable
     * @return {RuntimeException}
     */
    public static RuntimeException unchecked(Throwable e) {
        if (e instanceof Error) {
            throw (Error) e;
        } else if (e instanceof IllegalAccessException ||
            e instanceof IllegalArgumentException ||
            e instanceof NoSuchMethodException) {
            return new IllegalArgumentException(e);
        } else if (e instanceof InvocationTargetException) {
            return new RuntimeException(((InvocationTargetException) e).getTargetException());
        } else if (e instanceof RuntimeException) {
            return (RuntimeException) e;
        } else if (e instanceof InterruptedException) {
            Thread.currentThread().interrupt();
        }
        return Exceptions.runtime(e);
    }
    /**
     * ä¸é‡‡ç”¨ RuntimeException åŒ…装,直接抛出,使异常更加精准
     *
     * @param throwable Throwable
     * @param <T>       æ³›åž‹æ ‡è®°
     * @return Throwable
     * @throws T æ³›åž‹
     */
    @SuppressWarnings("unchecked")
    private static <T extends Throwable> T runtime(Throwable throwable) throws T {
        throw (T) throwable;
    }
    /**
     * ä»£ç†å¼‚常解包
     *
     * @param wrapped åŒ…装过得异常
     * @return è§£åŒ…后的异常
     */
    public static Throwable unwrap(Throwable wrapped) {
        Throwable unwrapped = wrapped;
        while (true) {
            if (unwrapped instanceof InvocationTargetException) {
                unwrapped = ((InvocationTargetException) unwrapped).getTargetException();
            } else if (unwrapped instanceof UndeclaredThrowableException) {
                unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();
            } else {
                return unwrapped;
            }
        }
    }
    /**
     * å°†ErrorStack转化为String.
     *
     * @param ex Throwable
     * @return {String}
     */
    public static String getStackTraceAsString(Throwable ex) {
        FastStringWriter stringWriter = new FastStringWriter();
        ex.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/FileUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,383 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
/**
 * æ–‡ä»¶å·¥å…·ç±»
 *
 * @author L.cm
 */
public class FileUtil extends org.springframework.util.FileCopyUtils {
    /**
     * é»˜è®¤ä¸ºtrue
     *
     * @author L.cm
     */
    public static class TrueFilter implements FileFilter, Serializable {
        private static final long serialVersionUID = -6420452043795072619L;
        public final static TrueFilter TRUE = new TrueFilter();
        @Override
        public boolean accept(File pathname) {
            return true;
        }
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param path è·¯å¾„
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(String path) {
        File file = new File(path);
        return list(file, TrueFilter.TRUE);
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param path   è·¯å¾„
     * @param fileNamePattern æ–‡ä»¶å * å·
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(String path, final String fileNamePattern) {
        File file = new File(path);
        return list(file, pathname -> {
            String fileName = pathname.getName();
            return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
        });
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param path   è·¯å¾„
     * @param filter æ–‡ä»¶è¿‡æ»¤
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(String path, FileFilter filter) {
        File file = new File(path);
        return list(file, filter);
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param file æ–‡ä»¶
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(File file) {
        List<File> fileList = new ArrayList<>();
        return list(file, fileList, TrueFilter.TRUE);
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param file   æ–‡ä»¶
     * @param fileNamePattern Spring AntPathMatcher è§„则
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(File file, final String fileNamePattern) {
        List<File> fileList = new ArrayList<>();
        return list(file, fileList, pathname -> {
            String fileName = pathname.getName();
            return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
        });
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param file   æ–‡ä»¶
     * @param filter æ–‡ä»¶è¿‡æ»¤
     * @return æ–‡ä»¶é›†åˆ
     */
    public static List<File> list(File file, FileFilter filter) {
        List<File> fileList = new ArrayList<>();
        return list(file, fileList, filter);
    }
    /**
     * æ‰«æç›®å½•下的文件
     *
     * @param file   æ–‡ä»¶
     * @param filter æ–‡ä»¶è¿‡æ»¤
     * @return æ–‡ä»¶é›†åˆ
     */
    private static List<File> list(File file, List<File> fileList, FileFilter filter) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    list(f, fileList, filter);
                }
            }
        } else {
            // è¿‡æ»¤æ–‡ä»¶
            boolean accept = filter.accept(file);
            if (file.exists() && accept) {
                fileList.add(file);
            }
        }
        return fileList;
    }
    /**
     * èŽ·å–æ–‡ä»¶åŽç¼€å
     * @param fullName æ–‡ä»¶å…¨å
     * @return {String}
     */
    public static String getFileExtension(String fullName) {
        if (StringUtil.isBlank(fullName)) return StringPool.EMPTY;
        String fileName = new File(fullName).getName();
        int dotIndex = fileName.lastIndexOf(CharPool.DOT);
        return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
    }
    /**
     * èŽ·å–æ–‡ä»¶åï¼ŒåŽ»é™¤åŽç¼€å
     * @param fullName æ–‡ä»¶å…¨å
     * @return {String}
     */
    public static String getNameWithoutExtension(String fullName) {
        if (StringUtil.isBlank(fullName)) return StringPool.EMPTY;
        String fileName = new File(fullName).getName();
        int dotIndex = fileName.lastIndexOf(CharPool.DOT);
        return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
    }
    /**
     * Returns the path to the system temporary directory.
     *
     * @return the path to the system temporary directory.
     */
    public static String getTempDirPath() {
        return System.getProperty("java.io.tmpdir");
    }
    /**
     * Returns a {@link File} representing the system temporary directory.
     *
     * @return the system temporary directory.
     */
    public static File getTempDir() {
        return new File(getTempDirPath());
    }
    /**
     * Reads the contents of a file into a String.
     * The file is always closed.
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     */
    public static String readToString(final File file) {
        return readToString(file, Charsets.UTF_8);
    }
    /**
     * Reads the contents of a file into a String.
     * The file is always closed.
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the file contents, never {@code null}
     */
    public static String readToString(final File file, final Charset encoding) {
        try (InputStream in = Files.newInputStream(file.toPath())) {
            return IoUtil.readToString(in, encoding);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * Reads the contents of a file into a String.
     * The file is always closed.
     *
     * @param file     the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     */
    public static byte[] readToByteArray(final File file) {
        try (InputStream in = Files.newInputStream(file.toPath())) {
            return IoUtil.readToByteArray(in);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * Writes a String to a file creating the file if it does not exist.
     *
     * @param file the file to write
     * @param data the content to write to the file
     */
    public static void writeToFile(final File file, final String data) {
        writeToFile(file, data, Charsets.UTF_8, false);
    }
    /**
     * Writes a String to a file creating the file if it does not exist.
     *
     * @param file   the file to write
     * @param data   the content to write to the file
     * @param append if {@code true}, then the String will be added to the
     *               end of the file rather than overwriting
     */
    public static void writeToFile(final File file, final String data, final boolean append){
        writeToFile(file, data, Charsets.UTF_8, append);
    }
    /**
     * Writes a String to a file creating the file if it does not exist.
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     */
    public static void writeToFile(final File file, final String data, final Charset encoding) {
        writeToFile(file, data, encoding, false);
    }
    /**
     * Writes a String to a file creating the file if it does not exist.
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @param append   if {@code true}, then the String will be added to the
     *                 end of the file rather than overwriting
     */
    public static void writeToFile(final File file, final String data, final Charset encoding, final boolean append) {
        try (OutputStream out = new FileOutputStream(file, append)) {
            IoUtil.write(data, out, encoding);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è½¬æˆfile
     * @param multipartFile MultipartFile
     * @param file File
     */
    public static void toFile(MultipartFile multipartFile, final File file) {
        try {
            FileUtil.toFile(multipartFile.getInputStream(), file);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è½¬æˆfile
     * @param in InputStream
     * @param file File
     */
    public static void toFile(InputStream in, final File file) {
        try (OutputStream out = new FileOutputStream(file)) {
            FileUtil.copy(in, out);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * Moves a file.
     * <p>
     * When the destination file is on another file system, do a "copy and delete".
     *
     * @param srcFile  the file to be moved
     * @param destFile the destination file
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     */
    public static void moveFile(final File srcFile, final File destFile) throws IOException {
        Assert.notNull(srcFile, "Source must not be null");
        Assert.notNull(destFile, "Destination must not be null");
        if (!srcFile.exists()) {
            throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
        }
        if (srcFile.isDirectory()) {
            throw new IOException("Source '" + srcFile + "' is a directory");
        }
        if (destFile.exists()) {
            throw new IOException("Destination '" + destFile + "' already exists");
        }
        if (destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile + "' is a directory");
        }
        final boolean rename = srcFile.renameTo(destFile);
        if (!rename) {
            FileUtil.copy(srcFile, destFile);
            if (!srcFile.delete()) {
                FileUtil.deleteQuietly(destFile);
                throw new IOException("Failed to delete original file '" + srcFile + "' after copy to '" + destFile + "'");
            }
        }
    }
    /**
     * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
     * <p>
     * The difference between File.delete() and this method are:
     * <ul>
     * <li>A directory to be deleted does not have to be empty.</li>
     * <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
     * </ul>
     *
     * @param file file or directory to delete, can be {@code null}
     * @return {@code true} if the file or directory was deleted, otherwise
     * {@code false}
     */
    public static boolean deleteQuietly(@Nullable final File file) {
        if (file == null) {
            return false;
        }
        try {
            if (file.isDirectory()) {
                FileSystemUtils.deleteRecursively(file);
            }
        } catch (final Exception ignored) {
        }
        try {
            return file.delete();
        } catch (final Exception ignored) {
            return false;
        }
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Func.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,2144 @@
package com.vci.web.util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.aspose.words.ConvertUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jndi.toolkit.url.UrlUtil;
import com.vci.web.util.jackson.JsonUtil;
import org.springframework.util.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.method.HandlerMethod;
import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.*;
import java.util.function.Supplier;
/**
 * å·¥å…·åŒ…集合,工具类快捷方式
 *
 * @author L.cm
 */
public class Func {
    /**
     * æ–­è¨€ï¼Œå¿…须不能为 null
     * <blockquote><pre>
     * public Foo(Bar bar) {
     *     this.bar = $.requireNotNull(bar);
     * }
     * </pre></blockquote>
     *
     * @param obj the object reference to check for nullity
     * @param <T> the type of the reference
     * @return {@code obj} if not {@code null}
     * @throws NullPointerException if {@code obj} is {@code null}
     */
    public static <T> T requireNotNull(T obj) {
        return Objects.requireNonNull(obj);
    }
    /**
     * æ–­è¨€ï¼Œå¿…须不能为 null
     * <blockquote><pre>
     * public Foo(Bar bar, Baz baz) {
     *     this.bar = $.requireNotNull(bar, "bar must not be null");
     *     this.baz = $.requireNotNull(baz, "baz must not be null");
     * }
     * </pre></blockquote>
     *
     * @param obj     the object reference to check for nullity
     * @param message detail message to be used in the event that a {@code
     *                NullPointerException} is thrown
     * @param <T>     the type of the reference
     * @return {@code obj} if not {@code null}
     * @throws NullPointerException if {@code obj} is {@code null}
     */
    public static <T> T requireNotNull(T obj, String message) {
        return Objects.requireNonNull(obj, message);
    }
    /**
     * æ–­è¨€ï¼Œå¿…须不能为 null
     * <blockquote><pre>
     * public Foo(Bar bar, Baz baz) {
     *     this.bar = $.requireNotNull(bar, () -> "bar must not be null");
     * }
     * </pre></blockquote>
     *
     * @param obj             the object reference to check for nullity
     * @param messageSupplier supplier of the detail message to be
     *                        used in the event that a {@code NullPointerException} is thrown
     * @param <T>             the type of the reference
     * @return {@code obj} if not {@code null}
     * @throws NullPointerException if {@code obj} is {@code null}
     */
    public static <T> T requireNotNull(T obj, Supplier<String> messageSupplier) {
        return Objects.requireNonNull(obj, messageSupplier);
    }
    /**
     * åˆ¤æ–­å¯¹è±¡æ˜¯å¦ä¸ºnull
     * <p>
     * This method exists to be used as a
     * {@link java.util.function.Predicate}, {@code filter($::isNull)}
     * </p>
     *
     * @param obj a reference to be checked against {@code null}
     * @return {@code true} if the provided reference is {@code null} otherwise
     * {@code false}
     * @see java.util.function.Predicate
     */
    public static boolean isNull(@Nullable Object obj) {
        return Objects.isNull(obj);
    }
    /**
     * åˆ¤æ–­å¯¹è±¡æ˜¯å¦ not null
     * <p>
     * This method exists to be used as a
     * {@link java.util.function.Predicate}, {@code filter($::notNull)}
     * </p>
     *
     * @param obj a reference to be checked against {@code null}
     * @return {@code true} if the provided reference is non-{@code null}
     * otherwise {@code false}
     * @see java.util.function.Predicate
     */
    public static boolean notNull(@Nullable Object obj) {
        return Objects.nonNull(obj);
    }
    /**
     * é¦–字母变小写
     *
     * @param str å­—符串
     * @return {String}
     */
    public static String firstCharToLower(String str) {
        return StringUtil.firstCharToLower(str);
    }
    /**
     * é¦–字母变大写
     *
     * @param str å­—符串
     * @return {String}
     */
    public static String firstCharToUpper(String str) {
        return StringUtil.firstCharToUpper(str);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦ä¸ºç©ºå­—符串
     * <pre class="code">
     * $.isBlank(null)        = true
     * $.isBlank("")        = true
     * $.isBlank(" ")        = true
     * $.isBlank("12345")    = false
     * $.isBlank(" 12345 ")    = false
     * </pre>
     *
     * @param cs the {@code CharSequence} to check (may be {@code null})
     * @return {@code true} if the {@code CharSequence} is not {@code null},
     * its length is greater than 0, and it does not contain whitespace only
     * @see Character#isWhitespace
     */
    public static boolean isBlank(@Nullable final CharSequence cs) {
        return StringUtil.isBlank(cs);
    }
    /**
     * åˆ¤æ–­ä¸ä¸ºç©ºå­—符串
     * <pre>
     * $.isNotBlank(null)    = false
     * $.isNotBlank("")        = false
     * $.isNotBlank(" ")    = false
     * $.isNotBlank("bob")    = true
     * $.isNotBlank("  bob  ") = true
     * </pre>
     *
     * @param cs the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is
     * not empty and not null and not whitespace
     * @see Character#isWhitespace
     */
    public static boolean isNotBlank(@Nullable final CharSequence cs) {
        return StringUtil.isNotBlank(cs);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦æœ‰ä»»æ„ä¸€ä¸ª ç©ºå­—符串
     *
     * @param css CharSequence
     * @return boolean
     */
    public static boolean isAnyBlank(final CharSequence... css) {
        return StringUtil.isAnyBlank(css);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦å…¨ä¸ºéžç©ºå­—符串
     *
     * @param css CharSequence
     * @return boolean
     */
    public static boolean isNoneBlank(final CharSequence... css) {
        return StringUtil.isNoneBlank(css);
    }
    /**
     * åˆ¤æ–­å¯¹è±¡æ˜¯æ•°ç»„
     *
     * @param obj the object to check
     * @return æ˜¯å¦æ•°ç»„
     */
    public static boolean isArray(@Nullable Object obj) {
        return ObjectUtil.isArray(obj);
    }
    /**
     * åˆ¤æ–­ç©ºå¯¹è±¡ object、map、list、set、字符串、数组
     *
     * @param obj the object to check
     * @return æ•°ç»„是否为空
     */
    public static boolean isEmpty(@Nullable Object obj) {
        return ObjectUtil.isEmpty(obj);
    }
    /**
     * å¯¹è±¡ä¸ä¸ºç©º object、map、list、set、字符串、数组
     *
     * @param obj the object to check
     * @return æ˜¯å¦ä¸ä¸ºç©º
     */
    public static boolean isNotEmpty(@Nullable Object obj) {
        return !ObjectUtil.isEmpty(obj);
    }
    /**
     * åˆ¤æ–­æ•°ç»„为空
     *
     * @param array the array to check
     * @return æ•°ç»„是否为空
     */
    public static boolean isEmpty(@Nullable Object[] array) {
        return ObjectUtil.isEmpty(array);
    }
    /**
     * åˆ¤æ–­æ•°ç»„不为空
     *
     * @param array æ•°ç»„
     * @return æ•°ç»„是否不为空
     */
    public static boolean isNotEmpty(@Nullable Object[] array) {
        return ObjectUtil.isNotEmpty(array);
    }
    /**
     * å¯¹è±¡ç»„中是否存在 Empty Object
     *
     * @param os å¯¹è±¡ç»„
     * @return boolean
     */
    public static boolean hasEmpty(Object... os) {
        for (Object o : os) {
            if (isEmpty(o)) {
                return true;
            }
        }
        return false;
    }
    /**
     * å¯¹è±¡ç»„中是否全部为 Empty Object
     *
     * @param os å¯¹è±¡ç»„
     * @return boolean
     */
    public static boolean isAllEmpty(Object... os) {
        for (Object o : os) {
            if (isNotEmpty(o)) {
                return false;
            }
        }
        return true;
    }
    /**
     * å°†å­—符串中特定模式的字符转换成map中对应的值
     * <p>
     * use: format("my name is ${name}, and i like ${like}!", {"name":"L.cm", "like": "Java"})
     *
     * @param message éœ€è¦è½¬æ¢çš„字符串
     * @param params  è½¬æ¢æ‰€éœ€çš„键值对集合
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String format(@Nullable String message, @Nullable Map<String, ?> params) {
        return StringUtil.format(message, params);
    }
    /**
     * åŒ log æ ¼å¼çš„ format è§„则
     * <p>
     * use: format("my name is {}, and i like {}!", "L.cm", "Java")
     *
     * @param message   éœ€è¦è½¬æ¢çš„字符串
     * @param arguments éœ€è¦æ›¿æ¢çš„变量
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String format(@Nullable String message, @Nullable Object... arguments) {
        return StringUtil.format(message, arguments);
    }
    /**
     * æ ¼å¼åŒ–执行时间,单位为 ms å’Œ s,保留三位小数
     *
     * @param nanos çº³ç§’
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String format(long nanos) {
        return StringUtil.format(nanos);
    }
    /**
     * æ¯”较两个对象是否相等。<br>
     * ç›¸åŒçš„æ¡ä»¶æœ‰ä¸¤ä¸ªï¼Œæ»¡è¶³å…¶ä¸€å³å¯ï¼š<br>
     *
     * @param obj1 å¯¹è±¡1
     * @param obj2 å¯¹è±¡2
     * @return æ˜¯å¦ç›¸ç­‰
     */
    public static boolean equals(Object obj1, Object obj2) {
        return Objects.equals(obj1, obj2);
    }
    /**
     * å®‰å…¨çš„ equals
     *
     * @param o1 first Object to compare
     * @param o2 second Object to compare
     * @return whether the given objects are equal
     * @see Object#equals(Object)
     * @see java.util.Arrays#equals
     */
    public static boolean equalsSafe(@Nullable Object o1, @Nullable Object o2) {
        return ObjectUtil.nullSafeEquals(o1, o2);
    }
    /**
     * åˆ¤æ–­æ•°ç»„中是否包含元素
     *
     * @param array   the Array to check
     * @param element the element to look for
     * @param <T>     The generic tag
     * @return {@code true} if found, {@code false} else
     */
    public static <T> boolean contains(@Nullable T[] array, final T element) {
        return CollectionUtil.contains(array, element);
    }
    /**
     * åˆ¤æ–­è¿­ä»£å™¨ä¸­æ˜¯å¦åŒ…含元素
     *
     * @param iterator the Iterator to check
     * @param element  the element to look for
     * @return {@code true} if found, {@code false} otherwise
     */
    public static boolean contains(@Nullable Iterator<?> iterator, Object element) {
        return CollectionUtil.contains(iterator, element);
    }
    /**
     * åˆ¤æ–­æžšä¸¾æ˜¯å¦åŒ…含该元素
     *
     * @param enumeration the Enumeration to check
     * @param element     the element to look for
     * @return {@code true} if found, {@code false} otherwise
     */
    public static boolean contains(@Nullable Enumeration<?> enumeration, Object element) {
        return CollectionUtil.contains(enumeration, element);
    }
    /**
     * ä¸å¯å˜ Set
     *
     * @param es  å¯¹è±¡
     * @param <E> æ³›åž‹
     * @return é›†åˆ
     */
    @SafeVarargs
    public static <E> Set<E> ofImmutableSet(E... es) {
        return CollectionUtil.ofImmutableSet(es);
    }
    /**
     * ä¸å¯å˜ List
     *
     * @param es  å¯¹è±¡
     * @param <E> æ³›åž‹
     * @return é›†åˆ
     */
    @SafeVarargs
    public static <E> List<E> ofImmutableList(E... es) {
        return CollectionUtil.ofImmutableList(es);
    }
    /**
     * å¼ºè½¬string,并去掉多余空格
     *
     * @param str å­—符串
     * @return {String}
     */
    public static String toStr(Object str) {
        return toStr(str, "");
    }
    /**
     * å¼ºè½¬string,并去掉多余空格
     *
     * @param str          å­—符串
     * @param defaultValue é»˜è®¤å€¼
     * @return {String}
     */
    public static String toStr(Object str, String defaultValue) {
        if (null == str || str.equals(StringPool.NULL)) {
            return defaultValue;
        }
        return String.valueOf(str);
    }
    /**
     * å¼ºè½¬string(包含空字符串),并去掉多余空格
     *
     * @param str          å­—符串
     * @param defaultValue é»˜è®¤å€¼
     * @return {String}
     */
    public static String toStrWithEmpty(Object str, String defaultValue) {
        if (null == str || str.equals(StringPool.NULL) || str.equals(StringPool.EMPTY)) {
            return defaultValue;
        }
        return String.valueOf(str);
    }
    /**
     * åˆ¤æ–­ä¸€ä¸ªå­—符串是否是数字
     *
     * @param cs the CharSequence to check, may be null
     * @return {boolean}
     */
    public static boolean isNumeric(final CharSequence cs) {
        return StringUtil.isNumeric(cs);
    }
    /**
     * å­—符串转 int,为空则返回0
     *
     * <pre>
     *   $.toInt(null) = 0
     *   $.toInt("")   = 0
     *   $.toInt("1")  = 1
     * </pre>
     *
     * @param str the string to convert, may be null
     * @return the int represented by the string, or <code>zero</code> if
     * conversion fails
     */
    public static int toInt(final Object str) {
        return NumberUtil.toInt(String.valueOf(str));
    }
    /**
     * å­—符串转 int,为空则返回默认值
     *
     * <pre>
     *   $.toInt(null, 1) = 1
     *   $.toInt("", 1)   = 1
     *   $.toInt("1", 0)  = 1
     * </pre>
     *
     * @param str          the string to convert, may be null
     * @param defaultValue the default value
     * @return the int represented by the string, or the default if conversion fails
     */
    public static int toInt(@Nullable final Object str, final int defaultValue) {
        return NumberUtil.toInt(String.valueOf(str), defaultValue);
    }
    /**
     * å­—符串转 long,为空则返回0
     *
     * <pre>
     *   $.toLong(null) = 0L
     *   $.toLong("")   = 0L
     *   $.toLong("1")  = 1L
     * </pre>
     *
     * @param str the string to convert, may be null
     * @return the long represented by the string, or <code>0</code> if
     * conversion fails
     */
    public static long toLong(final Object str) {
        return NumberUtil.toLong(String.valueOf(str));
    }
    /**
     * å­—符串转 long,为空则返回默认值
     *
     * <pre>
     *   $.toLong(null, 1L) = 1L
     *   $.toLong("", 1L)   = 1L
     *   $.toLong("1", 0L)  = 1L
     * </pre>
     *
     * @param str          the string to convert, may be null
     * @param defaultValue the default value
     * @return the long represented by the string, or the default if conversion fails
     */
    public static long toLong(@Nullable final Object str, final long defaultValue) {
        return NumberUtil.toLong(String.valueOf(str), defaultValue);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Double</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toDouble(null, 1) = 1.0
     *   $.toDouble("", 1)   = 1.0
     *   $.toDouble("1", 0)  = 1.0
     * </pre>
     *
     * @param value the string to convert, may be null
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Double toDouble(Object value) {
        return toDouble(String.valueOf(value), -1.00);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Double</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toDouble(null, 1) = 1.0
     *   $.toDouble("", 1)   = 1.0
     *   $.toDouble("1", 0)  = 1.0
     * </pre>
     *
     * @param value        the string to convert, may be null
     * @param defaultValue the default value
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Double toDouble(Object value, Double defaultValue) {
        return NumberUtil.toDouble(String.valueOf(value), defaultValue);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Float</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toFloat(null, 1) = 1.00f
     *   $.toFloat("", 1)   = 1.00f
     *   $.toFloat("1", 0)  = 1.00f
     * </pre>
     *
     * @param value the string to convert, may be null
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Float toFloat(Object value) {
        return toFloat(String.valueOf(value), -1.0f);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Float</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toFloat(null, 1) = 1.00f
     *   $.toFloat("", 1)   = 1.00f
     *   $.toFloat("1", 0)  = 1.00f
     * </pre>
     *
     * @param value        the string to convert, may be null
     * @param defaultValue the default value
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Float toFloat(Object value, Float defaultValue) {
        return NumberUtil.toFloat(String.valueOf(value), defaultValue);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Boolean</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toBoolean("true", true)  = true
     *   $.toBoolean("false")       = false
     *   $.toBoolean("", false)      = false
     * </pre>
     *
     * @param value the string to convert, may be null
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Boolean toBoolean(Object value) {
        return toBoolean(value, null);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>Boolean</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   $.toBoolean("true", true)  = true
     *   $.toBoolean("false")       = false
     *   $.toBoolean("", false)      = false
     * </pre>
     *
     * @param value        the string to convert, may be null
     * @param defaultValue the default value
     * @return the int represented by the string, or the default if conversion fails
     */
    public static Boolean toBoolean(Object value, Boolean defaultValue) {
        if (value != null) {
            String val = String.valueOf(value);
            val = val.toLowerCase().trim();
            return Boolean.parseBoolean(val);
        }
        return defaultValue;
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String str) {
        return toIntArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String split, String str) {
        if (StringUtil.isEmpty(str)) {
            return new Integer[]{};
        }
        String[] arr = str.split(split);
        final Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++) {
            final Integer v = toInt(arr[i], 0);
            ints[i] = v;
        }
        return ints;
    }
    /**
     * è½¬æ¢ä¸ºInteger集合<br>
     *
     * @param str ç»“果被转换的值
     * @return ç»“æžœ
     */
    public static List<Integer> toIntList(String str) {
        return Arrays.asList(toIntArray(str));
    }
    /**
     * è½¬æ¢ä¸ºInteger集合<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static List<Integer> toIntList(String split, String str) {
        return Arrays.asList(toIntArray(split, str));
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½Integer数值
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer firstInt(String str) {
        return firstInt(",", str);
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½Integer数值
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer firstInt(String split, String str) {
        List<Integer> ints = toIntList(split, str);
        if (isEmpty(ints)) {
            return null;
        } else {
            return ints.get(0);
        }
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String str) {
        return toLongArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String split, String str) {
        if (StringUtil.isEmpty(str)) {
            return new Long[]{};
        }
        String[] arr = str.split(split);
        final Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++) {
            final Long v = toLong(arr[i], 0);
            longs[i] = v;
        }
        return longs;
    }
    /**
     * è½¬æ¢ä¸ºLong集合<br>
     *
     * @param str ç»“果被转换的值
     * @return ç»“æžœ
     */
    public static List<Long> toLongList(String str) {
        return Arrays.asList(toLongArray(str));
    }
    /**
     * è½¬æ¢ä¸ºLong集合<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static List<Long> toLongList(String split, String str) {
        return Arrays.asList(toLongArray(split, str));
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½Long数值
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long firstLong(String str) {
        return firstLong(",", str);
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½Long数值
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long firstLong(String split, String str) {
        List<Long> longs = toLongList(split, str);
        if (isEmpty(longs)) {
            return null;
        } else {
            return longs.get(0);
        }
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String str) {
        return toStrArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String split, String str) {
        if (isBlank(str)) {
            return new String[]{};
        }
        return str.split(split);
    }
    /**
     * è½¬æ¢ä¸ºString集合<br>
     *
     * @param str ç»“果被转换的值
     * @return ç»“æžœ
     */
    public static List<String> toStrList(String str) {
        return Arrays.asList(toStrArray(str));
    }
    /**
     * è½¬æ¢ä¸ºString集合<br>
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static List<String> toStrList(String split, String str) {
        return Arrays.asList(toStrArray(split, str));
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½String数值
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String firstStr(String str) {
        return firstStr(",", str);
    }
    /**
     * èŽ·å–ç¬¬ä¸€ä½String数值
     *
     * @param split åˆ†éš”符
     * @param str   è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String firstStr(String split, String str) {
        List<String> strs = toStrList(split, str);
        if (isEmpty(strs)) {
            return null;
        } else {
            return strs.get(0);
        }
    }
    /**
     * å°† long è½¬çŸ­å­—符串 ä¸º 62 è¿›åˆ¶
     *
     * @param num æ•°å­—
     * @return çŸ­å­—符串
     */
    public static String to62String(long num) {
        return NumberUtil.to62String(num);
    }
    /**
     * å°†é›†åˆæ‹¼æŽ¥æˆå­—符串,默认使用`,`拼接
     *
     * @param coll the {@code Collection} to convert
     * @return the delimited {@code String}
     */
    public static String join(Collection<?> coll) {
        return StringUtil.join(coll);
    }
    /**
     * å°†é›†åˆæ‹¼æŽ¥æˆå­—符串,默认指定分隔符
     *
     * @param coll  the {@code Collection} to convert
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Collection<?> coll, String delim) {
        return StringUtil.join(coll, delim);
    }
    /**
     * å°†æ•°ç»„拼接成字符串,默认使用`,`拼接
     *
     * @param arr the array to display
     * @return the delimited {@code String}
     */
    public static String join(Object[] arr) {
        return StringUtil.join(arr);
    }
    /**
     * å°†æ•°ç»„拼接成字符串,默认指定分隔符
     *
     * @param arr   the array to display
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Object[] arr, String delim) {
        return StringUtil.join(arr, delim);
    }
    /**
     * åˆ‡åˆ†å­—符串,不去除切分后每个元素两边的空白符,不去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @return åˆ‡åˆ†åŽçš„集合
     */
    public static List<String> split(CharSequence str, char separator) {
        return StringUtil.split(str, separator, -1);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @return åˆ‡åˆ†åŽçš„集合
     */
    public static List<String> splitTrim(CharSequence str, char separator) {
        return StringUtil.splitTrim(str, separator);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @return åˆ‡åˆ†åŽçš„集合
     */
    public static List<String> splitTrim(CharSequence str, CharSequence separator) {
        return StringUtil.splitTrim(str, separator);
    }
    /**
     * åˆ†å‰² å­—符串
     *
     * @param str       å­—符串
     * @param delimiter åˆ†å‰²ç¬¦
     * @return å­—符串数组
     */
    public static String[] split(@Nullable String str, @Nullable String delimiter) {
        return StringUtil.delimitedListToStringArray(str, delimiter);
    }
    /**
     * åˆ†å‰² å­—符串 åˆ é™¤å¸¸è§ ç©ºç™½ç¬¦
     *
     * @param str       å­—符串
     * @param delimiter åˆ†å‰²ç¬¦
     * @return å­—符串数组
     */
    public static String[] splitTrim(@Nullable String str, @Nullable String delimiter) {
        return StringUtil.delimitedListToStringArray(str, delimiter, " \t\n\n\f");
    }
    /**
     * å­—符串是否符合指定的 è¡¨è¾¾å¼
     *
     * <p>
     * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
     * </p>
     *
     * @param pattern è¡¨è¾¾å¼
     * @param str     å­—符串
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) {
        return PatternMatchUtils.simpleMatch(pattern, str);
    }
    /**
     * å­—符串是否符合指定的 è¡¨è¾¾å¼
     *
     * <p>
     * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
     * </p>
     *
     * @param patterns è¡¨è¾¾å¼ æ•°ç»„
     * @param str      å­—符串
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean simpleMatch(@Nullable String[] patterns, String str) {
        return PatternMatchUtils.simpleMatch(patterns, str);
    }
    /**
     * ç”Ÿæˆuuid
     *
     * @return UUID
     */
    public static String randomUUID() {
        return StringUtil.randomUUID();
    }
    /**
     * è½¬ä¹‰HTML用于安全过滤
     *
     * @param html html
     * @return {String}
     */
    public static String escapeHtml(String html) {
        return StringUtil.escapeHtml(html);
    }
    /**
     * éšæœºæ•°ç”Ÿæˆ
     *
     * @param count å­—符长度
     * @return éšæœºæ•°
     */
    public static String random(int count) {
        return StringUtil.random(count);
    }
    /**
     * éšæœºæ•°ç”Ÿæˆ
     *
     * @param count      å­—符长度
     * @param randomType éšæœºæ•°ç±»åˆ«
     * @return éšæœºæ•°
     */
    public static String random(int count, RandomType randomType) {
        return StringUtil.random(count, randomType);
    }
    /**
     * å­—符串序列化成 md5
     *
     * @param data Data to digest
     * @return MD5 digest as a hex string
     */
    public static String md5Hex(final String data) {
        return DigestUtil.md5Hex(data);
    }
    /**
     * æ•°ç»„序列化成 md5
     *
     * @param bytes the bytes to calculate the digest over
     * @return md5 digest string
     */
    public static String md5Hex(final byte[] bytes) {
        return DigestUtil.md5Hex(bytes);
    }
    /**
     * sha1Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha1Hex(String data) {
        return DigestUtil.sha1Hex(data);
    }
    /**
     * sha1Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha1Hex(final byte[] bytes) {
        return DigestUtil.sha1Hex(bytes);
    }
    /**
     * SHA224Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha224Hex(String data) {
        return DigestUtil.sha224Hex(data);
    }
    /**
     * SHA224Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha224Hex(final byte[] bytes) {
        return DigestUtil.sha224Hex(bytes);
    }
    /**
     * sha256Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha256Hex(String data) {
        return DigestUtil.sha256Hex(data);
    }
    /**
     * sha256Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha256Hex(final byte[] bytes) {
        return DigestUtil.sha256Hex(bytes);
    }
    /**
     * sha384Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha384Hex(String data) {
        return DigestUtil.sha384Hex(data);
    }
    /**
     * sha384Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha384Hex(final byte[] bytes) {
        return DigestUtil.sha384Hex(bytes);
    }
    /**
     * sha512Hex
     *
     * @param data Data to digest
     * @return digest as a hex string
     */
    public static String sha512Hex(String data) {
        return DigestUtil.sha512Hex(data);
    }
    /**
     * sha512Hex
     *
     * @param bytes Data to digest
     * @return digest as a hex string
     */
    public static String sha512Hex(final byte[] bytes) {
        return DigestUtil.sha512Hex(bytes);
    }
    /**
     * hmacMd5 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacMd5Hex(String data, String key) {
        return DigestUtil.hmacMd5Hex(data, key);
    }
    /**
     * hmacMd5 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacMd5Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacMd5Hex(bytes, key);
    }
    /**
     * hmacSha1 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha1Hex(String data, String key) {
        return DigestUtil.hmacSha1Hex(data, key);
    }
    /**
     * hmacSha1 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha1Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacSha1Hex(bytes, key);
    }
    /**
     * hmacSha224 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha224Hex(String data, String key) {
        return DigestUtil.hmacSha224Hex(data, key);
    }
    /**
     * hmacSha224 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha224Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacSha224Hex(bytes, key);
    }
    /**
     * hmacSha256 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha256Hex(String data, String key) {
        return DigestUtil.hmacSha256Hex(data, key);
    }
    /**
     * hmacSha256 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha256Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacSha256Hex(bytes, key);
    }
    /**
     * hmacSha384 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha384Hex(String data, String key) {
        return DigestUtil.hmacSha384Hex(data, key);
    }
    /**
     * hmacSha384 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha384Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacSha384Hex(bytes, key);
    }
    /**
     * hmacSha512 Hex
     *
     * @param data Data to digest
     * @param key  key
     * @return digest as a hex string
     */
    public static String hmacSha512Hex(String data, String key) {
        return DigestUtil.hmacSha512Hex(data, key);
    }
    /**
     * hmacSha512 Hex
     *
     * @param bytes Data to digest
     * @param key   key
     * @return digest as a hex string
     */
    public static String hmacSha512Hex(final byte[] bytes, String key) {
        return DigestUtil.hmacSha512Hex(bytes, key);
    }
    /**
     * byte æ•°ç»„序列化成 hex
     *
     * @param bytes bytes to encode
     * @return MD5 digest as a hex string
     */
    public static String encodeHex(byte[] bytes) {
        return DigestUtil.encodeHex(bytes);
    }
    /**
     * å­—符串反序列化成 hex
     *
     * @param hexString String to decode
     * @return MD5 digest as a hex string
     */
    public static byte[] decodeHex(final String hexString) {
        return DigestUtil.decodeHex(hexString);
    }
    /**
     * Base64编码
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String encodeBase64(String value) {
        return Base64Util.encode(value);
    }
    /**
     * Base64编码
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String encodeBase64(String value, Charset charset) {
        return Base64Util.encode(value, charset);
    }
    /**
     * Base64编码为URL安全
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String encodeBase64UrlSafe(String value) {
        return Base64Util.encodeUrlSafe(value);
    }
    /**
     * Base64编码为URL安全
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String encodeBase64UrlSafe(String value, Charset charset) {
        return Base64Util.encodeUrlSafe(value, charset);
    }
    /**
     * Base64解码
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String decodeBase64(String value) {
        return Base64Util.decode(value);
    }
    /**
     * Base64解码
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String decodeBase64(String value, Charset charset) {
        return Base64Util.decode(value, charset);
    }
    /**
     * Base64URL安全解码
     *
     * @param value å­—符串
     * @return {String}
     */
    public static String decodeBase64UrlSafe(String value) {
        return Base64Util.decodeUrlSafe(value);
    }
    /**
     * Base64URL安全解码
     *
     * @param value   å­—符串
     * @param charset å­—符集
     * @return {String}
     */
    public static String decodeBase64UrlSafe(String value, Charset charset) {
        return Base64Util.decodeUrlSafe(value, charset);
    }
    /**
     * å…³é—­ Closeable
     *
     * @param closeable è‡ªåЍ关闭
     */
    public static void closeQuietly(@Nullable Closeable closeable) {
        IoUtil.closeQuietly(closeable);
    }
    /**
     * InputStream to String utf-8
     *
     * @param input the <code>InputStream</code> to read from
     * @return the requested String
     * @throws NullPointerException if the input is null
     */
    public static String readToString(InputStream input) {
        return IoUtil.readToString(input);
    }
    /**
     * InputStream to String
     *
     * @param input   the <code>InputStream</code> to read from
     * @param charset the <code>Charset</code>
     * @return the requested String
     * @throws NullPointerException if the input is null
     */
    public static String readToString(@Nullable InputStream input, Charset charset) {
        return IoUtil.readToString(input, charset);
    }
    /**
     * InputStream to bytes æ•°ç»„
     *
     * @param input InputStream
     * @return the requested byte array
     */
    public static byte[] readToByteArray(@Nullable InputStream input) {
        return IoUtil.readToByteArray(input);
    }
    /**
     * è¯»å–文件为字符串
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     */
    public static String readToString(final File file) {
        return FileUtil.readToString(file);
    }
    /**
     * è¯»å–文件为字符串
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the file contents, never {@code null}
     */
    public static String readToString(File file, Charset encoding) {
        return FileUtil.readToString(file, encoding);
    }
    /**
     * è¯»å–文件为 byte æ•°ç»„
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     */
    public static byte[] readToByteArray(File file) {
        return FileUtil.readToByteArray(file);
    }
    /**
     * å°†å¯¹è±¡åºåˆ—化成json字符串
     *
     * @param object javaBean
     * @return jsonString json字符串
     */
    public static String toJson(Object object) {
        return JsonUtil.toJson(object);
    }
    /**
     * å°†å¯¹è±¡åºåˆ—化成 json byte æ•°ç»„
     *
     * @param object javaBean
     * @return jsonString json字符串
     */
    public static byte[] toJsonAsBytes(Object object) {
        return JsonUtil.toJsonAsBytes(object);
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param jsonString jsonString
     * @return jsonString json字符串
     */
    public static JsonNode readTree(String jsonString) {
        return JsonUtil.readTree(jsonString);
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param in InputStream
     * @return jsonString json字符串
     */
    public static JsonNode readTree(InputStream in) {
        return JsonUtil.readTree(in);
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param content content
     * @return jsonString json字符串
     */
    public static JsonNode readTree(byte[] content) {
        return JsonUtil.readTree(content);
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param jsonParser JsonParser
     * @return jsonString json字符串
     */
    public static JsonNode readTree(JsonParser jsonParser) {
        return JsonUtil.readTree(jsonParser);
    }
    /**
     * å°†json byte æ•°ç»„反序列化成对象
     *
     * @param bytes     json bytes
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(byte[] bytes, Class<T> valueType) {
        return JsonUtil.parse(bytes, valueType);
    }
    /**
     * å°†json反序列化成对象
     *
     * @param jsonString jsonString
     * @param valueType  class
     * @param <T>        T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(String jsonString, Class<T> valueType) {
        return JsonUtil.parse(jsonString, valueType);
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in        InputStream
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(InputStream in, Class<T> valueType) {
        return JsonUtil.parse(in, valueType);
    }
    /**
     * å°†json反序列化成对象
     *
     * @param bytes         bytes
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(byte[] bytes, TypeReference<T> typeReference) {
        return JsonUtil.parse(bytes, typeReference);
    }
    /**
     * å°†json反序列化成对象
     *
     * @param jsonString    jsonString
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(String jsonString, TypeReference<T> typeReference) {
        return JsonUtil.parse(jsonString, typeReference);
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in            InputStream
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T readJson(InputStream in, TypeReference<T> typeReference) {
        return JsonUtil.parse(in, typeReference);
    }
    /**
     * url ç¼–码
     *
     * @param source the String to be encoded
     * @return the encoded String
     */
    public static String urlEncode(String source) {
        return UrlUtil.encode(source, Charsets.UTF_8);
    }
    /**
     * url ç¼–码
     *
     * @param source  the String to be encoded
     * @param charset the character encoding to encode to
     * @return the encoded String
     */
    public static String urlEncode(String source, Charset charset) {
        return UrlUtil.encode(source, charset);
    }
    /**
     * url è§£ç 
     *
     * @param source the encoded String
     * @return the decoded value
     * @throws IllegalArgumentException when the given source contains invalid encoded sequences
     * @see StringUtils#uriDecode(String, Charset)
     * @see java.net.URLDecoder#decode(String, String)
     */
    public static String urlDecode(String source) {
        return StringUtils.uriDecode(source, Charsets.UTF_8);
    }
    /**
     * url è§£ç 
     *
     * @param source  the encoded String
     * @param charset the character encoding to use
     * @return the decoded value
     * @throws IllegalArgumentException when the given source contains invalid encoded sequences
     * @see StringUtils#uriDecode(String, Charset)
     * @see java.net.URLDecoder#decode(String, String)
     */
    public static String urlDecode(String source, Charset charset) {
        return StringUtils.uriDecode(source, charset);
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTime(Date date) {
        return DateUtil.formatDateTime(date);
    }
    /**
     * æ—¥æœŸæ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDate(Date date) {
        return DateUtil.formatDate(date);
    }
    /**
     * æ—¶é—´æ ¼å¼åŒ–
     *
     * @param date æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatTime(Date date) {
        return DateUtil.formatTime(date);
    }
    /**
     * å¯¹è±¡æ ¼å¼åŒ– æ”¯æŒæ•°å­—,date,java8时间
     *
     * @param object  æ ¼å¼åŒ–对象
     * @param pattern è¡¨è¾¾å¼
     * @return æ ¼å¼åŒ–后的字符串
     */
    public static String format(Object object, String pattern) {
        if (object instanceof Number) {
            DecimalFormat decimalFormat = new DecimalFormat(pattern);
            return decimalFormat.format(object);
        } else if (object instanceof Date) {
            return DateUtil.format((Date) object, pattern);
        } else if (object instanceof TemporalAccessor) {
            return DateTimeUtil.format((TemporalAccessor) object, pattern);
        }
        throw new IllegalArgumentException("未支持的对象:" + object + ",格式:" + object);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param pattern è¡¨è¾¾å¼
     * @return æ—¶é—´
     */
    public static Date parseDate(String dateStr, String pattern) {
        return DateUtil.parse(dateStr, pattern);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @param format  ConcurrentDateFormat
     * @return æ—¶é—´
     */
    public static Date parse(String dateStr, ConcurrentDateFormat format) {
        return DateUtil.parse(dateStr, format);
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DateTimeUtil.formatDateTime(temporal);
    }
    /**
     * æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DateTimeUtil.formatDate(temporal);
    }
    /**
     * æ—¶é—´æ ¼å¼åŒ–
     *
     * @param temporal æ—¶é—´
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return DateTimeUtil.formatTime(temporal);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalDateTime parseDateTime(String dateStr, DateTimeFormatter formatter) {
        return DateTimeUtil.parseDateTime(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalDateTime parseDateTime(String dateStr) {
        return DateTimeUtil.parseDateTime(dateStr);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalDate parseDate(String dateStr, DateTimeFormatter formatter) {
        return DateTimeUtil.parseDate(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为日期
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalDate parseDate(String dateStr) {
        return DateTimeUtil.parseDate(dateStr, DateTimeUtil.DATE_FORMAT);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr   æ—¶é—´å­—符串
     * @param formatter DateTimeFormatter
     * @return æ—¶é—´
     */
    public static LocalTime parseTime(String dateStr, DateTimeFormatter formatter) {
        return DateTimeUtil.parseTime(dateStr, formatter);
    }
    /**
     * å°†å­—符串转换为时间
     *
     * @param dateStr æ—¶é—´å­—符串
     * @return æ—¶é—´
     */
    public static LocalTime parseTime(String dateStr) {
        return DateTimeUtil.parseTime(dateStr);
    }
    /**
     * æ—¶é—´æ¯”较
     *
     * @param startInclusive the start instant, inclusive, not null
     * @param endExclusive   the end instant, exclusive, not null
     * @return a {@code Duration}, not null
     */
    public static Duration between(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive);
    }
    /**
     * æ¯”较2个 æ—¶é—´å·®
     *
     * @param startDate å¼€å§‹æ—¶é—´
     * @param endDate   ç»“束时间
     * @return æ—¶é—´é—´éš”
     */
    public static Duration between(Date startDate, Date endDate) {
        return DateUtil.between(startDate, endDate);
    }
    /**
     * å¯¹è±¡ç±»åž‹è½¬æ¢
     *
     * @param source     the source object
     * @param targetType the target type
     * @param <T>        æ³›åž‹æ ‡è®°
     * @return the converted value
     * @throws IllegalArgumentException if targetType is {@code null},
     *                                  or sourceType is {@code null} but source is not {@code null}
     */
    @Nullable
    public static <T> T convert(@Nullable Object source, Class<T> targetType) {
        return ConvertUtil.convert(source, targetType);
    }
    /**
     * å¯¹è±¡ç±»åž‹è½¬æ¢
     *
     * @param source     the source object
     * @param sourceType the source type
     * @param targetType the target type
     * @param <T>        æ³›åž‹æ ‡è®°
     * @return the converted value
     * @throws IllegalArgumentException if targetType is {@code null},
     *                                  or sourceType is {@code null} but source is not {@code null}
     */
    @Nullable
    public static <T> T convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        return ConvertUtil.convert(source, sourceType, targetType);
    }
    /**
     * å¯¹è±¡ç±»åž‹è½¬æ¢
     *
     * @param source     the source object
     * @param targetType the target type
     * @param <T>        æ³›åž‹æ ‡è®°
     * @return the converted value
     * @throws IllegalArgumentException if targetType is {@code null},
     *                                  or sourceType is {@code null} but source is not {@code null}
     */
    @Nullable
    public static <T> T convert(@Nullable Object source, TypeDescriptor targetType) {
        return ConvertUtil.convert(source, targetType);
    }
    /**
     * èŽ·å–æ–¹æ³•å‚æ•°ä¿¡æ¯
     *
     * @param constructor    æž„造器
     * @param parameterIndex å‚数序号
     * @return {MethodParameter}
     */
    public static MethodParameter getMethodParameter(Constructor<?> constructor, int parameterIndex) {
        return ClassUtil.getMethodParameter(constructor, parameterIndex);
    }
    /**
     * èŽ·å–æ–¹æ³•å‚æ•°ä¿¡æ¯
     *
     * @param method         æ–¹æ³•
     * @param parameterIndex å‚数序号
     * @return {MethodParameter}
     */
    public static MethodParameter getMethodParameter(Method method, int parameterIndex) {
        return ClassUtil.getMethodParameter(method, parameterIndex);
    }
    /**
     * èŽ·å–Annotation注解
     *
     * @param annotatedElement AnnotatedElement
     * @param annotationType   æ³¨è§£ç±»
     * @param <A>              æ³›åž‹æ ‡è®°
     * @return {Annotation}
     */
    @Nullable
    public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
        return AnnotatedElementUtils.findMergedAnnotation(annotatedElement, annotationType);
    }
    /**
     * èŽ·å–Annotation,先找方法,没有则再找方法上的类
     *
     * @param method         Method
     * @param annotationType æ³¨è§£ç±»
     * @param <A>            æ³›åž‹æ ‡è®°
     * @return {Annotation}
     */
    @Nullable
    public static <A extends Annotation> A getAnnotation(Method method, Class<A> annotationType) {
        return ClassUtil.getAnnotation(method, annotationType);
    }
    /**
     * èŽ·å–Annotation,先找HandlerMethod,没有则再找对应的类
     *
     * @param handlerMethod  HandlerMethod
     * @param annotationType æ³¨è§£ç±»
     * @param <A>            æ³›åž‹æ ‡è®°
     * @return {Annotation}
     */
    @Nullable
    public static <A extends Annotation> A getAnnotation(HandlerMethod handlerMethod, Class<A> annotationType) {
        return ClassUtil.getAnnotation(handlerMethod, annotationType);
    }
    /**
     * å®žä¾‹åŒ–对象
     *
     * @param clazz ç±»
     * @param <T>   æ³›åž‹æ ‡è®°
     * @return å¯¹è±¡
     */
    @SuppressWarnings("unchecked")
    public static <T> T newInstance(Class<?> clazz) {
        return (T) BeanUtil.instantiateClass(clazz);
    }
    /**
     * å®žä¾‹åŒ–对象
     *
     * @param clazzStr ç±»å
     * @param <T>      æ³›åž‹æ ‡è®°
     * @return å¯¹è±¡
     */
    public static <T> T newInstance(String clazzStr) {
        return BeanUtil.newInstance(clazzStr);
    }
    /**
     * èŽ·å–Bean的属性
     *
     * @param bean         bean
     * @param propertyName å±žæ€§å
     * @return å±žæ€§å€¼
     */
    @Nullable
    public static Object getProperty(@Nullable Object bean, String propertyName) {
        return BeanUtil.getProperty(bean, propertyName);
    }
    /**
     * è®¾ç½®Bean属性
     *
     * @param bean         bean
     * @param propertyName å±žæ€§å
     * @param value        å±žæ€§å€¼
     */
    public static void setProperty(Object bean, String propertyName, Object value) {
        BeanUtil.setProperty(bean, propertyName, value);
    }
    /**
     * æµ…复制
     *
     * @param source æºå¯¹è±¡
     * @param <T>    æ³›åž‹æ ‡è®°
     * @return T
     */
    @Nullable
    public static <T> T clone(@Nullable T source) {
        return BeanUtil.clone(source);
    }
    /**
     * æ‹·è´å¯¹è±¡ï¼Œæ”¯æŒ Map å’Œ Bean
     *
     * @param source æºå¯¹è±¡
     * @param clazz  ç±»å
     * @param <T>    æ³›åž‹æ ‡è®°
     * @return T
     */
    @Nullable
    public static <T> T copy(@Nullable Object source, Class<T> clazz) {
        return BeanUtil.copy(source, clazz);
    }
    /**
     * æ‹·è´å¯¹è±¡ï¼Œæ”¯æŒ Map å’Œ Bean
     *
     * @param source     æºå¯¹è±¡
     * @param targetBean éœ€è¦èµ‹å€¼çš„对象
     */
    public static void copy(@Nullable Object source, @Nullable Object targetBean) {
        BeanUtil.copy(source, targetBean);
    }
    /**
     * æ‹·è´å¯¹è±¡ï¼Œsource å¯¹è±¡å±žæ€§åšéž null åˆ¤æ–­
     *
     * <p>
     * æ”¯æŒ map bean copy
     * </p>
     *
     * @param source     æºå¯¹è±¡
     * @param targetBean éœ€è¦èµ‹å€¼çš„对象
     */
    public static void copyNonNull(@Nullable Object source, @Nullable Object targetBean) {
        BeanUtil.copyNonNull(source, targetBean);
    }
    /**
     * æ‹·è´å¯¹è±¡ï¼Œå¹¶å¯¹ä¸åŒç±»åž‹å±žæ€§è¿›è¡Œè½¬æ¢
     *
     * @param source æºå¯¹è±¡
     * @param clazz  ç±»å
     * @param <T>    æ³›åž‹æ ‡è®°
     * @return T
     */
    @Nullable
    public static <T> T copyWithConvert(@Nullable Object source, Class<T> clazz) {
        return BeanUtil.copyWithConvert(source, clazz);
    }
    /**
     * æ‹·è´åˆ—表对象
     *
     * <p>
     * æ”¯æŒ map bean copy
     * </p>
     *
     * @param sourceList  æºåˆ—表
     * @param targetClazz è½¬æ¢æˆçš„类型
     * @param <T>         æ³›åž‹æ ‡è®°
     * @return T
     */
    public static <T> List<T> copy(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
        return BeanUtil.copy(sourceList, targetClazz);
    }
    /**
     * æ‹·è´åˆ—表对象,并对不同类型属性进行转换
     *
     * <p>
     * æ”¯æŒ map bean copy
     * </p>
     *
     * @param sourceList  æºå¯¹è±¡åˆ—表
     * @param targetClazz è½¬æ¢æˆçš„ç±»
     * @param <T>         æ³›åž‹æ ‡è®°
     * @return List
     */
    public static <T> List<T> copyWithConvert(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
        return BeanUtil.copyWithConvert(sourceList, targetClazz);
    }
    /**
     * æ‹·è´å¯¹è±¡ï¼Œæ‰©å±• Spring çš„æ‹·è´æ–¹æ³•
     *
     * @param source the source bean
     * @param clazz  the target bean class
     * @param <T>    æ³›åž‹æ ‡è®°
     * @return T
     * @throws BeansException if the copying failed
     */
    @Nullable
    public static <T> T copyProperties(@Nullable Object source, Class<T> clazz) throws BeansException {
        return BeanUtil.copyProperties(source, clazz);
    }
    /**
     * æ‹·è´åˆ—表对象,扩展 Spring çš„æ‹·è´æ–¹æ³•
     *
     * @param sourceList  the source list bean
     * @param targetClazz the target bean class
     * @param <T>         æ³›åž‹æ ‡è®°
     * @return List
     * @throws BeansException if the copying failed
     */
    public static <T> List<T> copyProperties(@Nullable Collection<?> sourceList, Class<T> targetClazz) throws BeansException {
        return BeanUtil.copyProperties(sourceList, targetClazz);
    }
    /**
     * å°†å¯¹è±¡è£…成map形式
     *
     * @param bean æºå¯¹è±¡
     * @return {Map}
     */
    public static Map<String, Object> toMap(@Nullable Object bean) {
        return BeanUtil.toMap(bean);
    }
    /**
     * å°†map è½¬ä¸º bean
     *
     * @param beanMap   map
     * @param valueType å¯¹è±¡ç±»åž‹
     * @param <T>       æ³›åž‹æ ‡è®°
     * @return {T}
     */
    public static <T> T toBean(Map<String, Object> beanMap, Class<T> valueType) {
        return BeanUtil.toBean(beanMap, valueType);
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/Holder.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.vci.web.util;
import java.security.SecureRandom;
import java.util.Random;
/**
 * ä¸€äº›å¸¸ç”¨çš„单例对象
 *
 * @author L.cm
 */
public class Holder {
    /**
     * RANDOM
     */
    public final static Random RANDOM = new Random();
    /**
     * SECURE_RANDOM
     */
    public final static SecureRandom SECURE_RANDOM = new SecureRandom();
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/IoUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,109 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package com.vci.web.util;
import org.springframework.lang.Nullable;
import java.io.*;
import java.nio.charset.Charset;
/**
 * æµå·¥å…·ç±»
 *
 * @author L.cm
 */
public class IoUtil extends org.springframework.util.StreamUtils {
    /**
     * closeQuietly
     *
     * @param closeable è‡ªåЍ关闭
     */
    public static void closeQuietly(@Nullable Closeable closeable) {
        if (closeable == null) {
            return;
        }
        if (closeable instanceof Flushable) {
            try {
                ((Flushable) closeable).flush();
            } catch (IOException ignored) {
                // ignore
            }
        }
        try {
            closeable.close();
        } catch (IOException ignored) {
            // ignore
        }
    }
    /**
     * InputStream to String utf-8
     *
     * @param input the <code>InputStream</code> to read from
     * @return the requested String
     */
    public static String readToString(InputStream input) {
        return readToString(input, Charsets.UTF_8);
    }
    /**
     * InputStream to String
     *
     * @param input   the <code>InputStream</code> to read from
     * @param charset the <code>Charset</code>
     * @return the requested String
     */
    public static String readToString(@Nullable InputStream input, Charset charset) {
        try {
            return IoUtil.copyToString(input, charset);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        } finally {
            IoUtil.closeQuietly(input);
        }
    }
    public static byte[] readToByteArray(@Nullable InputStream input) {
        try {
            return IoUtil.copyToByteArray(input);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        } finally {
            IoUtil.closeQuietly(input);
        }
    }
    /**
     * Writes chars from a <code>String</code> to bytes on an
     * <code>OutputStream</code> using the specified character encoding.
     * <p>
     * This method uses {@link String#getBytes(String)}.
     * </p>
     * @param data     the <code>String</code> to write, null ignored
     * @param output   the <code>OutputStream</code> to write to
     * @param encoding the encoding to use, null means platform default
     * @throws NullPointerException if output is null
     * @throws IOException          if an I/O error occurs
     */
    public static void write(@Nullable final String data, final OutputStream output, final Charset encoding) throws IOException {
        if (data != null) {
            output.write(data.getBytes(encoding));
        }
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/NumberUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,195 @@
package com.vci.web.util;
import org.springframework.lang.Nullable;
/**
 * æ•°å­—类型工具类
 *
 * @author L.cm
 */
public class NumberUtil extends org.springframework.util.NumberUtils {
    //-----------------------------------------------------------------------
    /**
     * <p>Convert a <code>String</code> to an <code>int</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtil.toInt(null) = 0
     *   NumberUtil.toInt("")   = 0
     *   NumberUtil.toInt("1")  = 1
     * </pre>
     *
     * @param str the string to convert, may be null
     * @return the int represented by the string, or <code>zero</code> if
     * conversion fails
     */
    public static int toInt(final String str) {
        return toInt(str, -1);
    }
    /**
     * <p>Convert a <code>String</code> to an <code>int</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtil.toInt(null, 1) = 1
     *   NumberUtil.toInt("", 1)   = 1
     *   NumberUtil.toInt("1", 0)  = 1
     * </pre>
     *
     * @param str          the string to convert, may be null
     * @param defaultValue the default value
     * @return the int represented by the string, or the default if conversion fails
     */
    public static int toInt(@Nullable final String str, final int defaultValue) {
        if (str == null) {
            return defaultValue;
        }
        try {
            return Integer.valueOf(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }
    /**
     * <p>Convert a <code>String</code> to a <code>long</code>, returning
     * <code>zero</code> if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
     *
     * <pre>
     *   NumberUtil.toLong(null) = 0L
     *   NumberUtil.toLong("")   = 0L
     *   NumberUtil.toLong("1")  = 1L
     * </pre>
     *
     * @param str the string to convert, may be null
     * @return the long represented by the string, or <code>0</code> if
     * conversion fails
     */
    public static long toLong(final String str) {
        return toLong(str, 0L);
    }
    /**
     * <p>Convert a <code>String</code> to a <code>long</code>, returning a
     * default value if the conversion fails.</p>
     *
     * <p>If the string is <code>null</code>, the default value is returned.</p>
     *
     * <pre>
     *   NumberUtil.toLong(null, 1L) = 1L
     *   NumberUtil.toLong("", 1L)   = 1L
     *   NumberUtil.toLong("1", 0L)  = 1L
     * </pre>
     *
     * @param str          the string to convert, may be null
     * @param defaultValue the default value
     * @return the long represented by the string, or the default if conversion fails
     */
    public static long toLong(@Nullable final String str, final long defaultValue) {
        if (str == null) {
            return defaultValue;
        }
        try {
            return Long.valueOf(str);
        } catch (final NumberFormatException nfe) {
            return defaultValue;
        }
    }
    /**
     * <p>Convert a <code>String</code> to a <code>Double</code>
     *
     * @param value value
     * @return double value
     */
    public static Double toDouble(String value) {
        return toDouble(value, null);
    }
    /**
     * <p>Convert a <code>String</code> to a <code>Double</code>
     *
     * @param value value
     * @param defaultValue é»˜è®¤å€¼
     * @return double value
     */
    public static Double toDouble(@Nullable String value, Double defaultValue) {
        if (value != null) {
            return Double.valueOf(value.trim());
        }
        return defaultValue;
    }
    /**
     * <p>Convert a <code>String</code> to a <code>Double</code>
     *
     * @param value value
     * @return double value
     */
    public static Float toFloat(String value) {
        return toFloat(value, null);
    }
    /**
     * <p>Convert a <code>String</code> to a <code>Double</code>
     *
     * @param value value
     * @param defaultValue é»˜è®¤å€¼
     * @return double value
     */
    public static Float toFloat(@Nullable String value, Float defaultValue) {
        if (value != null) {
            return Float.valueOf(value.trim());
        }
        return defaultValue;
    }
    /**
     * All possible chars for representing a number as a String
     */
    private final static char[] DIGITS = {
            '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b',
            'c', 'd', 'e', 'f', 'g', 'h',
            'i', 'j', 'k', 'l', 'm', 'n',
            'o', 'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z',
            'A', 'B', 'C', 'D', 'E', 'F',
            'G', 'H', 'I', 'J', 'K', 'L',
            'M', 'N', 'O', 'P', 'Q', 'R',
            'S', 'T', 'U', 'V', 'W', 'X',
            'Y', 'Z'
    };
    /**
     * å°† long è½¬çŸ­å­—符串 ä¸º 62 è¿›åˆ¶
     *
     * @param i æ•°å­—
     * @return çŸ­å­—符串
     */
    public static String to62String(long i) {
        int radix = DIGITS.length;
        char[] buf = new char[65];
        int charPos = 64;
        i = -i;
        while (i <= -radix) {
            buf[charPos--] = DIGITS[(int) (-(i % radix))];
            i = i / radix;
        }
        buf[charPos] = DIGITS[(int) (-i)];
        return new String(buf, charPos, (65 - charPos));
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/ObjectUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.vci.web.util;
import org.springframework.lang.Nullable;
/**
 * å¯¹è±¡å·¥å…·ç±»
 *
 * @author L.cm
 */
public class ObjectUtil extends org.springframework.util.ObjectUtils {
    /**
     * åˆ¤æ–­å…ƒç´ ä¸ä¸ºç©º
     * @param obj object
     * @return boolean
     */
    public static boolean isNotEmpty(@Nullable Object obj) {
        return !ObjectUtil.isEmpty(obj);
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/RandomType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.vci.web.util;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
 * ç”Ÿæˆçš„随机数类型
 *
 * @author L.cm
 */
@Getter
@RequiredArgsConstructor
public enum RandomType {
    /**
     * INT STRING ALL
     */
    INT(RandomType.INT_STR),
    STRING(RandomType.STR_STR),
    ALL(RandomType.ALL_STR);
    private final String factor;
    /**
     * éšæœºå­—符串因子
     */
    private static final String INT_STR = "0123456789";
    private static final String STR_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static final String ALL_STR = INT_STR + STR_STR;
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/StringPool.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,71 @@
package com.vci.web.util;
/**
 * é™æ€ String æ± 
 *
 * @author L.cm
 */
public interface StringPool {
    String AMPERSAND        = "&";
    String AND                = "and";
    String AT                = "@";
    String ASTERISK            = "*";
    String STAR                = ASTERISK;
    String SLASH            = "/";
    String BACK_SLASH        = "\\";
    String DOUBLE_SLASH        = "#//";
    String COLON            = ":";
    String COMMA            = ",";
    String DASH                = "-";
    String DOLLAR            = "$";
    String DOT                = ".";
    String EMPTY            = "";
    String EMPTY_JSON         = "{}";
    String EQUALS            = "=";
    String FALSE            = "false";
    String HASH                = "#";
    String HAT                = "^";
    String LEFT_BRACE        = "{";
    String LEFT_BRACKET        = "(";
    String LEFT_CHEV        = "<";
    String NEWLINE            = "\n";
    String N                = "n";
    String NO                = "no";
    String NULL                = "null";
    String OFF                = "off";
    String ON                = "on";
    String PERCENT            = "%";
    String PIPE                = "|";
    String PLUS                = "+";
    String QUESTION_MARK    = "?";
    String EXCLAMATION_MARK    = "!";
    String QUOTE            = "\"";
    String RETURN            = "\r";
    String TAB                = "\t";
    String RIGHT_BRACE        = "}";
    String RIGHT_BRACKET    = ")";
    String RIGHT_CHEV        = ">";
    String SEMICOLON        = ";";
    String SINGLE_QUOTE        = "'";
    String BACKTICK            = "`";
    String SPACE            = " ";
    String TILDA            = "~";
    String LEFT_SQ_BRACKET    = "[";
    String RIGHT_SQ_BRACKET    = "]";
    String TRUE                = "true";
    String UNDERSCORE        = "_";
    String UTF_8            = "UTF-8";
    String GBK                = "GBK";
    String ISO_8859_1         = "ISO-8859-1";
    String Y                = "y";
    String YES                = "yes";
    String ONE                = "1";
    String ZERO                = "0";
    String MINUS_ONE        = "-1";
    String DOLLAR_LEFT_BRACE= "${";
    String UNKNOWN            = "unknown";
    String GET                = "GET";
    String POST                = "POST";
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/StringUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1560 @@
package com.vci.web.util;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.util.HtmlUtils;
import com.vci.web.support.StrSpliter;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;
import java.util.stream.Stream;
/**
 * ç»§æ‰¿è‡ªSpring util的工具类,减少jar依赖
 *
 * @author L.cm
 */
public class StringUtil extends org.springframework.util.StringUtils {
    public static final int INDEX_NOT_FOUND = -1;
    // public static final int INDEX_NOT_FOUND = 0;
    /**
     * Check whether the given {@code CharSequence} contains actual <em>text</em>.
     * <p>More specifically, this method returns {@code true} if the
     * {@code CharSequence} is not {@code null}, its length is greater than
     * 0, and it contains at least one non-whitespace character.
     * <pre class="code">
     * StringUtil.isBlank(null) = true
     * StringUtil.isBlank("") = true
     * StringUtil.isBlank(" ") = true
     * StringUtil.isBlank("12345") = false
     * StringUtil.isBlank(" 12345 ") = false
     * </pre>
     *
     * @param cs the {@code CharSequence} to check (may be {@code null})
     * @return {@code true} if the {@code CharSequence} is not {@code null},
     * its length is greater than 0, and it does not contain whitespace only
     * @see Character#isWhitespace
     */
    public static boolean isBlank(final CharSequence cs) {
        return !StringUtil.hasText(cs);
    }
    /**
     * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
     * <pre>
     * StringUtil.isNotBlank(null)      = false
     * StringUtil.isNotBlank("")        = false
     * StringUtil.isNotBlank(" ")       = false
     * StringUtil.isNotBlank("bob")     = true
     * StringUtil.isNotBlank("  bob  ") = true
     * </pre>
     *
     * @param cs the CharSequence to check, may be null
     * @return {@code true} if the CharSequence is
     * not empty and not null and not whitespace
     * @see Character#isWhitespace
     */
    public static boolean isNotBlank(final CharSequence cs) {
        return StringUtil.hasText(cs);
    }
    /**
     * æœ‰ ä»»æ„ ä¸€ä¸ª Blank
     *
     * @param css CharSequence
     * @return boolean
     */
    public static boolean isAnyBlank(final CharSequence... css) {
        if (ObjectUtil.isEmpty(css)) {
            return true;
        }
        return Stream.of(css).anyMatch(StringUtil::isBlank);
    }
    /**
     * æ˜¯å¦å…¨éž Blank
     *
     * @param css CharSequence
     * @return boolean
     */
    public static boolean isNoneBlank(final CharSequence... css) {
        if (ObjectUtil.isEmpty(css)) {
            return false;
        }
        return Stream.of(css).allMatch(StringUtil::isNotBlank);
    }
    /**
     * æ˜¯å¦å…¨ä¸º Blank
     *
     * @param css CharSequence
     * @return boolean
     */
    public static boolean isAllBlank(final CharSequence... css) {
        return Stream.of(css).allMatch(StringUtil::isBlank);
    }
    /**
     * åˆ¤æ–­ä¸€ä¸ªå­—符串是否是数字
     *
     * @param cs the CharSequence to check, may be null
     * @return {boolean}
     */
    public static boolean isNumeric(final CharSequence cs) {
        if (isBlank(cs)) {
            return false;
        }
        for (int i = cs.length(); --i >= 0; ) {
            int chr = cs.charAt(i);
            if (chr < 48 || chr > 57) {
                return false;
            }
        }
        return true;
    }
    /**
     * å°†å­—符串中特定模式的字符转换成map中对应的值
     * <p>
     * use: format("my name is ${name}, and i like ${like}!", {"name":"L.cm", "like": "Java"})
     *
     * @param message éœ€è¦è½¬æ¢çš„字符串
     * @param params  è½¬æ¢æ‰€éœ€çš„键值对集合
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String format(@Nullable String message, @Nullable Map<String, ?> params) {
        // message ä¸º null è¿”回空字符串
        if (message == null) {
            return StringPool.EMPTY;
        }
        // å‚数为 null æˆ–者为空
        if (params == null || params.isEmpty()) {
            return message;
        }
        // æ›¿æ¢å˜é‡
        StringBuilder sb = new StringBuilder((int) (message.length() * 1.5));
        int cursor = 0;
        for (int start, end; (start = message.indexOf(StringPool.DOLLAR_LEFT_BRACE, cursor)) != -1 && (end = message.indexOf(StringPool.RIGHT_BRACE, start)) != -1; ) {
            sb.append(message, cursor, start);
            String key = message.substring(start + 2, end);
            Object value = params.get(StringUtil.trimWhitespace(key));
            sb.append(value == null ? StringPool.EMPTY : value);
            cursor = end + 1;
        }
        sb.append(message.substring(cursor));
        return sb.toString();
    }
    /**
     * åŒ log æ ¼å¼çš„ format è§„则
     * <p>
     * use: format("my name is {}, and i like {}!", "L.cm", "Java")
     *
     * @param message   éœ€è¦è½¬æ¢çš„字符串
     * @param arguments éœ€è¦æ›¿æ¢çš„变量
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String format(@Nullable String message, @Nullable Object... arguments) {
        // message ä¸º null è¿”回空字符串
        if (message == null) {
            return StringPool.EMPTY;
        }
        // å‚数为 null æˆ–者为空
        if (arguments == null || arguments.length == 0) {
            return message;
        }
        StringBuilder sb = new StringBuilder((int) (message.length() * 1.5));
        int cursor = 0;
        int index = 0;
        int argsLength = arguments.length;
        for (int start, end; (start = message.indexOf('{', cursor)) != -1 && (end = message.indexOf('}', start)) != -1 && index < argsLength; ) {
            sb.append(message, cursor, start);
            sb.append(arguments[index]);
            cursor = end + 1;
            index++;
        }
        sb.append(message.substring(cursor));
        return sb.toString();
    }
    /**
     * æ ¼å¼åŒ–执行时间,单位为 ms å’Œ s,保留三位小数
     *
     * @param nanos çº³ç§’
     * @return æ ¼å¼åŒ–后的时间
     */
    public static String format(long nanos) {
        if (nanos < 1) {
            return "0ms";
        }
        double millis = (double) nanos / (1000 * 1000);
        // ä¸å¤Ÿ 1 ms,最小单位为 ms
        if (millis > 1000) {
            return String.format("%.3fs", millis / 1000);
        } else {
            return String.format("%.3fms", millis);
        }
    }
    /**
     * Convert a {@code Collection} into a delimited {@code String} (e.g., CSV).
     * <p>Useful for {@code toString()} implementations.
     *
     * @param coll the {@code Collection} to convert
     * @return the delimited {@code String}
     */
    public static String join(Collection<?> coll) {
        return StringUtil.collectionToCommaDelimitedString(coll);
    }
    /**
     * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV).
     * <p>Useful for {@code toString()} implementations.
     *
     * @param coll  the {@code Collection} to convert
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Collection<?> coll, String delim) {
        return StringUtil.collectionToDelimitedString(coll, delim);
    }
    /**
     * Convert a {@code String} array into a comma delimited {@code String}
     * (i.e., CSV).
     * <p>Useful for {@code toString()} implementations.
     *
     * @param arr the array to display
     * @return the delimited {@code String}
     */
    public static String join(Object[] arr) {
        return StringUtil.arrayToCommaDelimitedString(arr);
    }
    /**
     * Convert a {@code String} array into a delimited {@code String} (e.g. CSV).
     * <p>Useful for {@code toString()} implementations.
     *
     * @param arr   the array to display
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String join(Object[] arr, String delim) {
        return StringUtil.arrayToDelimitedString(arr, delim);
    }
    /**
     * å­—符串是否符合指定的 è¡¨è¾¾å¼
     *
     * <p>
     * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
     * </p>
     *
     * @param pattern è¡¨è¾¾å¼
     * @param str     å­—符串
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) {
        return PatternMatchUtils.simpleMatch(pattern, str);
    }
    /**
     * å­—符串是否符合指定的 è¡¨è¾¾å¼
     *
     * <p>
     * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy"
     * </p>
     *
     * @param patterns è¡¨è¾¾å¼ æ•°ç»„
     * @param str      å­—符串
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean simpleMatch(@Nullable String[] patterns, String str) {
        return PatternMatchUtils.simpleMatch(patterns, str);
    }
    /**
     * ç”Ÿæˆuuid
     *
     * @return UUID
     */
    public static String randomUUID() {
        ThreadLocalRandom random = ThreadLocalRandom.current();
        return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
    }
    /**
     * è½¬ä¹‰HTML用于安全过滤
     *
     * @param html html
     * @return {String}
     */
    public static String escapeHtml(String html) {
        return StringUtil.isBlank(html) ? StringPool.EMPTY : HtmlUtils.htmlEscape(html);
    }
    /**
     * æ¸…理字符串,清理出某些不可见字符
     *
     * @param txt å­—符串
     * @return {String}
     */
    public static String cleanChars(String txt) {
        return txt.replaceAll("[ ã€€`·•�\\f\\t\\v\\s]", "");
    }
    /**
     * ç‰¹æ®Šå­—符正则,sql特殊字符和空白符
     */
    private final static Pattern SPECIAL_CHARS_REGEX = Pattern.compile("[`'\"|/,;()-+*%#·•� \\s]");
    /**
     * æ¸…理字符串,清理出某些不可见字符和一些sql特殊字符
     *
     * @param txt æ–‡æœ¬
     * @return {String}
     */
    @Nullable
    public static String cleanText(@Nullable String txt) {
        if (txt == null) {
            return null;
        }
        return SPECIAL_CHARS_REGEX.matcher(txt).replaceAll(StringPool.EMPTY);
    }
    /**
     * èŽ·å–æ ‡è¯†ç¬¦ï¼Œç”¨äºŽå‚æ•°æ¸…ç†
     *
     * @param param å‚æ•°
     * @return æ¸…理后的标识符
     */
    @Nullable
    public static String cleanIdentifier(@Nullable String param) {
        if (param == null) {
            return null;
        }
        StringBuilder paramBuilder = new StringBuilder();
        for (int i = 0; i < param.length(); i++) {
            char c = param.charAt(i);
            if (Character.isJavaIdentifierPart(c)) {
                paramBuilder.append(c);
            }
        }
        return paramBuilder.toString();
    }
    /**
     * éšæœºæ•°ç”Ÿæˆ
     *
     * @param count å­—符长度
     * @return éšæœºæ•°
     */
    public static String random(int count) {
        return StringUtil.random(count, RandomType.ALL);
    }
    /**
     * éšæœºæ•°ç”Ÿæˆ
     *
     * @param count      å­—符长度
     * @param randomType éšæœºæ•°ç±»åˆ«
     * @return éšæœºæ•°
     */
    public static String random(int count, RandomType randomType) {
        if (count == 0) {
            return StringPool.EMPTY;
        }
        Assert.isTrue(count > 0, "Requested random string length " + count + " is less than 0.");
        final Random random = Holder.SECURE_RANDOM;
        char[] buffer = new char[count];
        for (int i = 0; i < count; i++) {
            String factor = randomType.getFactor();
            buffer[i] = factor.charAt(random.nextInt(factor.length()));
        }
        return new String(buffer);
    }
    /**
     * æœ‰åºçš„æ ¼å¼åŒ–文本,使用{number}做为占位符<br>
     * ä¾‹ï¼š<br>
     * é€šå¸¸ä½¿ç”¨ï¼šformat("this is {0} for {1}", "a", "b") =》 this is a for b<br>
     *
     * @param pattern   æ–‡æœ¬æ ¼å¼
     * @param arguments å‚æ•°
     * @return æ ¼å¼åŒ–后的文本
     */
    public static String indexedFormat(CharSequence pattern, Object... arguments) {
        return MessageFormat.format(pattern.toString(), arguments);
    }
    /**
     * æ ¼å¼åŒ–文本,使用 {varName} å ä½<br>
     * map = {a: "aValue", b: "bValue"} format("{a} and {b}", map) ---=》 aValue and bValue
     *
     * @param template æ–‡æœ¬æ¨¡æ¿ï¼Œè¢«æ›¿æ¢çš„部分用 {key} è¡¨ç¤º
     * @param map      å‚数值对
     * @return æ ¼å¼åŒ–后的文本
     */
    public static String format(CharSequence template, Map<?, ?> map) {
        if (null == template) {
            return null;
        }
        if (null == map || map.isEmpty()) {
            return template.toString();
        }
        String template2 = template.toString();
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            template2 = template2.replace("{" + entry.getKey() + "}", Func.toStr(entry.getValue()));
        }
        return template2;
    }
    /**
     * åˆ‡åˆ†å­—符串,不去除切分后每个元素两边的空白符,不去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @param limit     é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @return åˆ‡åˆ†åŽçš„集合
     */
    public static List<String> split(CharSequence str, char separator, int limit) {
        return split(str, separator, limit, false, false);
    }
    /**
     * åˆ†å‰² å­—符串 åˆ é™¤å¸¸è§ ç©ºç™½ç¬¦
     *
     * @param str       å­—符串
     * @param delimiter åˆ†å‰²ç¬¦
     * @return å­—符串数组
     */
    public static String[] splitTrim(@Nullable String str, @Nullable String delimiter) {
        return StringUtil.delimitedListToStringArray(str, delimiter, " \t\n\n\f");
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.1.2
     */
    public static List<String> splitTrim(CharSequence str, char separator) {
        return splitTrim(str, separator, -1);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.0
     */
    public static List<String> splitTrim(CharSequence str, CharSequence separator) {
        return splitTrim(str, separator, -1);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @param limit     é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.1.0
     */
    public static List<String> splitTrim(CharSequence str, char separator, int limit) {
        return split(str, separator, limit, true, true);
    }
    /**
     * åˆ‡åˆ†å­—符串,去除切分后每个元素两边的空白符,去除空白项
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符字符
     * @param limit     é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.0
     */
    public static List<String> splitTrim(CharSequence str, CharSequence separator, int limit) {
        return split(str, separator, limit, true, true);
    }
    /**
     * åˆ‡åˆ†å­—符串,不限制分片数量
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(CharSequence str, char separator, boolean isTrim, boolean ignoreEmpty) {
        return split(str, separator, 0, isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.0.8
     */
    public static List<String> split(CharSequence str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        if (null == str) {
            return new ArrayList<>(0);
        }
        return StrSpliter.split(str.toString(), separator, limit, isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str         è¢«åˆ‡åˆ†çš„字符串
     * @param separator   åˆ†éš”符字符
     * @param limit       é™åˆ¶åˆ†ç‰‡æ•°ï¼Œ-1不限制
     * @param isTrim      æ˜¯å¦åŽ»é™¤åˆ‡åˆ†å­—ç¬¦ä¸²åŽæ¯ä¸ªå…ƒç´ ä¸¤è¾¹çš„ç©ºæ ¼
     * @param ignoreEmpty æ˜¯å¦å¿½ç•¥ç©ºä¸²
     * @return åˆ‡åˆ†åŽçš„集合
     * @since 3.2.0
     */
    public static List<String> split(CharSequence str, CharSequence separator, int limit, boolean isTrim, boolean ignoreEmpty) {
        if (null == str) {
            return new ArrayList<>(0);
        }
        final String separatorStr = (null == separator) ? null : separator.toString();
        return StrSpliter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty);
    }
    /**
     * åˆ‡åˆ†å­—符串
     *
     * @param str       è¢«åˆ‡åˆ†çš„字符串
     * @param separator åˆ†éš”符
     * @return å­—符串
     */
    public static String[] split(CharSequence str, CharSequence separator) {
        if (str == null) {
            return new String[]{};
        }
        final String separatorStr = (null == separator) ? null : separator.toString();
        return StrSpliter.splitToArray(str.toString(), separatorStr, 0, false, false);
    }
    /**
     * æ ¹æ®ç»™å®šé•¿åº¦ï¼Œå°†ç»™å®šå­—符串截取为多个部分
     *
     * @param str å­—符串
     * @param len æ¯ä¸€ä¸ªå°èŠ‚çš„é•¿åº¦
     * @return æˆªå–后的字符串数组
     * @see StrSpliter#splitByLength(String, int)
     */
    public static String[] split(CharSequence str, int len) {
        if (null == str) {
            return new String[]{};
        }
        return StrSpliter.splitByLength(str.toString(), len);
    }
    /**
     * æŒ‡å®šå­—符是否在字符串中出现过
     *
     * @param str        å­—符串
     * @param searchChar è¢«æŸ¥æ‰¾çš„字符
     * @return æ˜¯å¦åŒ…含
     * @since 3.1.2
     */
    public static boolean contains(CharSequence str, char searchChar) {
        return indexOf(str, searchChar) > -1;
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串
     *
     * @param str      æŒ‡å®šå­—符串
     * @param testStrs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ…含任意一个字符串
     * @since 3.2.0
     */
    public static boolean containsAny(CharSequence str, CharSequence... testStrs) {
        return null != getContainsStr(str, testStrs);
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串,如果包含返回找到的第一个字符串
     *
     * @param str      æŒ‡å®šå­—符串
     * @param testStrs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return è¢«åŒ…含的第一个字符串
     * @since 3.2.0
     */
    public static String getContainsStr(CharSequence str, CharSequence... testStrs) {
        if (isEmpty(str) || Func.isEmpty(testStrs)) {
            return null;
        }
        for (CharSequence checkStr : testStrs) {
            if (str.toString().contains(checkStr)) {
                return checkStr.toString();
            }
        }
        return null;
    }
    /**
     * æ˜¯å¦åŒ…含特定字符,忽略大小写,如果给定两个参数都为<code>null</code>,返回true
     *
     * @param str     è¢«æ£€æµ‹å­—符串
     * @param testStr è¢«æµ‹è¯•是否包含的字符串
     * @return æ˜¯å¦åŒ…含
     */
    public static boolean containsIgnoreCase(CharSequence str, CharSequence testStr) {
        if (null == str) {
            // å¦‚果被监测字符串和
            return null == testStr;
        }
        return str.toString().toLowerCase().contains(testStr.toString().toLowerCase());
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串<br>
     * å¿½ç•¥å¤§å°å†™
     *
     * @param str      æŒ‡å®šå­—符串
     * @param testStrs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ…含任意一个字符串
     * @since 3.2.0
     */
    public static boolean containsAnyIgnoreCase(CharSequence str, CharSequence... testStrs) {
        return null != getContainsStrIgnoreCase(str, testStrs);
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串,如果包含返回找到的第一个字符串<br>
     * å¿½ç•¥å¤§å°å†™
     *
     * @param str      æŒ‡å®šå­—符串
     * @param testStrs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return è¢«åŒ…含的第一个字符串
     * @since 3.2.0
     */
    public static String getContainsStrIgnoreCase(CharSequence str, CharSequence... testStrs) {
        if (isEmpty(str) || Func.isEmpty(testStrs)) {
            return null;
        }
        for (CharSequence testStr : testStrs) {
            if (containsIgnoreCase(str, testStr)) {
                return testStr.toString();
            }
        }
        return null;
    }
    /**
     * æ”¹è¿›JDK subString<br>
     * index从0开始计算,最后一个字符为-1<br>
     * å¦‚æžœfrom和to位置一样,返回 "" <br>
     * å¦‚æžœfrom或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br>
     * å¦‚果经过修正的index中from大于to,则互换from和to example: <br>
     * abcdefgh 2 3 =》 c <br>
     * abcdefgh 2 -3 =》 cde <br>
     *
     * @param str       String
     * @param fromIndex å¼€å§‹çš„index(包括)
     * @param toIndex   ç»“束的index(不包括)
     * @return å­—串
     */
    public static String sub(CharSequence str, int fromIndex, int toIndex) {
        if (isEmpty(str)) {
            return StringPool.EMPTY;
        }
        int len = str.length();
        if (fromIndex < 0) {
            fromIndex = len + fromIndex;
            if (fromIndex < 0) {
                fromIndex = 0;
            }
        } else if (fromIndex > len) {
            fromIndex = len;
        }
        if (toIndex < 0) {
            toIndex = len + toIndex;
            if (toIndex < 0) {
                toIndex = len;
            }
        } else if (toIndex > len) {
            toIndex = len;
        }
        if (toIndex < fromIndex) {
            int tmp = fromIndex;
            fromIndex = toIndex;
            toIndex = tmp;
        }
        if (fromIndex == toIndex) {
            return StringPool.EMPTY;
        }
        return str.toString().substring(fromIndex, toIndex);
    }
    /**
     * æˆªå–分隔字符串之前的字符串,不包括分隔字符串<br>
     * å¦‚果给定的字符串为空串(null或"")或者分隔字符串为null,返回原字符串<br>
     * å¦‚果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串
     * <p>
     * æ —子:
     *
     * <pre>
     * StringUtil.subBefore(null, *)      = null
     * StringUtil.subBefore("", *)        = ""
     * StringUtil.subBefore("abc", "a")   = ""
     * StringUtil.subBefore("abcba", "b") = "a"
     * StringUtil.subBefore("abc", "c")   = "ab"
     * StringUtil.subBefore("abc", "d")   = "abc"
     * StringUtil.subBefore("abc", "")    = ""
     * StringUtil.subBefore("abc", null)  = "abc"
     * </pre>
     *
     * @param string          è¢«æŸ¥æ‰¾çš„字符串
     * @param separator       åˆ†éš”字符串(不包括)
     * @param isLastSeparator æ˜¯å¦æŸ¥æ‰¾æœ€åŽä¸€ä¸ªåˆ†éš”字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个
     * @return åˆ‡å‰²åŽçš„字符串
     * @since 3.1.1
     */
    public static String subBefore(CharSequence string, CharSequence separator, boolean isLastSeparator) {
        if (isEmpty(string) || separator == null) {
            return null == string ? null : string.toString();
        }
        final String str = string.toString();
        final String sep = separator.toString();
        if (sep.isEmpty()) {
            return StringPool.EMPTY;
        }
        final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep);
        if (pos == INDEX_NOT_FOUND) {
            return str;
        }
        return str.substring(0, pos);
    }
    /**
     * æˆªå–分隔字符串之后的字符串,不包括分隔字符串<br>
     * å¦‚果给定的字符串为空串(null或""),返回原字符串<br>
     * å¦‚果分隔字符串为空串(null或""),则返回空串,如果分隔字符串未找到,返回空串
     * <p>
     * æ —子:
     *
     * <pre>
     * StringUtil.subAfter(null, *)      = null
     * StringUtil.subAfter("", *)        = ""
     * StringUtil.subAfter(*, null)      = ""
     * StringUtil.subAfter("abc", "a")   = "bc"
     * StringUtil.subAfter("abcba", "b") = "cba"
     * StringUtil.subAfter("abc", "c")   = ""
     * StringUtil.subAfter("abc", "d")   = ""
     * StringUtil.subAfter("abc", "")    = "abc"
     * </pre>
     *
     * @param string          è¢«æŸ¥æ‰¾çš„字符串
     * @param separator       åˆ†éš”字符串(不包括)
     * @param isLastSeparator æ˜¯å¦æŸ¥æ‰¾æœ€åŽä¸€ä¸ªåˆ†éš”字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个
     * @return åˆ‡å‰²åŽçš„字符串
     * @since 3.1.1
     */
    public static String subAfter(CharSequence string, CharSequence separator, boolean isLastSeparator) {
        if (isEmpty(string)) {
            return null == string ? null : string.toString();
        }
        if (separator == null) {
            return StringPool.EMPTY;
        }
        final String str = string.toString();
        final String sep = separator.toString();
        final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep);
        if (pos == INDEX_NOT_FOUND) {
            return StringPool.EMPTY;
        }
        return str.substring(pos + separator.length());
    }
    /**
     * æˆªå–指定字符串中间部分,不包括标识字符串<br>
     * <p>
     * æ —子:
     *
     * <pre>
     * StringUtil.subBetween("wx[b]yz", "[", "]") = "b"
     * StringUtil.subBetween(null, *, *)          = null
     * StringUtil.subBetween(*, null, *)          = null
     * StringUtil.subBetween(*, *, null)          = null
     * StringUtil.subBetween("", "", "")          = ""
     * StringUtil.subBetween("", "", "]")         = null
     * StringUtil.subBetween("", "[", "]")        = null
     * StringUtil.subBetween("yabcz", "", "")     = ""
     * StringUtil.subBetween("yabcz", "y", "z")   = "abc"
     * StringUtil.subBetween("yabczyabcz", "y", "z")   = "abc"
     * </pre>
     *
     * @param str    è¢«åˆ‡å‰²çš„字符串
     * @param before æˆªå–开始的字符串标识
     * @param after  æˆªå–到的字符串标识
     * @return æˆªå–后的字符串
     * @since 3.1.1
     */
    public static String subBetween(CharSequence str, CharSequence before, CharSequence after) {
        if (str == null || before == null || after == null) {
            return null;
        }
        final String str2 = str.toString();
        final String before2 = before.toString();
        final String after2 = after.toString();
        final int start = str2.indexOf(before2);
        if (start != INDEX_NOT_FOUND) {
            final int end = str2.indexOf(after2, start + before2.length());
            if (end != INDEX_NOT_FOUND) {
                return str2.substring(start + before2.length(), end);
            }
        }
        return null;
    }
    /**
     * æˆªå–指定字符串中间部分,不包括标识字符串<br>
     * <p>
     * æ —子:
     *
     * <pre>
     * StringUtil.subBetween(null, *)            = null
     * StringUtil.subBetween("", "")             = ""
     * StringUtil.subBetween("", "tag")          = null
     * StringUtil.subBetween("tagabctag", null)  = null
     * StringUtil.subBetween("tagabctag", "")    = ""
     * StringUtil.subBetween("tagabctag", "tag") = "abc"
     * </pre>
     *
     * @param str            è¢«åˆ‡å‰²çš„字符串
     * @param beforeAndAfter æˆªå–开始和结束的字符串标识
     * @return æˆªå–后的字符串
     * @since 3.1.1
     */
    public static String subBetween(CharSequence str, CharSequence beforeAndAfter) {
        return subBetween(str, beforeAndAfter, beforeAndAfter);
    }
    /**
     * åŽ»æŽ‰æŒ‡å®šå‰ç¼€
     *
     * @param str    å­—符串
     * @param prefix å‰ç¼€
     * @return åˆ‡æŽ‰åŽçš„字符串,若前缀不是 preffix, è¿”回原字符串
     */
    public static String removePrefix(CharSequence str, CharSequence prefix) {
        if (isEmpty(str) || isEmpty(prefix)) {
            return StringPool.EMPTY;
        }
        final String str2 = str.toString();
        if (str2.startsWith(prefix.toString())) {
            return subSuf(str2, prefix.length());
        }
        return str2;
    }
    /**
     * å¿½ç•¥å¤§å°å†™åŽ»æŽ‰æŒ‡å®šå‰ç¼€
     *
     * @param str    å­—符串
     * @param prefix å‰ç¼€
     * @return åˆ‡æŽ‰åŽçš„字符串,若前缀不是 prefix, è¿”回原字符串
     */
    public static String removePrefixIgnoreCase(CharSequence str, CharSequence prefix) {
        if (isEmpty(str) || isEmpty(prefix)) {
            return StringPool.EMPTY;
        }
        final String str2 = str.toString();
        if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) {
            return subSuf(str2, prefix.length());
        }
        return str2;
    }
    /**
     * åŽ»æŽ‰æŒ‡å®šåŽç¼€
     *
     * @param str    å­—符串
     * @param suffix åŽç¼€
     * @return åˆ‡æŽ‰åŽçš„字符串,若后缀不是 suffix, è¿”回原字符串
     */
    public static String removeSuffix(CharSequence str, CharSequence suffix) {
        if (isEmpty(str) || isEmpty(suffix)) {
            return StringPool.EMPTY;
        }
        final String str2 = str.toString();
        if (str2.endsWith(suffix.toString())) {
            return subPre(str2, str2.length() - suffix.length());
        }
        return str2;
    }
    /**
     * åŽ»æŽ‰æŒ‡å®šåŽç¼€ï¼Œå¹¶å°å†™é¦–å­—æ¯
     *
     * @param str    å­—符串
     * @param suffix åŽç¼€
     * @return åˆ‡æŽ‰åŽçš„字符串,若后缀不是 suffix, è¿”回原字符串
     */
    public static String removeSufAndLowerFirst(CharSequence str, CharSequence suffix) {
        return firstCharToLower(removeSuffix(str, suffix));
    }
    /**
     * å¿½ç•¥å¤§å°å†™åŽ»æŽ‰æŒ‡å®šåŽç¼€
     *
     * @param str    å­—符串
     * @param suffix åŽç¼€
     * @return åˆ‡æŽ‰åŽçš„字符串,若后缀不是 suffix, è¿”回原字符串
     */
    public static String removeSuffixIgnoreCase(CharSequence str, CharSequence suffix) {
        if (isEmpty(str) || isEmpty(suffix)) {
            return StringPool.EMPTY;
        }
        final String str2 = str.toString();
        if (str2.toLowerCase().endsWith(suffix.toString().toLowerCase())) {
            return subPre(str2, str2.length() - suffix.length());
        }
        return str2;
    }
    /**
     * é¦–字母变小写
     *
     * @param str å­—符串
     * @return {String}
     */
    public static String firstCharToLower(String str) {
        char firstChar = str.charAt(0);
        if (firstChar >= CharPool.UPPER_A && firstChar <= CharPool.UPPER_Z) {
            char[] arr = str.toCharArray();
            arr[0] += (CharPool.LOWER_A - CharPool.UPPER_A);
            return new String(arr);
        }
        return str;
    }
    /**
     * é¦–字母变大写
     *
     * @param str å­—符串
     * @return {String}
     */
    public static String firstCharToUpper(String str) {
        char firstChar = str.charAt(0);
        if (firstChar >= CharPool.LOWER_A && firstChar <= CharPool.LOWER_Z) {
            char[] arr = str.toCharArray();
            arr[0] -= (CharPool.LOWER_A - CharPool.UPPER_A);
            return new String(arr);
        }
        return str;
    }
    /**
     * åˆ‡å‰²æŒ‡å®šä½ç½®ä¹‹å‰éƒ¨åˆ†çš„字符串
     *
     * @param string  å­—符串
     * @param toIndex åˆ‡å‰²åˆ°çš„位置(不包括)
     * @return åˆ‡å‰²åŽçš„剩余的前半部分字符串
     */
    public static String subPre(CharSequence string, int toIndex) {
        return sub(string, 0, toIndex);
    }
    /**
     * åˆ‡å‰²æŒ‡å®šä½ç½®ä¹‹åŽéƒ¨åˆ†çš„字符串
     *
     * @param string    å­—符串
     * @param fromIndex åˆ‡å‰²å¼€å§‹çš„位置(包括)
     * @return åˆ‡å‰²åŽåŽå‰©ä½™çš„后半部分字符串
     */
    public static String subSuf(CharSequence string, int fromIndex) {
        if (isEmpty(string)) {
            return null;
        }
        return sub(string, fromIndex, string.length());
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找指定字符
     *
     * @param str        å­—符串
     * @param searchChar è¢«æŸ¥æ‰¾çš„字符
     * @return ä½ç½®
     */
    public static int indexOf(final CharSequence str, char searchChar) {
        return indexOf(str, searchChar, 0);
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找指定字符
     *
     * @param str        å­—符串
     * @param searchChar è¢«æŸ¥æ‰¾çš„字符
     * @param start      èµ·å§‹ä½ç½®ï¼Œå¦‚果小于0,从0开始查找
     * @return ä½ç½®
     */
    public static int indexOf(final CharSequence str, char searchChar, int start) {
        if (str instanceof String) {
            return ((String) str).indexOf(searchChar, start);
        } else {
            return indexOf(str, searchChar, start, -1);
        }
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找指定字符
     *
     * @param str        å­—符串
     * @param searchChar è¢«æŸ¥æ‰¾çš„字符
     * @param start      èµ·å§‹ä½ç½®ï¼Œå¦‚果小于0,从0开始查找
     * @param end        ç»ˆæ­¢ä½ç½®ï¼Œå¦‚果超过str.length()则默认查找到字符串末尾
     * @return ä½ç½®
     */
    public static int indexOf(final CharSequence str, char searchChar, int start, int end) {
        final int len = str.length();
        if (start < 0 || start > len) {
            start = 0;
        }
        if (end > len || end < 0) {
            end = len;
        }
        for (int i = start; i < end; i++) {
            if (str.charAt(i) == searchChar) {
                return i;
            }
        }
        return -1;
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串,忽略大小写<br>
     *
     * <pre>
     * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
     * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
     * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
     * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
     * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
     * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
     * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
     * </pre>
     *
     * @param str       å­—符串
     * @param searchStr éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
        return indexOfIgnoreCase(str, searchStr, 0);
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串
     *
     * <pre>
     * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
     * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
     * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
     * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
     * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
     * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
     * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
     * </pre>
     *
     * @param str       å­—符串
     * @param searchStr éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @param fromIndex èµ·å§‹ä½ç½®
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) {
        return indexOf(str, searchStr, fromIndex, true);
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…反向查找字符串
     *
     * @param str        å­—符串
     * @param searchStr  éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @param fromIndex  èµ·å§‹ä½ç½®
     * @param ignoreCase æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int indexOf(final CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) {
        if (str == null || searchStr == null) {
            return INDEX_NOT_FOUND;
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        final int endLimit = str.length() - searchStr.length() + 1;
        if (fromIndex > endLimit) {
            return INDEX_NOT_FOUND;
        }
        if (searchStr.length() == 0) {
            return fromIndex;
        }
        if (false == ignoreCase) {
            // ä¸å¿½ç•¥å¤§å°å†™è°ƒç”¨JDK方法
            return str.toString().indexOf(searchStr.toString(), fromIndex);
        }
        for (int i = fromIndex; i < endLimit; i++) {
            if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
                return i;
            }
        }
        return INDEX_NOT_FOUND;
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串,忽略大小写<br>
     *
     * @param str       å­—符串
     * @param searchStr éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
        return lastIndexOfIgnoreCase(str, searchStr, str.length());
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串,忽略大小写<br>
     *
     * @param str       å­—符串
     * @param searchStr éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @param fromIndex èµ·å§‹ä½ç½®ï¼Œä»ŽåŽå¾€å‰è®¡æ•°
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) {
        return lastIndexOf(str, searchStr, fromIndex, true);
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串<br>
     *
     * @param str        å­—符串
     * @param searchStr  éœ€è¦æŸ¥æ‰¾ä½ç½®çš„字符串
     * @param fromIndex  èµ·å§‹ä½ç½®ï¼Œä»ŽåŽå¾€å‰è®¡æ•°
     * @param ignoreCase æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return ä½ç½®
     * @since 3.2.1
     */
    public static int lastIndexOf(final CharSequence str, final CharSequence searchStr, int fromIndex, boolean ignoreCase) {
        if (str == null || searchStr == null) {
            return INDEX_NOT_FOUND;
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        fromIndex = Math.min(fromIndex, str.length());
        if (searchStr.length() == 0) {
            return fromIndex;
        }
        if (false == ignoreCase) {
            // ä¸å¿½ç•¥å¤§å°å†™è°ƒç”¨JDK方法
            return str.toString().lastIndexOf(searchStr.toString(), fromIndex);
        }
        for (int i = fromIndex; i > 0; i--) {
            if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
                return i;
            }
        }
        return INDEX_NOT_FOUND;
    }
    /**
     * è¿”回字符串 searchStr åœ¨å­—符串 str ä¸­ç¬¬ ordinal æ¬¡å‡ºçŽ°çš„ä½ç½®ã€‚<br>
     * æ­¤æ–¹æ³•来自:Apache-Commons-Lang
     * <p>
     * æ —子(*代表任意字符):
     *
     * <pre>
     * StringUtil.ordinalIndexOf(null, *, *)          = -1
     * StringUtil.ordinalIndexOf(*, null, *)          = -1
     * StringUtil.ordinalIndexOf("", "", *)           = 0
     * StringUtil.ordinalIndexOf("aabaabaa", "a", 1)  = 0
     * StringUtil.ordinalIndexOf("aabaabaa", "a", 2)  = 1
     * StringUtil.ordinalIndexOf("aabaabaa", "b", 1)  = 2
     * StringUtil.ordinalIndexOf("aabaabaa", "b", 2)  = 5
     * StringUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1
     * StringUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4
     * StringUtil.ordinalIndexOf("aabaabaa", "", 1)   = 0
     * StringUtil.ordinalIndexOf("aabaabaa", "", 2)   = 0
     * </pre>
     *
     * @param str       è¢«æ£€æŸ¥çš„字符串,可以为null
     * @param searchStr è¢«æŸ¥æ‰¾çš„字符串,可以为null
     * @param ordinal   ç¬¬å‡ æ¬¡å‡ºçŽ°çš„ä½ç½®
     * @return æŸ¥æ‰¾åˆ°çš„位置
     * @since 3.2.3
     */
    public static int ordinalIndexOf(String str, String searchStr, int ordinal) {
        if (str == null || searchStr == null || ordinal <= 0) {
            return INDEX_NOT_FOUND;
        }
        if (searchStr.length() == 0) {
            return 0;
        }
        int found = 0;
        int index = INDEX_NOT_FOUND;
        do {
            index = str.indexOf(searchStr, index + 1);
            if (index < 0) {
                return index;
            }
            found++;
        } while (found < ordinal);
        return index;
    }
    /**
     * æˆªå–两个字符串的不同部分(长度一致),判断截取的子串是否相同<br>
     * ä»»æ„ä¸€ä¸ªå­—符串为null返回false
     *
     * @param str1       ç¬¬ä¸€ä¸ªå­—符串
     * @param start1     ç¬¬ä¸€ä¸ªå­—符串开始的位置
     * @param str2       ç¬¬äºŒä¸ªå­—符串
     * @param start2     ç¬¬äºŒä¸ªå­—符串开始的位置
     * @param length     æˆªå–长度
     * @param ignoreCase æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return å­ä¸²æ˜¯å¦ç›¸åŒ
     * @since 3.2.1
     */
    public static boolean isSubEquals(CharSequence str1, int start1, CharSequence str2, int start2, int length, boolean ignoreCase) {
        if (null == str1 || null == str2) {
            return false;
        }
        return str1.toString().regionMatches(ignoreCase, start1, str2.toString(), start2, length);
    }
    /**
     * æ¯”较两个字符串(大小写敏感)。
     *
     * <pre>
     * equalsIgnoreCase(null, null)   = true
     * equalsIgnoreCase(null, &quot;abc&quot;)  = false
     * equalsIgnoreCase(&quot;abc&quot;, null)  = false
     * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
     * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
     * </pre>
     *
     * @param str1 è¦æ¯”较的字符串1
     * @param str2 è¦æ¯”较的字符串2
     * @return å¦‚果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
     */
    public static boolean equals(CharSequence str1, CharSequence str2) {
        return equals(str1, str2, false);
    }
    /**
     * æ¯”较两个字符串(大小写不敏感)。
     *
     * <pre>
     * equalsIgnoreCase(null, null)   = true
     * equalsIgnoreCase(null, &quot;abc&quot;)  = false
     * equalsIgnoreCase(&quot;abc&quot;, null)  = false
     * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
     * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
     * </pre>
     *
     * @param str1 è¦æ¯”较的字符串1
     * @param str2 è¦æ¯”较的字符串2
     * @return å¦‚果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
     */
    public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) {
        return equals(str1, str2, true);
    }
    /**
     * æ¯”较两个字符串是否相等。
     *
     * @param str1       è¦æ¯”较的字符串1
     * @param str2       è¦æ¯”较的字符串2
     * @param ignoreCase æ˜¯å¦å¿½ç•¥å¤§å°å†™
     * @return å¦‚果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code>
     * @since 3.2.0
     */
    public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) {
        if (null == str1) {
            // åªæœ‰ä¸¤ä¸ªéƒ½ä¸ºnull才判断相等
            return str2 == null;
        }
        if (null == str2) {
            // å­—符串2空,字符串1非空,直接false
            return false;
        }
        if (ignoreCase) {
            return str1.toString().equalsIgnoreCase(str2.toString());
        } else {
            return str1.equals(str2);
        }
    }
    /**
     * åˆ›å»ºStringBuilder对象
     *
     * @return {String}Builder对象
     */
    public static StringBuilder builder() {
        return new StringBuilder();
    }
    /**
     * åˆ›å»ºStringBuilder对象
     *
     * @param capacity åˆå§‹å¤§å°
     * @return {String}Builder对象
     */
    public static StringBuilder builder(int capacity) {
        return new StringBuilder(capacity);
    }
    /**
     * åˆ›å»ºStringBuilder对象
     *
     * @param strs åˆå§‹å­—符串列表
     * @return {String}Builder对象
     */
    public static StringBuilder builder(CharSequence... strs) {
        final StringBuilder sb = new StringBuilder();
        for (CharSequence str : strs) {
            sb.append(str);
        }
        return sb;
    }
    /**
     * åˆ›å»ºStringBuilder对象
     *
     * @param sb   åˆå§‹StringBuilder
     * @param strs åˆå§‹å­—符串列表
     * @return {String}Builder对象
     */
    public static StringBuilder appendBuilder(StringBuilder sb, CharSequence... strs) {
        for (CharSequence str : strs) {
            sb.append(str);
        }
        return sb;
    }
    /**
     * èŽ·å¾—StringReader
     *
     * @param str å­—符串
     * @return {String}Reader
     */
    public static StringReader getReader(CharSequence str) {
        if (null == str) {
            return null;
        }
        return new StringReader(str.toString());
    }
    /**
     * èŽ·å¾—StringWriter
     *
     * @return {String}Writer
     */
    public static StringWriter getWriter() {
        return new StringWriter();
    }
    /**
     * ç»Ÿè®¡æŒ‡å®šå†…容中包含指定字符串的数量<br>
     * å‚数为 {@code null} æˆ–者 "" è¿”回 {@code 0}.
     *
     * <pre>
     * StringUtil.count(null, *)       = 0
     * StringUtil.count("", *)         = 0
     * StringUtil.count("abba", null)  = 0
     * StringUtil.count("abba", "")    = 0
     * StringUtil.count("abba", "a")   = 2
     * StringUtil.count("abba", "ab")  = 1
     * StringUtil.count("abba", "xxx") = 0
     * </pre>
     *
     * @param content      è¢«æŸ¥æ‰¾çš„字符串
     * @param strForSearch éœ€è¦æŸ¥æ‰¾çš„字符串
     * @return æŸ¥æ‰¾åˆ°çš„个数
     */
    public static int count(CharSequence content, CharSequence strForSearch) {
        if (Func.hasEmpty(content, strForSearch) || strForSearch.length() > content.length()) {
            return 0;
        }
        int count = 0;
        int idx = 0;
        final String content2 = content.toString();
        final String strForSearch2 = strForSearch.toString();
        while ((idx = content2.indexOf(strForSearch2, idx)) > -1) {
            count++;
            idx += strForSearch.length();
        }
        return count;
    }
    /**
     * ç»Ÿè®¡æŒ‡å®šå†…容中包含指定字符的数量
     *
     * @param content       å†…容
     * @param charForSearch è¢«ç»Ÿè®¡çš„字符
     * @return åŒ…含数量
     */
    public static int count(CharSequence content, char charForSearch) {
        int count = 0;
        if (isEmpty(content)) {
            return 0;
        }
        int contentLength = content.length();
        for (int i = 0; i < contentLength; i++) {
            if (charForSearch == content.charAt(i)) {
                count++;
            }
        }
        return count;
    }
    /**
     * ä¸‹åˆ’线转驼峰
     *
     * @param para å­—符串
     * @return {String}
     */
    public static String underlineToHump(String para) {
        if (isBlank(para)) {
            return StringPool.EMPTY;
        }
        StringBuilder result = new StringBuilder();
        String[] a = para.split("_");
        for (String s : a) {
            if (result.length() == 0) {
                result.append(s.toLowerCase());
            } else {
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }
    /**
     * é©¼å³°è½¬ä¸‹åˆ’线
     *
     * @param para å­—符串
     * @return {String}
     */
    public static String humpToUnderline(String para) {
        if (isBlank(para)) {
            return StringPool.EMPTY;
        }
        para = firstCharToLower(para);
        StringBuilder sb = new StringBuilder(para);
        int temp = 0;
        for (int i = 0; i < para.length(); i++) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.insert(i + temp, "_");
                temp += 1;
            }
        }
        return sb.toString().toLowerCase();
    }
    /**
     * æ¨ªçº¿è½¬é©¼å³°
     *
     * @param para å­—符串
     * @return {String}
     */
    public static String lineToHump(String para) {
        if (isBlank(para)) {
            return StringPool.EMPTY;
        }
        StringBuilder result = new StringBuilder();
        String[] a = para.split("-");
        for (String s : a) {
            if (result.length() == 0) {
                result.append(s.toLowerCase());
            } else {
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }
    /**
     * é©¼å³°è½¬æ¨ªçº¿
     *
     * @param para å­—符串
     * @return {String}
     */
    public static String humpToLine(String para) {
        if (isBlank(para)) {
            return StringPool.EMPTY;
        }
        para = firstCharToLower(para);
        StringBuilder sb = new StringBuilder(para);
        int temp = 0;
        for (int i = 0; i < para.length(); i++) {
            if (Character.isUpperCase(para.charAt(i))) {
                sb.insert(i + temp, "-");
                temp += 1;
            }
        }
        return sb.toString().toLowerCase();
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/jackson/BladeJavaTimeModule.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package com.vci.web.util.jackson;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.vci.web.util.DateTimeUtil;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
 * java 8 æ—¶é—´é»˜è®¤åºåˆ—化
 *
 * @author L.cm
 */
public class BladeJavaTimeModule extends SimpleModule {
    public static final BladeJavaTimeModule INSTANCE = new BladeJavaTimeModule();
    public BladeJavaTimeModule() {
        super(PackageVersion.VERSION);
        this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeUtil.DATETIME_FORMAT));
        this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeUtil.DATE_FORMAT));
        this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeUtil.TIME_FORMAT));
        this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeUtil.DATETIME_FORMAT));
        this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeUtil.DATE_FORMAT));
        this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeUtil.TIME_FORMAT));
    }
}
Source/platformProject/vci-platform-web/src/main/java/com/vci/web/util/jackson/JsonUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,705 @@
/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill åº„骞 (smallchill@163.com)
 */
package com.vci.web.util.jackson;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.CollectionLikeType;
import com.fasterxml.jackson.databind.type.MapType;
import com.vci.web.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.*;
/**
 * Jackson工具类
 *
 * @author Chill
 */
@Slf4j
public class JsonUtil {
    /**
     * å°†å¯¹è±¡åºåˆ—化成json字符串
     *
     * @param value javaBean
     * @return jsonString json字符串
     */
    public static <T> String toJson(T value) {
        try {
            return getInstance().writeValueAsString(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    /**
     * å°†å¯¹è±¡åºåˆ—化成 json byte æ•°ç»„
     *
     * @param object javaBean
     * @return jsonString json字符串
     */
    public static byte[] toJsonAsBytes(Object object) {
        try {
            return getInstance().writeValueAsBytes(object);
        } catch (JsonProcessingException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param content   content
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(String content, Class<T> valueType) {
        try {
            return getInstance().readValue(content, valueType);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    /**
     * å°†json反序列化成对象
     *
     * @param content       content
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(String content, TypeReference<T> typeReference) {
        try {
            return getInstance().readValue(content, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json byte æ•°ç»„反序列化成对象
     *
     * @param bytes     json bytes
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(byte[] bytes, Class<T> valueType) {
        try {
            return getInstance().readValue(bytes, valueType);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param bytes         bytes
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(byte[] bytes, TypeReference<T> typeReference) {
        try {
            return getInstance().readValue(bytes, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in        InputStream
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(InputStream in, Class<T> valueType) {
        try {
            return getInstance().readValue(in, valueType);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in            InputStream
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    public static <T> T parse(InputStream in, TypeReference<T> typeReference) {
        try {
            return getInstance().readValue(in, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成List对象
     *
     * @param content      content
     * @param valueTypeRef class
     * @param <T>          T æ³›åž‹æ ‡è®°
     * @return List<T>
     */
    public static <T> List<T> parseArray(String content, Class<T> valueTypeRef) {
        try {
            if (!StringUtil.startsWithIgnoreCase(content, StringPool.LEFT_SQ_BRACKET)) {
                content = StringPool.LEFT_SQ_BRACKET + content + StringPool.RIGHT_SQ_BRACKET;
            }
            List<Map<String, Object>> list = getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() {
            });
            List<T> result = new ArrayList<>();
            for (Map<String, Object> map : list) {
                result.add(toPojo(map, valueTypeRef));
            }
            return result;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param jsonString jsonString
     * @return jsonString json字符串
     */
    public static JsonNode readTree(String jsonString) {
        Objects.requireNonNull(jsonString, "jsonString is null");
        try {
            return getInstance().readTree(jsonString);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param in InputStream
     * @return jsonString json字符串
     */
    public static JsonNode readTree(InputStream in) {
        Objects.requireNonNull(in, "InputStream in is null");
        try {
            return getInstance().readTree(in);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param content content
     * @return jsonString json字符串
     */
    public static JsonNode readTree(byte[] content) {
        Objects.requireNonNull(content, "byte[] content is null");
        try {
            return getInstance().readTree(content);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json字符串转成 JsonNode
     *
     * @param jsonParser JsonParser
     * @return jsonString json字符串
     */
    public static JsonNode readTree(JsonParser jsonParser) {
        Objects.requireNonNull(jsonParser, "jsonParser is null");
        try {
            return getInstance().readTree(jsonParser);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json byte æ•°ç»„反序列化成对象
     *
     * @param content   json bytes
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable byte[] content, Class<T> valueType) {
        if (ObjectUtil.isEmpty(content)) {
            return null;
        }
        try {
            return getInstance().readValue(content, valueType);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param jsonString jsonString
     * @param valueType  class
     * @param <T>        T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable String jsonString, Class<T> valueType) {
        if (StringUtil.isBlank(jsonString)) {
            return null;
        }
        try {
            return getInstance().readValue(jsonString, valueType);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in        InputStream
     * @param valueType class
     * @param <T>       T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable InputStream in, Class<T> valueType) {
        if (in == null) {
            return null;
        }
        try {
            return getInstance().readValue(in, valueType);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param content       bytes
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable byte[] content, TypeReference<T> typeReference) {
        if (ObjectUtil.isEmpty(content)) {
            return null;
        }
        try {
            return getInstance().readValue(content, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param jsonString    jsonString
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable String jsonString, TypeReference<T> typeReference) {
        if (StringUtil.isBlank(jsonString)) {
            return null;
        }
        try {
            return getInstance().readValue(jsonString, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°†json反序列化成对象
     *
     * @param in            InputStream
     * @param typeReference æ³›åž‹ç±»åž‹
     * @param <T>           T æ³›åž‹æ ‡è®°
     * @return Bean
     */
    @Nullable
    public static <T> T readValue(@Nullable InputStream in, TypeReference<T> typeReference) {
        if (in == null) {
            return null;
        }
        try {
            return getInstance().readValue(in, typeReference);
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å°è£… map type
     *
     * @param keyClass   key ç±»åž‹
     * @param valueClass value ç±»åž‹
     * @return MapType
     */
    public static MapType getMapType(Class<?> keyClass, Class<?> valueClass) {
        return getInstance().getTypeFactory().constructMapType(Map.class, keyClass, valueClass);
    }
    /**
     * å°è£… map type
     *
     * @param elementClass é›†åˆå€¼ç±»åž‹
     * @return CollectionLikeType
     */
    public static CollectionLikeType getListType(Class<?> elementClass) {
        return getInstance().getTypeFactory().constructCollectionLikeType(List.class, elementClass);
    }
    /**
     * è¯»å–集合
     *
     * @param content      bytes
     * @param elementClass elementClass
     * @param <T>          æ³›åž‹
     * @return é›†åˆ
     */
    public static <T> List<T> readList(@Nullable byte[] content, Class<T> elementClass) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyList();
        }
        try {
            return getInstance().readValue(content, getListType(elementClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content      InputStream
     * @param elementClass elementClass
     * @param <T>          æ³›åž‹
     * @return é›†åˆ
     */
    public static <T> List<T> readList(@Nullable InputStream content, Class<T> elementClass) {
        if (content == null) {
            return Collections.emptyList();
        }
        try {
            return getInstance().readValue(content, getListType(elementClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content      bytes
     * @param elementClass elementClass
     * @param <T>          æ³›åž‹
     * @return é›†åˆ
     */
    public static <T> List<T> readList(@Nullable String content, Class<T> elementClass) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyList();
        }
        try {
            return getInstance().readValue(content, getListType(elementClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content    bytes
     * @param keyClass   key类型
     * @param valueClass å€¼ç±»åž‹
     * @param <K>        æ³›åž‹
     * @param <V>        æ³›åž‹
     * @return é›†åˆ
     */
    public static <K, V> Map<K, V> readMap(@Nullable byte[] content, Class<?> keyClass, Class<?> valueClass) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyMap();
        }
        try {
            return getInstance().readValue(content, getMapType(keyClass, valueClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content    InputStream
     * @param keyClass   key类型
     * @param valueClass å€¼ç±»åž‹
     * @param <K>        æ³›åž‹
     * @param <V>        æ³›åž‹
     * @return é›†åˆ
     */
    public static <K, V> Map<K, V> readMap(@Nullable InputStream content, Class<?> keyClass, Class<?> valueClass) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyMap();
        }
        try {
            return getInstance().readValue(content, getMapType(keyClass, valueClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content    bytes
     * @param keyClass   key类型
     * @param valueClass å€¼ç±»åž‹
     * @param <K>        æ³›åž‹
     * @param <V>        æ³›åž‹
     * @return é›†åˆ
     */
    public static <K, V> Map<K, V> readMap(@Nullable String content, Class<?> keyClass, Class<?> valueClass) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyMap();
        }
        try {
            return getInstance().readValue(content, getMapType(keyClass, valueClass));
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * è¯»å–集合
     *
     * @param content bytes
     * @return é›†åˆ
     */
    public static Map<String, Object> readMap(@Nullable String content) {
        return readMap(content, String.class, Object.class);
    }
    /**
     * è¯»å–集合
     *
     * @param content bytes
     * @return é›†åˆ
     */
    public static List<Map<String, Object>> readListMap(@Nullable String content) {
        if (ObjectUtil.isEmpty(content)) {
            return Collections.emptyList();
        }
        try {
            return getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() {
            });
        } catch (IOException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * jackson çš„类型转换
     *
     * @param fromValue   æ¥æºå¯¹è±¡
     * @param toValueType è½¬æ¢çš„类型
     * @param <T>         æ³›åž‹æ ‡è®°
     * @return è½¬æ¢ç»“æžœ
     */
    public static <T> T convertValue(Object fromValue, Class<T> toValueType) {
        return getInstance().convertValue(fromValue, toValueType);
    }
    /**
     * jackson çš„类型转换
     *
     * @param fromValue   æ¥æºå¯¹è±¡
     * @param toValueType è½¬æ¢çš„类型
     * @param <T>         æ³›åž‹æ ‡è®°
     * @return è½¬æ¢ç»“æžœ
     */
    public static <T> T convertValue(Object fromValue, JavaType toValueType) {
        return getInstance().convertValue(fromValue, toValueType);
    }
    /**
     * jackson çš„类型转换
     *
     * @param fromValue      æ¥æºå¯¹è±¡
     * @param toValueTypeRef æ³›åž‹ç±»åž‹
     * @param <T>            æ³›åž‹æ ‡è®°
     * @return è½¬æ¢ç»“æžœ
     */
    public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) {
        return getInstance().convertValue(fromValue, toValueTypeRef);
    }
    /**
     * tree è½¬å¯¹è±¡
     *
     * @param treeNode  TreeNode
     * @param valueType valueType
     * @param <T>       æ³›åž‹æ ‡è®°
     * @return è½¬æ¢ç»“æžœ
     */
    public static <T> T treeToValue(TreeNode treeNode, Class<T> valueType) {
        try {
            return getInstance().treeToValue(treeNode, valueType);
        } catch (JsonProcessingException e) {
            throw Exceptions.unchecked(e);
        }
    }
    /**
     * å¯¹è±¡è½¬ä¸º json node
     *
     * @param value å¯¹è±¡
     * @return JsonNode
     */
    public static JsonNode valueToTree(@Nullable Object value) {
        return getInstance().valueToTree(value);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦å¯ä»¥åºåˆ—化
     *
     * @param value å¯¹è±¡
     * @return æ˜¯å¦å¯ä»¥åºåˆ—化
     */
    public static boolean canSerialize(@Nullable Object value) {
        if (value == null) {
            return true;
        }
        return getInstance().canSerialize(value.getClass());
    }
    public static Map<String, Object> toMap(String content) {
        try {
            return getInstance().readValue(content, Map.class);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    public static <T> Map<String, T> toMap(String content, Class<T> valueTypeRef) {
        try {
            Map<String, Map<String, Object>> map = getInstance().readValue(content, new TypeReference<Map<String, Map<String, Object>>>() {
            });
            Map<String, T> result = new HashMap<>(16);
            for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
                result.put(entry.getKey(), toPojo(entry.getValue(), valueTypeRef));
            }
            return result;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
    public static <T> T toPojo(Map fromValue, Class<T> toValueType) {
        return getInstance().convertValue(fromValue, toValueType);
    }
    public static ObjectMapper getInstance() {
        return JacksonHolder.INSTANCE;
    }
    private static class JacksonHolder {
        private static final ObjectMapper INSTANCE = new JacksonObjectMapper();
    }
    private static class JacksonObjectMapper extends ObjectMapper {
        private static final long serialVersionUID = 4288193147502386170L;
        private static final Locale CHINA = Locale.CHINA;
        public JacksonObjectMapper(ObjectMapper src) {
            super(src);
        }
        public JacksonObjectMapper() {
            super();
            //设置地点为中国
            super.setLocale(CHINA);
            //去掉默认的时间戳格式
            super.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            //设置为中国上海时区
            super.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
            //序列化时,日期的统一格式
            super.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA));
            // å•引号
            super.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
            // å…è®¸JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)
            super.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
            super.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true);
            super.findAndRegisterModules();
            //失败处理
            super.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            super.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            //单引号处理
            super.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);
            //反序列化时,属性不存在的兼容处理s
            super.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            //日期格式化
            super.registerModule(new BladeJavaTimeModule());
            super.findAndRegisterModules();
        }
        @Override
        public ObjectMapper copy() {
            return new JacksonObjectMapper(this);
        }
    }
}