{"id":46661252,"url":"https://github.com/cutexingluo/xingtools","last_synced_at":"2026-04-02T20:01:24.315Z","repository":{"id":248954815,"uuid":"829956171","full_name":"cutexingluo/xingtools","owner":"cutexingluo","description":"一个功能丰富且易用的 Java工具库的整合框架starter。 星天制作的 Java SDK 工具包 分组版本，继承hutool，可以称为 hutool-plus， 兼容  ican, ruoyi 等工具包，接口、算法、封装工具类，并进行了Spring 系列等组件扩展。 核心：https://github.com/cutexingluo/xingcore","archived":false,"fork":false,"pushed_at":"2026-03-31T09:29:46.000Z","size":5396,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-31T09:35:47.879Z","etag":null,"topics":["algorithm","hutool","java","spring-boot","spring-security"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cutexingluo.png","metadata":{"files":{"readme":"README-OLD.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-17T10:22:36.000Z","updated_at":"2026-03-31T09:25:30.000Z","dependencies_parsed_at":"2024-07-26T10:11:09.905Z","dependency_job_id":"d80d33a3-c608-44f3-9984-b6c010de14d6","html_url":"https://github.com/cutexingluo/xingtools","commit_stats":null,"previous_names":["cutexingluo/xingtools"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/cutexingluo/xingtools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cutexingluo%2Fxingtools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cutexingluo%2Fxingtools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cutexingluo%2Fxingtools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cutexingluo%2Fxingtools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cutexingluo","download_url":"https://codeload.github.com/cutexingluo/xingtools/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cutexingluo%2Fxingtools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314787,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","hutool","java","spring-boot","spring-security"],"created_at":"2026-03-08T11:35:47.300Z","updated_at":"2026-04-02T20:01:24.291Z","avatar_url":"https://github.com/cutexingluo.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xingtools 工具包\n\n## :book:相关介绍\nxingtools sdk 工具包，v1.1.7 正式版发布。( 依赖的版本不能低于 1.1.1 )\n星天（xingtian）制作的 Java 工具包，是基于 Springboot 2.7.18 和 SpringBoot 3.0.5 制作的 ,  基于 Java 8 和 Java 17，它是一个整合各工具类的整合包。\n\n### :scroll:简介\n\n是一个功能丰富且易用的 **Java工具库**，通过诸多实用工具类的使用，旨在帮助开发者快速、便捷地完成各类开发任务。 这些封装的工具涵盖了hutool包（依赖[hutool包](https://gitee.com/dromara/hutool)）, 部分 ruoyi 工具类，包含了系列字符串、数字、集合、编码、日期、文件、IO、加密、数据库JDBC、JSON、HTTP客户端等一系列基础操作，还包含了 ACM算法，JDK版本兼容包，各种base接口，快速开发工具类（链式调用、逻辑建造）、注解AOP装配，配置自动装配，Spring 扩展，Security扩展，OAuth2扩展，Cloud扩展，可以满足各种不同的开发需求。\n\n目前仍使用 xingtool 文档 v1.0.5 [使用文档](使用文档.md)，未来会更新，别急哦各位，大部分类名及用法没有更改，可以参考。\n\n###   :golf:本包说明\n\n该依赖为 xingtools sdk 工具包 分组版本。 它是一个整合各工具类的整合starter。具体详情详见 [xingtool-spring-boot-starter](https://gitee.com/SangonomiyaKokomi/xingtool)  这个原sdk。 该分组工具包为升级版，将核心拆分应对不同使用情况，大大提高灵活性，未来原sdk可能会依赖该升级版的sdk。如果你是jdk任何版本（ jdk8, jdk17 ）都可以进行使用。唯一缺点就是可能会需要多个（两个及以上，因为需要导入pkg的jdk版本包）的依赖。\n\n## :wrench:包含组件\n\n| 模块                                | 介绍                                                         |\n| ----------------------------------- | ------------------------------------------------------------ |\n| xingtools-core                      | 核心，包括各种接口，实体类和工具类                           |\n| xingtools-pkg-jdk8                  | 依赖core包，jdk 分类包，对不同的jdk版本提供兼容性            |\n| xingtools-pkg-jdk17                 | 依赖core包，jdk 分类包，对不同的jdk版本提供兼容性            |\n| xingtools-web                       | 依赖core和pkg包，提供一些 http 工具                          |\n| xingtools-extra                     | 依赖core，附加，也就是基于 SpringBoot 的一些工具或实体类     |\n| xingtools-db                        | 依赖core，数据库操作，包含mybatis-plus等操作                 |\n| xingtools-mvc                       | 依赖web，extra，db三包，基于 SpringBoot-Web的一些集成工具或实体类 |\n| xingtools-log                       | 依赖mvc，包含日志扩展操作的封装                              |\n| xingtools-cloud                     | 依赖mvc，基于SpringCloud，包括各种 cloud，security，oauth 的工具 |\n| xingtools-aop                       | 依赖mvc，log，cloud三包，提供前面依赖的aop注解和切面类       |\n| xingtools-unified                   | 依赖aop，整合包，整合所有依赖并依赖 hutool-all               |\n| xingtools-spring-boot               | 整合版本，排除pkg-jdk依赖，在这之后需要配合pkg-jdk依赖使用   |\n| xingtools-spring-boot-autoconfigure | 整合版本的自动装配，含各种自动装配配置，开关，注解，类等     |\n| xingtools-spring-boot-starter       | 最终依赖包                                                   |\n\n当前版本组件之间的依赖关系如下：（v1.1.2 开始组件依赖更新，后续沿用该依赖关系）\n\n![image-20240808174556862](./assets/image-20240808174556862.png)\n\n​\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t**组件依赖关系图**\n\n目前使 pkg包 仅依赖 core 包，可以按需导入从前面开始的依赖。\n\n## :bookmark:依赖使用\n\n### :inbox_tray:安装教程\n\n\u003e 使用 Maven 导入依赖\n\nMaven 依赖（JDK8版本）\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003etop.cutexingluo.tools\u003c/groupId\u003e\n\t\u003cartifactId\u003exingtools-spring-boot-starter\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.7\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n\t\u003cgroupId\u003etop.cutexingluo.tools\u003c/groupId\u003e\n\t\u003cartifactId\u003exingtools-pkg-jdk8\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.7\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nMaven 依赖（JDK17版本）\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003etop.cutexingluo.tools\u003c/groupId\u003e\n\t\u003cartifactId\u003exingtools-spring-boot-starter\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.7\u003c/version\u003e\n\u003c/dependency\u003e\n\u003cdependency\u003e\n\t\u003cgroupId\u003etop.cutexingluo.tools\u003c/groupId\u003e\n\t\u003cartifactId\u003exingtools-pkg-jdk17\u003c/artifactId\u003e\n\t\u003cversion\u003e1.1.7\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n第二个包 （pkg包） 代表存在兼容 jdk 版本的工具，必须存在。\n\n目前推荐使用的版本如下：（其他版本有一定bug，如需使用请参考更新公告的版本使用攻略）\n\n```wiki\n极力推荐使用最新版 v1.1.7\nxingtools v1.1.3, v1.1.4, v1.1.5, v1.1.6, v1.1.7\nxingtool v1.0.1, v1.0.4, v1.0.5\n```\n\n如果想使用老版本依赖，可以使用以下依赖 (xingtool 仅支持 JDK8 )\n\n```xml\n\u003cdependency\u003e\n\t\u003cgroupId\u003etop.cutexingluo.tools\u003c/groupId\u003e\n\t\u003cartifactId\u003exingtool-spring-boot-starter\u003c/artifactId\u003e\n\t\u003cversion\u003e1.0.5\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### :apple:使用方式\n\n#### :lemon:使用讲解\n\n1). 可以通过Util.静态类的方式调出静态方法，一般由XT开头的类，例如XTObjUtil等，以便直接调出类名、方法，根据类名意思了解该功能，好处是暂时不用查文档，并且和hutool互补，能够加快开发效率。\n2). 可以通过new的方式获得非单例对象，也是常用的方式。\n3). 在启动类上加上@EnableXingToolsServer，开启自动注入，比如默认开启的两个注解aop(例如@Printlog注解，以及其他现版本默认未开启的各种日志异常拦截aop等),其他的配置或者aop需要在配置文件中开启，以xingtools开头即可点出，例如\n\n```properties\n# 开启 redis\nxingtools.enabled.redisconfig=true\n# 开启 redis 的多个工具类，需 @Autowired 注入使用\nxingtools.enabled.redisconfig-util=true\n# 使用jackson2序列化(默认，可以不用配置)\nxingtools.enabled.redisconfig-setting=jackson\n# 默认全局异常拦截\nxingtools.enabled.global-exception=true\n# mybatis-plus 分页插件 这个还是推荐自己注册Bean\nxingtools.enabled.mybatis-plus-config=true\n```\n\u003e 注意这些只是进行了简单的配置，也就是大多数人的需求，也暂时不用每次自行创建配置类等。\n\n\u003e 所有aop和配置都可以通过配置类或者自行bean导入，导入启动后，会有日志说明配置启动成功，也可以用xingtools.enabled.log-info=false把自动导入的日志关闭。**由于减少侵入和大小占用，有些相应的配置解释会提供工件名，请自行配置相关依赖。**\n\n- 4).也就是SpringSecurity,SpringCould的相关配置,可以通过配置@EnableXTCloudSecurity，@EnableXingToolsCloudServer，开启相关Security和Could的简化配置，精简你的项目。\n\n综上不管是简单作为工具包，或者简化你的SpringBoot,SpringCloud等项目，该Starter放到你的依赖里也是一种不错的选择。\n\n#### :pear:使用说明\n\n1.  静态工具类，new对象\n2.  @EnableXingToolsServer等注解启动装配，使用配置文件快捷开启对应配置\n\n\n\n如有bug，欢迎反馈。\n\n## :game_die:使用样例（xingtools v1.1.7 版本）\n\n本只做样例阐述，下面示例只是皮毛，更多更丰富的工具还在内部。\n\n由于下一节的 xingtool 有些使用样例过时或不推荐，现在更新使用样例，其他请优先阅读源码再参考文档。\n\n### 1. 数据封装类，Controller 层\n\n```java\n// controller 示例\n@RestController\n@RequestMapping(\"/common\")\npublic class CaptchaController {\n    /**\n     * 获取验证码（放行）\n     */\n    @Operation(operationId = \"getCaptchaInfo\") //open-api\n    @GetMapping(\"/captcha\") // 接口\n    public MyResult\u003c?\u003e getCaptchaInfo() {\n\n        HashMap\u003cString, String\u003e captcha = captchaService.getCaptcha();\n        \n        // 新版返回方式，可使用自定义返回类，更优雅\n        return ResultUtil.selectFill(captcha,\n                EnumResult.GET_SUCCESS,\n                EnumResult.GET_ERROR,\n                new MyResult\u003c\u003e());\n        \n        // 新版返回方式2\n        return ResultUtil.selectFill(captcha,\n                MyResult.fillBy(EnumResult.GET_SUCCESS),\n                EnumResult.GET_ERROR); // 返回自定义的MyResult对象\n        \n        // 也可以使用下面传统返回方式 (使用xingtools自带的 Result 及成功和失败策略)\n        return ResultUtil.selectResult(captcha); // 返回Result对象\n        \n\t\t// ResultUtil 工具类 默认策略(可以更改) 等同于下面 \n        return captcha == null || Boolean.FALSE.equals(captcha)  ? \n            \tMyResult.errorBy(EnumResult.GET_ERROR):\n                MyResult.successBy(EnumResult.GET_SUCCESS).setData(captcha);\n    }\n}\n```\n\n有人会说：我不想使用你的 Result 这个封装返回类，能不能自己定义。这是可以的，在1.0.3版本，统一了4个返回类，全部继承于CommonResult类，该类的基本属性如下：\n\n```java\npublic class CommonResult\u003cC, T\u003e implements IResultSource\u003cC, T\u003e {\n    protected C code;\n    protected String msg;\n    protected T data;\n}\n```\n\n它实现 IResultSource 接口，而我们可以直接实现 IResultSource 接口或者再往上仅实现 IResult 接口就行了。基本上工具包的很多方法参数都是 IResult 接口或者 IResultSource接口(比IResult多了set方法)。我们可以直接实现该接口像这样：\n\n```java\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\npublic class MyResult implements IResultSource\u003cInteger, Object\u003e {\n    protected Integer retCode; // 不想使用 code，想使用 retCode\n    protected String message; // 不想使用 msg，想使用 message\n    protected Object data;\n    \n    @Override\n    public Object getData() { // 使用原 getData 方法\n        return data;\n    }\n    @JsonIgnore // 屏蔽原方法，避免序列化\n    @Override\n    public Integer getCode() { \n        return retCode;\n    }\n    @JsonIgnore // 屏蔽原方法，避免序列化\n    @Override\n    public String getMsg() {\n        return message;\n    }\n}\n```\n\n对于不需要json转化的字段进行@JsonIgnore忽略掉就行。\n\n同理如果不需要data字段，再往上实现 IResultData 接口 (包含code和msg) 就可以，工具包里面的很多异常或者枚举都是实现了该接口, 因为基本上都需要 code 和 msg 两种属性。\n\n如果仅需要 msg 属性，仅需实现 IR 接口 ，需要 msg 和 code 需要实现 IResultData 接口，以此类推。\n\n### 2.工具类使用，例如锁，异步(多线程)\n\n锁提供基本的 LockHandler 类，以及下面的子类 XTLockHandler , XTExtLockHandler 等类。\n\n下面是 LockHandler 的基本使用。\n\n```java\n    @Test\n    void test11() {\n        XTLockMeta lockMeta = new XTLockMeta(XTLockType.ReentrantLock);\n        LockHandler lockHandler = new LockHandler(lockMeta);\n        lockHandler.init();\n        // Spring 的线程池\n        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();\n        executor.setCorePoolSize(5);\n        executor.setMaxPoolSize(10);\n        executor.initialize();\n\n\n        // Runnable 接口\n        XTAsync.runAsync(() -\u003e { // 继承 CompleteFuture 类，扩展了一些静态方法\n            lockHandler.lock(() -\u003e {// Callable 接口\n                for (int i = 0; i \u003c 20; i++) {\n                    XTJUC.sleepMillis(100); // 目前仅两个线程方法，睡100ms\n                    System.out.println(Thread.currentThread().getName() + \",\" + i);\n                }\n                return null; // 返回值\n            }, null);\n        }, executor);\n\n\n        XTAsync.runAsync(() -\u003e {\n            lockHandler.lock(() -\u003e {\n                for (int i = 0; i \u003c 20; i++) {\n                    XTJUC.sleepMillis(80);\n                    System.out.println(Thread.currentThread().getName() + \",\" + i);\n                }\n                return null;\n            }, null);\n\n        }, executor);\n\n        XTJUC.sleepMillis(100_000);\n    }\n```\n\n\n\n### 3.实体工具类使用，例如日志打印\n\n打印日志一般只需要 以下代码或者 lombok 的 @Slf4j 注解\n\n```java\nprivate static final Logger log = LoggerFactory.getLogger(XXX.class);\n```\n\n而提供的 ILogProvider 接口支持多个实现，例如log4j,log4j2,slf4j等，可以直接使用，但需要导入相应的依赖。\n\n提供的 ILogHandler 接口含义 send 方法，提供打印的动作，是为了方便适配自定义打印动作，提高灵活性。\n\n下面是直接使用方式\n\n```java\n    @Test\n    void test3() {\n        // LogHandler  使用 slf4j, info 模式打印\n        LogHandler logHandler = new LogHandler(new LogSlf4j(), LogLevel.INFO);\n        logHandler.send(\"hello world\");\n        // LogPkg.slf4j  打印\n        ILogHandler logHandler1 = LogPkg.SLF4J_PKG.getLogHandler();\n        logHandler1.send(LogLevel.ERROR, \"hello world23\");\n    }\n```\n\n一般情况下会使用打印策略配合使用，支持SpEL 表达式等更加高级的使用方式。\n\n示例如下, 打印的字符串会通过配置对 ${} 包裹的字符串进行替换。\n\n```java\n@Slf4j // 提供log\n@Configuration\npublic class WebLogHandlerConfig {\n\t/**\n     * 访问日志打印\n     */\n    public static final String ACCESS_LOG_KEY = \"当前用户 userId : ${userId}\" + LogKey.COMMAS\n            + LogKey.IP_STR + LogKey.COMMAS\n            + LogKey.HOST_IP + LogKey.COMMAS\n            + LogKey.URI + LogKey.COMMAS\n            + LogKey.HTTP_METHOD;\n\t@Bean\n    public WebLogConfig webLogConfig() { // config 配置\n        DefaultWebLogStrategy strategy = new DefaultWebLogStrategy(); // 默认策略(组装字符串)\n        WebLogConfig config = new WebLogConfig(strategy); // 设置策略\n        config.setLogProvider(new LogSlf4j(log)); //使用 slf4j, log\n        config.setLevelCode(LogLevel.INFO); // info 级别\n        config.setMsg(ACCESS_LOG_KEY); // 配置打印的字符串\n        return config;\n    }\n\n    public WebLogHandler newWebLogHandler(WebLogConfig webLogConfig) { // handler 处理器\n        WebLogHandler handler = new WebLogHandler(webLogConfig).initDefaultMap().modifyAll(); // 初始化变量值，可以在这里设置全局 map 映射\n        return handler;\n    }\n}\n```\n\n然后使用 WebLogHandler 对象 (该类继承 LogHandler，提供web方面的支持)\n\n```java\n    /**\n     * 访问日志打印\n     * \u003cp\u003e当前用户 userId : x \u003c/p\u003e\n     */\n    protected void accessLog(HttpServletRequest request, LoginUser loginUser, String ip) {\n        // 三位一体切面捆绑类，一般用于 aop 等切面类\n        AspectBundle aspectBundle = new AspectBundle( // web 捆绑类\n                null, // Method 类，目前不需要\n                HttpServletRequestData.of(request), // HttpServletRequest适配类,需要为其他默认 ACCESS_LOG_KEY 映射提供来源，如 LogKey.URI 等\n                null // ProceedingJoinPoint 类，切面对象，目前不需要\n        );\n        // 添加打印变量\n        HashMap\u003cString, String\u003e map = newWebLogHandler(webLogConfig).getMsgMap().getKeyMap();\n        // 这里开始可以加锁\n        // 存 userId\n        map.put(\"userId\", String.valueOf(loginUser.getUser().getId()));\n        // 存 ip\n        map.put(\"ip\", ip);\n\n        webLogHandler.send(aspectBundle); // 打印\n    }\n```\n\n如果有并发问题，请自行将设置值和打印值的部分加锁。\n\n### 4.系列注解使用，例如参数校验和异步线程\n\n#### ***参数校验** （必须导入 validation 包 并且参数添上@Valid或@Validated ）\n\n```java\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class MyUserQuery {\n\n    // 1.首先如果非空字符串和 null 均会进入下一步\n    // 2.必须匹配下面指定字符串\n    @StrStatus(anyStr = { // 必须匹配的字符串\n            \"1\", \"0\"\n    }, message = \"类型格式错误\",notBlankIfPresent = true) \n    private String type;\n\n    @StrStatus(anyReg = { // 正则匹配\n            RegexPool.MOBILE\n    }, message = \"手机格式错误\") // 验证\n    @StrJson(value = SensitiveSerializer.class, name = \"PHONE\") //脱敏\n    private String phone;\n\n    @NotBlank(message = \"邮箱不能为空\")\n    @Email(message = \"邮箱格式错误\") //validation包的校验\n    private String email;\n\n    @StrJson(value = SensitiveSerializer.class, name = \"\") // 返回值脱敏\n    private String password;\n    \n    /**\n     * 逻辑删除（1删除）\n     */\n    @ShortStatus(\n            matchNum = {\n                    EnumDelFlag.NOT_DELETED_CODE,\n                    EnumDelFlag.IS_DELETED_CODE\n            },\n            message = \"删除状态格式错误\"\n    )\n    private Short delFlag;\n}\n\n```\n\n#### 异步线程 \n\n1.可以使用**编程式**，例如 XTAsync, 或者你的类实现 ThreadHelper 接口或者  ThreadExecutorHelper 接口\n\n下面示例作为 异步配置，同时兼容ThreadPoolTaskExecutor, AsyncConfigurer(支持@Async 注解)和 ThreadHelper (CompletableFuture 编程式操作)\n\n```java\n@EnableAsync\n@Configuration\npublic class AsyncConfig implements AsyncConfigurer, ThreadHelper {\n\n    @Autowired\n    ThreadPoolTaskExecutor taskExecutor;\n\n    @Override\n    public Executor getAsyncExecutor() {\n        return taskExecutor;\n    }\n\n    @Override\n    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {\n        return null;\n    }\n\n    @Override\n    public Executor executor() {\n        return taskExecutor;\n    }\n}\n```\n\n注入该对象即可使用ThreadHelper里面的方法\n\n2.使用**声明式**，但不一定会得到预期结果\n\n一般情况下，只使用 XTAsync 静态方法类  (继承CompleteFuture类) 或者 XTCompletionService 对象 (继承ExecutorCompletionService) 即可\n\n下面是声明式异步编程，添加注解方式。\n\nTestThread 主线程类\n\n```java\n@Component\npublic class TestThread {\n    @Autowired\n    private ThreadResults threadResults; // 线程结果对象\n    @Autowired\n    private TestService testService;\n\n    // value 建议和调用的子线程方法数量一致 , 默认策略 GetResultAfterLastSon \n    @MainThread(value = 2, startTime = ThreadTimePolicy.GetResultAfterLastSon)\n    public void mainThread2() {\n        testService.sonThread1(); // 子线程1 ,需要被代理，注解才能生效\n        testService.sonThread2(); // 子线程2\n\n        List\u003cObject\u003e results = threadResults.getResults();\n        if (results != null) {//1. GetResultAfterLastSon 策略会在最后一个子线程阻塞等待 (所以上面的子线程数量必须一致) value数量的子线程执行完 , 所以该策略 results 始终会存在\n            XTArrayUtil.printlnList(results); // 数组\n        }\n\n        List\u003cFuture\u003cObject\u003e\u003e futures = threadResults.getFutures(); //2. GetFuture 策略，会在调用 getFutures 的 get处 阻塞，否则会在当前主方法执行完阻塞。所以这时候results会为空，所以需要调用 future 的 get方法 阻塞 等待完成。如果没有调用，则会在当前方法结束时阻塞。\n        XTArrayUtil.printlnList(futures);\n\n        futures.forEach(future -\u003e {\n            try {\n                System.out.println(future.get());\n            } catch (InterruptedException | ExecutionException e) {\n                e.printStackTrace();\n            }\n        });\n    }\n}\n```\n\nTestService 子线程类\n\n```java\n@Service\npublic class TestService {\n    @SonThread(threadPoolName = \"threadPoolExecutor\") // 指定 Spring容器 里面线程池名称\n    public String sonThread1() {\n        System.out.println(\"进入sonThread1\");\n        XTTime.sleepBySecond(3); \n        System.out.println(\"sonThread1 已经睡了3秒\");\n        return \"hello --\u003e sonThread1\";\n    }\n    @SonThread(threadPoolName = \"threadPoolExecutor\")\n    public void sonThread2() { // 无返回值\n        System.out.println(\"进入sonThread2\");\n        XTTime.sleepBySecond(1);\n        System.out.println(\"sonThread2 已经睡了1秒\");\n    }\n\n}\n```\n\n### 5.快速建造工具\n\n#### 1.HashMap扩展\n\n为 HashMap 添加值\n\n```java\nvoid test() {\n    HashMap\u003cString, Integer\u003e hashMap = new HashMap\u003c\u003e();\n\n    // 为 map 添加 key,value 对\n    int i = XTHashMap.putMapEntriesFromDValues(\n        hashMap,\n        \"hello\", 1,\n        \"world\", 2\n    );\n\n\n    System.out.println(hashMap); // {world=2, hello=1}\n\n\t// 为 map 的 list value 补充值, check 代表不存在就 new 一个ArrayList填充进去\n    HashMap\u003cString, List\u003cString\u003e\u003e hashMap1 = new HashMap\u003c\u003e();\n    XTMapUtil.checkAddAll(hashMap1, \"hello\", ArrayList::new,\n                          Arrays.asList(\"hello\", \"world\"));\n    XTMapUtil.checkAddAll(hashMap1, \"hello\", ArrayList::new,\n                          Arrays.asList(\"hello1\", \"world1\"));\n\n\n    System.out.println(hashMap1); // {hello=[hello, world, hello1, world1]}\n}\n```\n\n#### 2.Optional 功能扩展类 StreamChain\n\nStreamChain 包含 Optional 几乎所有方法，还对其进行了扩展\n\n```java\nvoid test() {\n    StreamChain\u003cInteger\u003e chain = StreamChain.ofNullable(null)\n        .directMap(v -\u003e v == null ? 2 : (int) v + 1);\n    System.out.println(chain); // StreamChain[2]\n\n    StreamChain\u003cInteger\u003e streamChain = new ObjectStreamChain(1)\n        .cast(Integer.class)\n        .flatMap(StreamChain::ofNullable)\n        .map(v -\u003e v + 1);\n    System.out.println(streamChain); // StreamChain[2]\n\n    ObjectStreamChain objectStreamChain = new ObjectStreamChain(2);\n    System.out.println(objectStreamChain);// StreamChain[2]\n\n    System.out.println(objectStreamChain.equals(streamChain)); // true\n\n    StreamChain\u003cInteger\u003e opt = StreamChain.ofNullable(1);\n    List\u003cInteger\u003e collect = opt.stream().collect(Collectors.toList());\n    Integer integer = opt\n        .flatMap(StreamChain::of)\n        .get();\n    System.out.println(integer); // 1\n    System.out.println(opt); // StreamChain[1]\n    System.out.println(collect); // [1]\n\n}\n```\n\n#### 3.高级建造类 BuilderMapChain\n\n生成一个建造树，如果当前层的值不存在，便可以从其他兄弟节点获取或生成，或者从父节点生成，直到得到值，返回。\n\n```java\nvoid test15() {\n    BuilderMapChain chain = new BuilderMapChain(3, null,  () -\u003e {\n        // 第1层\n        return \"第1层,\";\n    }).withGetter(null, o -\u003e {\n        // 第2层\n        String str = (String) o;\n        str += \"第2层,\";\n        return str;\n    }).withListGetter(null, Arrays.asList( // 第3层\n        (o) -\u003e { // 从上1层获取数据\n            String str = (String) o;\n            str += \"第3层-1,\";\n            return str;\n        },\n        (o) -\u003e { // 从上2层获取数据\n            String str = (String) o;\n            str += \"第3层-2,\";\n            return str;\n        }\n    ));\n    \n    // 下面三块是独立的，不在同一个方法内，因为创建便会填充数据（一次性对象）。\n    \n    Entry\u003cInteger, String\u003e entry = chain.createFrontDfs(3); // 前驱dfs创建3层\n    System.out.println(entry); // Entry [key=3, value=第1层,第2层,第3层-1,]\n    String s = chain.getValue(3); // 获取第3层数据\n    System.out.println(s); // 第1层,第2层,第3层-1,\n\n    Entry\u003cInteger, String\u003e entry2 = chain.createBackBfs(2); // 后驱bfs创建2层\n    System.out.println(entry2); // Entry [key=1, value=第1层,第2层,]\n    String s2 = chain.getValue(2); // 获取第2层数据\n    System.out.println(s2); // 第1层,第2层,\n    \n    Entry\u003cInteger, String\u003e entry3 = chain.createBackDfs(3); // 后驱dfs创建3层\n    System.out.println(entry3); // Entry [key=2, value=第1层,第3层-2,]\n    String s3 = chain.getValue(3); //获取第3层数据\n    System.out.println(s3); // 第1层,第3层-2,\n}\n```\n\n第3层数据不为null，则返回数据。\n\n第3层数据为null，便从第3层 front（List 从前往后，前驱），back（List 从后往前，后驱）获取生成方法（用于生成该层数据，填充到该层），dfs （依次获取上层数据，直至能填充目标层数据）, bfs （先把该层List遍历完成，还没有填充数据才从上层获取）\n\n**那么有什么用呢？**\n\n示例如下：\n\n```java\nvoid test{\n    ...\n    ApplicationContext applicationContext = SpringUtils.getApplicationContext(); // Spring 上下文\n    // 创建3层建造树\n    BuilderMapChain chain = new BuilderMapChain(3, applicationContext) \n        .with(redisTemplate, o -\u003e { // redisTemplate 数据\n            ApplicationContext ac = (ApplicationContext) o;\n            return ac.getBean(RedisTemplate.class); // redisTemplate 数据不存在则从容器获取\n        }).withList(redisCache, Arrays.asList(\n        o -\u003e {\n            RedisTemplate\u003cString, Object\u003e rt = (RedisTemplate\u003cString, Object\u003e) o;\n            return new RYRedisCache(rt); // 填充进 RYRedisCache\n        },\n        o -\u003e {\n            ApplicationContext ac = (ApplicationContext) o;\n            return ac.getBean(RYRedisCache.class); // RYRedisCache 数据不存在则从容器获取\n        }\n    ));\n    \n    // 得到生成的值\n    RYRedisCache redisCache = chain.createFrontDfs(3).getValue(3);\n}\n```\n\n里面有许许多多快速开发的工具，还请多多研究。\n\n### 6.*系列算法\n\n算法都放在  top.cutexingluo.tools.utils.se.algo.cpp 包下，顾名思义，工具/SE/算法/C++，\n\n例如二分查找\n\n```java\nint index = XTBinarySearch.lowerBound(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5);\n// c++ std::lower_bound 找到大于或等于目标的数据的位置, index = 4\n```\n\n例如字符串算法，在字符串里面查找子串，原生java是一个个匹配，遇到多重复字符速度变慢。\n\n这里有KMP算法\n\n```java\nint index = XTStringAlgo.find(\"abcabcabc...abcdabcabcabc\", \"abcd\");// 查找重复字符串\n```\n\n例如数据结构，简易线段树，线段树，动态线段树，平衡二叉树，树状数组，字典树，Splay树，Treap树，B 树，B+ 树的基础实现，可供参考\n\n```java\nBTree\u003cString, String\u003e tree = new BTree\u003c\u003e(3); // B树\nBPlusTree\u003cString, String\u003e tree = new BPlusTree\u003c\u003e(3); // B+树\ntree.put(\"1\", \"1\");\ntree.put(\"4\", \"4\");\ntree.put(\"2\", \"2\");\n// 实现 NavigableMap 接口，兼容基本操作\n```\n\n例如数学\n\n```java\nPoint a = new Point(1.0,1.0);\nPoint b = new Point(1.0,2.0);\ndouble dis = a.distance(b); // 两点距离\nPoint middle = a.middle(b); // 两点中点\n```\n\n例如图论，Dijkstra 最短路，最小生成树，网络流等\n\n例如状态机（类似 map）\n\n```java\nNodeStateMachine\u003cInteger, StatusNode\u003cEnumPay, EnumPay\u003e\u003e stateMachine = new NodeStateMachine\u003c\u003e();\nstateMachine.put(EnumPay.ALIPAY.getCode(),\n        new StatusNode\u003c\u003e(EnumPay.ALIPAY,\n                Arrays.asList(\n                        EnumPay.ALIPAY,\n                        EnumPay.WECHAT,\n                        EnumPay.UNIONPAY\n                )\n        ));\nstateMachine.put(EnumPay.WECHAT.getCode(),\n        new StatusNode\u003c\u003e(EnumPay.WECHAT,\n                Arrays.asList(\n                        EnumPay.WECHAT,\n                        EnumPay.UNIONPAY\n                )\n        ));\nboolean accept = stateMachine.canAcceptNode(EnumPay.ALIPAY.getCode(), EnumPay.ALIPAY.getCode());\nSystem.out.println(accept); // true\n\nboolean accept1 = stateMachine.canAcceptNode(EnumPay.ALIPAY.getCode(), EnumPay.WECHAT.getCode());\nSystem.out.println(accept1); // true\n\nboolean accept2 = stateMachine.canAcceptNode(EnumPay.ALIPAY.getCode(), EnumPay.UNIONPAY.getCode());\nSystem.out.println(accept2); // false\n\nboolean accept3 = stateMachine.canAcceptNode(EnumPay.ALIPAY.getCode(), EnumPay.CASH.getCode());\nSystem.out.println(accept3); // false\n\nStatusNode\u003cEnumPay, EnumPay\u003e node = stateMachine.get(EnumPay.ALIPAY.getCode());\nSystem.out.println(node); // StatusNode(node=ALIPAY, nextNodes=[ALIPAY, WECHAT, UNIONPAY])\nboolean contains = node.getChildren().contains(EnumPay.ALIPAY);\nSystem.out.println(contains); // true\n```\n\n\n\n未完待续...\n\n具体内容详见源码和使用文档。\n\n其他丰富的 工具，算法，注解， 自动配置 等均可在源码注释上看到使用说明，多查看源码。\n\n\n\n\n\n## :game_die:使用样例（xingtool v1.0.5 版本）(老版本)\n\n以下xingtool v1.0.5版本的使用样例，可以加快你的开发\n\n##### 1. 数据封装类，Controller 层\n\n```java\n@RestController\n@RequestMapping(\"/admin\")\npublic class AdminController {\n    \n    @RequestLimit // 限流注解\n    @WebLog(match = \"ip:uri:method+s+tab+ip\", levelStr = \"info\", referer = \"log1\") // 打印日志注解\n    @GetMapping(\"/user/getAll\")\n    public Result getAll() { // Result 对象 推荐使用\n        //ResultUtil.selectResult 动态解析返回值 (false和null得到获取失败) 也可以直接使用 Result.success()\n        return ResultUtil.selectResult(adminService.getAll(),\"获取成功\",\"获取失败\"); \n    }\n    \n    // 这个注解是打印日志，其中一个策略是可以使用spEL表达式执行任意方法\n    @WebLog(spEL = \" @testService.hello ( #msgMap, #bundle ,'hello world') \") \n    @GetMapping(\"/user/getOne\")\n    public R\u003cUserInfo\u003e getOne() { // R对象 alias MSResult 支持泛型\n        //ResultUtil.selectResult 动态解析返回值 (false和null得到获取失败) 也可以直接使用 Result.success()\n        return ResultUtil.selectR(adminService.getOne(),\"获取成功\",\"获取失败\"); \n    }\n}\n```\n\n有人会说：我不想使用你的 Result 这个封装返回类，能不能自己定义。这是可以的，在1.0.3版本，统一了4个返回类，全部继承于CommonResult类，该类的基本属性如下：\n\n```java\npublic class CommonResult\u003cC, T\u003e implements IResultSource\u003cC, T\u003e {\n    protected C code;\n    protected String msg;\n    protected T data;\n}\n```\n\n它实现 IResultSource 接口，而我们可以直接实现IResultSource或者再往上仅实现 IResult 接口就行了。基本上工具包的很多方法参数都是IResult 接口。我们可以直接实现该接口像这样：\n\n```java\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\npublic class MyResult implements IResult\u003cString,Object\u003e {\n    protected String retCode; // 不想使用 code，想使用 retCode\n    protected String message; // 不想使用 msg，想使用 message\n    protected Object data;\n    \n    @Override\n    public Object getData() {\n        return data;\n    }\n    @JsonIgnore\n    @Override\n    public String getCode() {\n        return retCode;\n    }\n    @JsonIgnore\n    @Override\n    public String getMsg() {\n        return message;\n    }\n}\n```\n\n对于不需要json转化的字段进行@JsonIgnore忽略掉就行。\n\n同理如果不需要data字段，再往上实现 IResultData 接口(包含code和msg) 就可以，工具包里面的很多异常或者枚举都是实现了该接口。\n\n\n\n##### 2.工具类使用，拦截器 以 OAuth2 为例（springboot2.x版本）\n\n```java\n@Component\npublic class MyTokenFilter extends OncePerRequestFilter {\n\n\n    @Autowired\n    private TokenStore tokenStore;\n\n    // jwt解析类\n    @Autowired\n    private MyUserAuthenticationConverter myUserAuthenticationConverter;\n\n    RYRedisCache redisCache;\n\n    // 构造注入\n    @Autowired\n    public MyTokenFilter(RYRedisCache redisCache, ApplicationContext applicationContext) {\n        this.redisCache = redisCache;\n        AccessLimitUtil.setRedisCache(redisCache);\n        AccessLimitUtil.setApplicationContext(applicationContext);\n    }\n\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {\n\n        try {\n            // AccessLimitUtil 工具类 ， 可以利用 Redis 进行限流\n            // limitFilter 解析方法上的注解\n            boolean check1 = AccessLimitUtil.limitFilter(request, response, filterChain);\n            if (!check1) return;\n            // limitFilter IP 拦截\n            boolean check2 = AccessLimitUtil.limitIP(request, response, 1, 20,\n                    \"访问过于频繁，请稍后访问\");\n            if (!check2) return;\n        } catch (Exception e) {\n            XTResponseUtil.forbidden(response, e.getMessage()); // 返回 403\n            return;\n        }\n\n        Authentication authentication;\n        try {\n            // XTAuthenticationUtil 执行链操作，对token进行解析\n            authentication = new XTAuthenticationUtil \n                    .AuthenticationBuilder(request, XTAuthenticationUtil.USE_HEADERS | XTAuthenticationUtil.USE_COOKIES) // headers 和 cookies 都要解析\n                    .setTokenExtractor(tokenExtractor)\n                    .setTokenStore(tokenStore)\n                    .setAccessTokenConsumer(accessToken -\u003e {\n                        //XTAccessTokenUtil 对Oauth2 包的 AccessToken类进行解析\n                        if (XTAccessTokenUtil.isExpired(accessToken)) { \n                            throw new AuthenticationServiceException(\"Token String 已经过期！\");\n                        }\n}).setAccessTokenAdditionalConverter(myUserAuthenticationConverter::extractAuthentication)\n                    .repairCreate(\"\").build(); // 对 Authorization 头 进行解析\n        } catch (AuthenticationServiceException e) {\n            XTResponseUtil.unauthorized(response, e.getMessage());// 401 返回\n            return;\n        }\n        if (authentication != null) { // 解析到token，设置上下文\n            SecurityContext context = SecurityContextHolder.getContext();\n            context.setAuthentication(authentication);\n        }\n        // 如果没有解析到，authentication会为空，然后交给资源服务判定\n\n        filterChain.doFilter(request, response); \n    }\n}\n\n```\n\n\n\n##### 3.系列注解使用，例如参数校验和异步线程\n\n###### **参数校验** （必须导入 validation 包 并且参数添上@Valid或@Validated ）\n\n```java\n@Data\n@AllArgsConstructor\n@NoArgsConstructor\npublic class MyUserQuery {\n\n    // 1.首先如果非空字符串和 null 均会进入下一步\n    // 2.必须匹配下面指定字符串\n    @StrStatus(anyStr = { // 必须匹配的字符串\n            \"1\", \"0\"\n    }, message = \"类型格式错误\",notBlankIfPresent = true) \n    private String type;\n\n    @StrStatus(anyReg = { // 正则匹配\n            RegexPool.MOBILE\n    }, message = \"手机格式错误\") // 验证\n    @StrJson(value = SensitiveSerializer.class, name = \"PHONE\") //脱敏\n    private String phone;\n\n    @NotBlank(message = \"邮箱不能为空\")\n    @Email(message = \"邮箱格式错误\") //validation包的校验\n    private String email;\n\n    @StrJson(value = SensitiveSerializer.class, name = \"\") // 返回值脱敏\n    private String password;\n}\n\n```\n\n###### 异步线程 \n\n1.可以使用**编程式**，例如 XTAsync, 或者你的类实现 ThreadHelper接口\n\n2.使用**声明式**，但不一定会得到预期结果\n\nTestThread 主线程类\n\n```java\n@Component\npublic class TestThread {\n    @Autowired\n    private ThreadResults threadResults; // 线程结果对象\n    @Autowired\n    private TestService testService;\n\n    // value 建议和调用的子线程方法数量一致 , 默认策略 GetResultAfterLastSon \n    @MainThread(value = 2, startTime = ThreadTimePolicy.GetResultAfterLastSon)\n    public void mainThread2() {\n        testService.sonThread1(); // 子线程1 ,需要被代理，注解才能生效\n        testService.sonThread2(); // 子线程2\n\n        List\u003cObject\u003e results = threadResults.getResults();\n        if (results != null) {// GetResultAfterLastSon 策略会阻塞等待 value数量的子线程执行完 , 所以该策略 results 始终会存在\n            XTArrayUtil.printlnList(results); // 数组\n        }\n\n        List\u003cFuture\u003cObject\u003e\u003e futures = threadResults.getFutures(); // GetFuture 策略会阻塞在当前主方法执行完，所以这时候results会为空，所以需要调用 future 的 get方法 阻塞 等待完成。如果没有调用，则会在当前方法结束时阻塞。\n        XTArrayUtil.printlnList(futures);\n\n        futures.forEach(future -\u003e {\n            try {\n                System.out.println(future.get());\n            } catch (InterruptedException | ExecutionException e) {\n                e.printStackTrace();\n            }\n        });\n    }\n}\n```\n\nTestService 子线程类\n\n```java\n@Service\npublic class TestService {\n    @SonThread(threadPoolName = \"threadPoolExecutor\") // 指定 Spring容器 里面线程池名称\n    public String sonThread1() {\n        System.out.println(\"进入sonThread1\");\n        XTTime.sleepBySecond(3); \n        System.out.println(\"sonThread1 已经睡了3秒\");\n        return \"hello --\u003e sonThread1\";\n    }\n    @SonThread(threadPoolName = \"threadPoolExecutor\")\n    public void sonThread2() { // 无返回值\n        System.out.println(\"进入sonThread2\");\n        XTTime.sleepBySecond(1);\n        System.out.println(\"sonThread2 已经睡了1秒\");\n    }\n\n}\n```\n\n\n\n未完待续...\n\n具体内容详见使用文档。\n\n##  :memo:更新公告\n\n**2025-7-26  v1.1.7 (推荐)**\n\n```txt\n版本更新说明\n当前版本逐渐趋于稳定，新增和改动内容少，逐渐可放心使用。\n\n更改部分\n1.移除 JavaVersion.EIGHT 防止报错\n2.状态节点 StatusNode 面向接口 Collection\n3.XTDateUtil 更新\n4.JacksonSerializer bug 修正\n\n新增部分\n1.新增 EmptyChecker 等系列接口\n2.新增 IPageDetail 接口，及其系列实现接口\n3.新增链式调用接口 TaskChain, TaskNode 及实现类\n4.新增 IValueSource 接口, 拥有setValue方法\n```\n\n**2024-11-22  v1.1.6**\n\n```txt\n版本更新说明\n当前版本新增和修改了很多东西。比如对 Map.Entry 及各种 Node 节点类的支持，并新增 B树 和 B+ 树作为数据结构，增强了工具包的可用性。本次也对编码哈希加密等算法进行了重构，开始了面向接口使用，更加方便管理多种算法。相应的迭代器，比较器都进行了增强。二分查找也单独提取出来。重要的是现在能够同时支持 spring-cloud-starter-security, spring-cloud-starter-oauth2, spring-security-oauth2-authorization-server 三种框架的组合和兼容。\n\n更改部分\n1.*重构迭代器，比较器，使之更通用，更健壮\n2.提取 XTMath 的二分查找 为 XTBinarySearch, 支持多种二分查找，类似 c++ lower_bound, upper_bound\n\n新增部分\n1.XTCallable 新增 getInCatchRet 更加健全\n2.*继承重构1.0.5 版本的 XTEncryptUtil 加密工具类，支持Md5,SHA256,DES,AES,RSA 算法\n3.新增IdNode接口 (含 getId 方法),新增DataNode作为IDataValue 默认实现类\n4.新增编码/哈希/加密算法接口和多个实现类，CryptHandler 是所有算法的基类\n5.新增 ECC 加密，XTEncryptUtil 改名为 XTCryptUtil , 使综合工具更明确\n6.* 新增 BTree (B 树) 和 BPlusTree (B+ 树) 数据结构，支持插入，删除，查找，遍历等操作，使用新的迭代器速度更快\n7.新增 MapEntry 实体类兼容 Map.Entry 接口和其他实体类\n8.*新增对 spring-security-oauth2-authorization-server 的 OAuth2 的管理接口，以及各种实现类，后续也会持续跟进更新\n```\n\n**2024-9-29  v1.1.5**\n\n```txt\n版本更新说明\n当前版本主要是为了灵活性扩展，更改了 返回数据实体类及工具类的实现，也更改了 XTCallable 和新增 XTSupplier ，来解决令人头疼的 Supplier和Callable两个接口的统一问题。\n\n更改部分\n1.* 重构 IResult 实现类四大类，更改里面的所有 success 和 error 的默认值,  true 和 false 统一改为 null , 不带值\n2.* 重构 ResultUtil 的 大部分方法，为适应不同情况，可以自定义策略等\n3.* 更改并提取 XTCallable 使其更通用，更健壮。并更改部分方法名，并应用其他例如 XTAsync 实现更改。\n4.大部分类将升级 e.printStackTrace() 这种异常输出形式, 大部分类将引入 异常处理消费者，来控制开关，未来将系统处理异常或改为抛出\n\n新增部分\n1.新增 XTSupplier 作为 XTCallable 的补充，使其更灵活，扩展性好。从XTCallable 提出公共静态方法 XTAround , 很多方法优先使用该类\n2.新增接口 IName, IRName ,提供getName 方法, 并使Constants 和 HttpStatus 实现该接口, IResult 四大实现类支持配置msg默认英文名name\n```\n\n**2024-9-14  v1.1.4**\n\n```txt\n更改部分\n1.恢复 mybatis-plus 插件自动配置, 默认关闭 xt-lock-aop\n2.日志包ILogProvider从静态改为面向对象\n3.WebHandler 接口 参数 HttpServletRequestAdapter 变更为 HttpServletRequestDataAdapter\n4.*为适应不同需求，ResultUtil新增select方法返回封装对象\n5.*对锁的类进行解耦操作, 修改LockHandler, XTLockHandler 等类, 修改LockHelper接口, LockHandler 移植到 core 包\n6.针对 Redis 的 AccessLimitUtil 工具类进行更改, 将使用 LimitStrategy 策略; 更改 RedisLimitStrategy 可保证原子性\n7.对 RequestLimit 系列部分方法进行了修改, 新增 XTRedisScript 组合获取lua限流脚本\n\n新增部分\n1.新增多个节点接口，节点状态机 NodeStateMachine ，适配于无边权无事件情况\n2.新增Entry类代替hutool的Pair类，更改新增Entry, Pair, TupleEntry, TuplePair 等适应不同情况的二元组, 部分类开始继承Entry而不是hutool的Pair\n3.*新增链式接口，过滤器链接口及其实现类，核心类为 FilterChain (CompositeFilterChainFactory) , StreamChain , BuilderChain , BuilderMapChain可分别模拟过滤器链Filter, 流式Stream的调用方式 和 建造者链, 建造者扩展链, 加快开发\n4.*新添 ModuleAdapter 及其实现类，针对 JacksonSerializer 进行了增强，支持更多类似 FastJson 功能，并提供配置全局序列化器，RYRedisCache 支持从容器获取序列化器，容器bean名称分别为 jacksonSerializer 和 redisJacksonSerializer\n```\n\n**2024-8-12  v1.1.3**\n\n```txt\nbug 修复\n1.由于源码包只识别签名，所以在支持 jdk17 的众多方法会抛出 NoSuchMethodError 错误，故 jdk17 版本不推荐使用 v1.1.2 版本，现对该版本进行紧急修复。\n\n更改部分\n1.部分方法参数从 HttpServletRequestData 实体类更改为 HttpServletRequestAdapter接口\n\n新增部分\n1.新增HttpServletRequestAdapter和 HttpServletResponseAdapter 针对 HttpServlet 系列的适配方法，并替换之前的长链调用，以便通过对包的支持来达到对jdk支持的目的。\n2.新增 HttpServletRequestDataAdapter 和 HttpServletResponseDataAdapter 作为上面两个接口的实现，通过导入不同 jdk 包或者自行实现的方式 满足工具方法的需求。\n```\n\n**2024-8-8  v1.1.2**\n\n```txt\n版本使用攻略：jdk17 禁止使用含 HttpServletRequest 参数的大部分方法。该版本不推荐使用，请移步下一版本。\n\nbug 修复\n1.由于未导入 spring-boot-starter-aop ，故启用 @EnableXingToolsServer 时使用 某个 aop 报错，目前将所有 aop 关闭；现在不使用 aop 不导入 aop 包，依旧能运行服务。\n在v1.1.1版本需要配置  xingtools.ext-transaction-anno.enabled=false # v1.1.1 版本需要关闭。\n2.修复 IntStatus 等参数校验注解未初始化的问题，以及数字匹配 matchNum 绝对匹配放行的问题。\n\n更改部分\n1.将 pkg-jdk8 和 pkg-jdk17 部分代码移除或移出到mvc包和cloud等其他包下，只做javax 和 jakarta 包的兼容，该包只依赖 core包。依赖关系更新。\n2.cloud包将支持 cloud 和 security 两种模块，可以根据需要按需导入模块。\n\n新增部分\n1.cloud 包新增对 spring-security , spring-security-oauth2 和 spring-authorization-server 等不同依赖的支持。并提取两个依赖中的公共元素合并作为新的类集合。\n例如：AuthToken, AuthAccessToken, AuthTokenExtractor, AuthTokenGenerator 等作为新的框架，和新的 XTAuthenticationBuilder 工具建造类对授权执行链的支持。\n2.新增 HttpStatus 作为 Constants 的另一种实现形式。并对 Result 等一系列返回封装类添加对应方法。\n3.新增系列集合类对 short 和 float 的支持，并新增 @ShortStatus 和 @FloatStatus 等参数校验注解。\n```\n\n**2024-7-17  v1.1.1**\n\n```txt\n版本使用攻略：如果没有导入spring-boot-starter-aop包并且开启@EnableXingToolsServer，需要配置文件配置 xingtools.ext-transaction-anno.enabled=false\n\n中版本更新，为了保证灵活性。更改工具名 xingtool -\u003e xingtools 。\n更改部分\n1.分离为多个包，例如分离core 包和 log 大包，保证 log 大包能够使用\n2.部分强耦合方法被移除，例如移出 XTArrayUtil 的 logPrintln 等方法\n3.更改大部分包名，例如 designtools.http 包名-\u003e designtools.convert\n4.部分类按包名合并，例如 designtools.distributed 合并到 utils.ee 里面\n5.部分类消失简化操作等，例如Security Oauth的装配\n\n移除部分\n1.多个历史遗留类移除，例如移除类XTDataType\n2.很多业务类和重复工具类移除，例如暂时移除 ruoyi 和 ican 的多个类，后续会合并到大工具类。如果已经使用了这些类的方法，请留级到 xingtool的 v1.0.5 版本\n3.移除其他暂时不需要的类和冗余类，例如kotlin依赖等\n\n支持 jdk8, jdk17 双版本\n(为保证移植性，javax包减少使用，无法去掉则移植到 pkg-jdk8 包)\n大包分为许多小包，可以按需依赖。\n后续版本将 pkg 包降低其对 其他包依赖性，提高扩展性。\n```\n\n**2024-7-7  v1.0.5**\n\n```txt\n更改部分\n1.允许 OptData 直接接受 null 值\n2. RedisLockUtil 更改包名为 redis\n\n新增部分\n1.添加 Method Proxy 系列方法\n2.新增 Serializer 序列化接口，及其子类 多种序列化类\n3.新增 model 包，模型含有状态机等多种结构\n4.扩展 OptBundle 系列方法\n\n支持部分 SpringBoot3\n新增使用文档\n```\n\n**2024-3-27  v1.0.4**\n\n```\nbug修复\n1.紧急修复 XTCallable 的 getSupplier 和 canRunTask 问题，并修复逻辑。\n2.紧急修复 XTStrUtil findFirstOf错误调用自身的问题。 1.0.2-1.0.3 两个版本不要使用该方法。\n3.修复单 pick 问题, 解决并发注解 @MainThread @SonThread 事务问题, 修复 TreeUtil 树转列表的问题\n4.修复 ResultUtil 对 R类 的支持问题\n\n更改部分\n1.修改 @MainThread 默认时间策略为  GetResultAfterLastSon, 和原来没有什么差别。\n2.修改了 XTMethodUtil 类方法名称 isAnnotationPresent =\u003e isHandlerMethodAnnotationPresent。\n3.修改所有限流注解/工具的位置。\n4.修改 XTLog 实现, 以及新增一系列 web 的 key 接口 和日志接口。\n5.修改XTThreadPool、ThreadData默认核心线程，并修改ThreadHelper 命名防止冲突。\n\n新增部分\n1.新增 @StrJson 注解 返回数据时返回指定json字符串，并新增 StrJsonStrategy 接口的实现类 SensitiveSerializer 类用于敏感字符串脱敏，可自行实现StrJsonStrategy接口。\n2.新增 SocketServer 和 SocketClient 等类 和 XTCollUtil 集合工具类。\n3.新增 @RequestLimit 限流注解 和 RequestLimitHandler 工具类，可以取代 @Limit 和 @AccessLimit 注解,  提供了两个策略，可自定义策略，使用灵活。\n4.新增 @WebLog注解 和 WebHandler 工具类，用于自定义策略日志打印，可以取代 @MethodLog 和 @XTSystemLog , 匹配, 模式串用法更灵活。\n5.新增 OptBundle 类 用于执行链操作 , 和 OptionalResult 用于扩展 Optional 类。\n6.新增 kotlin 依赖 临时支持 kotlin 。\n```\n\n**2023-12-25 v1.0.3**\n\n```txt\n版本使用攻略：禁止使用 XTStrUtil.findFirstOf，XTCallable的 getSupplier 和 canRunTask，TreeUtil.flatListBfs 等所有树转列表方法\n\nbug修复\n1. 修复了 AccessLimitUtil.limitIP 加载 Ipdb 错误 的bug\n\n更改部分\n1. 修改了XTCompletionService实现，以及ThreadLocalHelper文件位置\n2. 所有web 拦截类 从 Result 改为返回 IResult 接口，并且添加 GlobalResultFactory 接口用于全局返回结果，使用时需要注册到容器。\n\n新增部分\n1. 新增top.cutexingluo.tools.utils.se.algo.cpp包，里面包含各种算法（有些未测试），例如数论，几何，数据结构，图论，字符串等\n2. 新增 BoolUtil  用于使 java 适配 c++性质。\n3. 新增XTArrayUtil一些方法，用于移动数组元素，新增 XTSetUtil 的 Set 工具类。\n4. 新增ClassMaker类，用于转化和反射，可以配合XTObjUtil。\n5. 增加了 CommonResult 类，用于返回通用结果, 四大返回类重新继承了该类。\n6. 新增红黑树 RBTree，迭代器默认中序遍历，即默认升序排序。属性全为protected，方便子类继承。常规推荐使用 TreeMap\n7. 新增各种迭代器用于适配多种情况。可自行继承使用。\n8. 新增启用 server 的 banner 和 cloud server 的 banner\n```\n\n**2023-10-21 v1.0.2**\n\n```txt\n版本使用攻略：禁止使用XTStrUtil.findFirstOf，AccessLimitUtil.limitIP\n\n1. 添加了 Supplier 接口,。与之对应各种适配类的调整。\n2. 添加多线程注解AOP @MainThread @SonThread\n3. 调整 XTAsync 类 , 并且添加 ThreadHelper接口，更快速使用。\n4. 添加 XTString 工具类，可以通过 C++ 方法名称的方式使用。\n5. 重构代码（位置和代码）。以下为 v1.0.2 重构更新日志：\n\n1.移除 XTExceptionAop 两个静态方法\n2.添加 BaseAspectAroundHandler 接口默认方法\n3.规范类的命名，例如ThreadLocal的工具类，规范了各工具类的用法注释\n4.更改了 XTCallable 和 XTRunnable 的部分方法，添加 TryCatchHelper 等helper接口，方便直接使用工具类。例如 LockHelper, ThreadHelper 等\n5.更改 XTProxy 的实现\n6.更改了 XTResponseUtil 的参数, 使之更通用\n7.新增 TreeUtil  树转列表\n8.更改 LogInfo 类 转为 LogInfoDisable 类\n9.为 RedisConfig , SpringSecurity Oauth2 添加用法注释\n10.XTCallOtherUtil 更名为 XTCodeInteropUtil，关于生成其他语言代码的工具类\n11.添加RabbitMQ系列初始工具类, 以及用法Test类, 可以不使用，没有太多优化的地方。\n```\n**2023-9-26 v1.0.1**\n正式版发布，中央仓库 ,  依赖最低版本不能低于 v1.0.1\n\n```txt\n1. 含有基础日志、事务、线程、异常等AOP，需要通过配置文件开启。\n2. 包含基础包 Callable , Runnable 等系列封装的函数式接口及其实现类，如 XTRunCallUtil 工具类。\n3. 含有系列注解，如 StrStatus,  IntStatus 等注解，可以对类属性进行验证。\n4. 含有MVC 封装返回值的封装接口及其四个实现类，可以应对任何 code , msg , data 三件套的情况。\n5. 含有传统设计方法封装工具类，包含 XTBuilder, 反射, 多线程, 锁等工具类。\n6. 含有拦截器封装的工具类，例如 Oauth2 Authentication 的过滤 ，IP 限流 等工具类。\n7. 支持 SpringCloud Oauth2 的简化配置，例如 @EnableXTCloudSecurity 开启 JWT 自动导入Bean。\n8. 含有各配置的开启，例如 MybatisPlus 分页插件和 Redis 的配置 及其 四个以上的Redis工具类和其他工具类。\n9. 对RuoYi、ican工具类的大部分支持，对 hutool 工具包默认导入以及扩展。\n10. 对一些其他语言的扩展工具类支持，例如 JS 系列的方法名称,, 以及其他语言的操作，生成。\n11. 对加密解密的各种封装，以及对token解析的封装，但还是建议使用 hutool工具。\n12. 对许多工具类的扩展，包含字符，文件，IO，map等，以及各种基本类的对应工具类。\n```\n\n在 properties/yml 配置文件输入 xingtools 即可查看相关自动配置。\n\n在最新版本中，使用 @EnableXingToolsServer 开启自动配置后，仅开启 配置开启日志和SpringUtils 注册，其他均默认关闭。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcutexingluo%2Fxingtools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcutexingluo%2Fxingtools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcutexingluo%2Fxingtools/lists"}