{"id":37030330,"url":"https://github.com/cheny2151/toolbox","last_synced_at":"2026-01-14T03:41:45.929Z","repository":{"id":37114559,"uuid":"265739318","full_name":"cheny2151/toolbox","owner":"cheny2151","description":"somethings stable tool","archived":false,"fork":false,"pushed_at":"2024-08-26T10:12:19.000Z","size":680,"stargazers_count":5,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-13T11:03:13.828Z","etag":null,"topics":["cluster-tasks","expression-parser","lock","redis","toolbox"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cheny2151.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2020-05-21T02:51:30.000Z","updated_at":"2024-02-29T04:54:35.000Z","dependencies_parsed_at":"2024-03-08T07:30:56.703Z","dependency_job_id":"51a11777-caf3-4e57-a8e1-8e34adb80b94","html_url":"https://github.com/cheny2151/toolbox","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/cheny2151/toolbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheny2151%2Ftoolbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheny2151%2Ftoolbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheny2151%2Ftoolbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheny2151%2Ftoolbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cheny2151","download_url":"https://codeload.github.com/cheny2151/toolbox/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheny2151%2Ftoolbox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408856,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cluster-tasks","expression-parser","lock","redis","toolbox"],"created_at":"2026-01-14T03:41:45.312Z","updated_at":"2026-01-14T03:41:45.916Z","avatar_url":"https://github.com/cheny2151.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"TOOLBOX\n===========================\n提供常用工具类,redis分布式锁，redis分布式任务发布订阅，注解实体缓存，表达式解析器，poi工具类封装，反射工具，包扫描器，多线程任务等。并且在Spring boot环境下，自动配置。\n\n****\n## 目录\n* [redis 分布式锁](#Redis分布式锁)\n    * [锁实现类](#锁实现类)\n    * [Spring环境下用例](#分布式锁Spring环境下用例)\n    * [非Spring环境下用例（jedis）](#分布式锁非Spring环境下用例（jedis）)\n* [redis分布式任务发布订阅](#Redis分布式集群任务)\n    * [Spring环境下用例](#集群任务Spring环境下用例)\n    * [非Spring环境下用例（jedis）](#集群任务非Spring环境下用例（jedis）)\n* 注解实体缓存\n    * mybatis环境下使用\n    * ...\n* 表达式解析器\n    * 导入静态方法\n    * 测试表达式\n    * 用例\n-----------\n\nRedis分布式锁\n-----------\n### 锁实现类\n1. 可重入锁 -- ReentrantRedisLock\u003cbr/\u003e\n    特点：可重入\n2. 多路径锁 -- MultiPathRedisLock\u003cbr/\u003e\n    特点：一次性可对多个path上锁，只要有一个path被其他线程持有，则获取锁失败\n3. 二级锁 -- SecondLevelRedisLock\u003cbr/\u003e\n    特点：一级锁被占用，则任务二级锁获取失败；二级锁被占用，则一级锁获取失败，但不会阻塞其他线程获取其他二级锁。\n\n### 分布式锁Spring环境下用例\nSpring环境静下，无需其他配置，自动整合spring-boot-starter-data-redis，通过redisTemplate的api实现redis操作。\n```Java\ntry (RedisLock redisLock = new ReentrantRedisLock(\"test\")) {\n    if (redisLock.tryLock(1000, 1000, TimeUnit.MILLISECONDS)) {\n        System.out.println(\"获取锁成功\");\n    }\n} catch (Exception e) {\n    e.printStackTrace();\n}\n```\n注意：\nRedisLock继承了AutoCloseable，在try中创建实例会自动调用Close释放锁。\n\n### 分布式锁非Spring环境下用例（jedis）\n非Spring环境下，需要配置jedis工厂、将JedisManagerFactory实例配置到RedisConfiguration中即可使用。\n```Java\n// 配置jedis工厂\nJedisClientFactory factory = new JedisClientFactory(\"localhost\", null, null, null);\n// 从工厂中获取jedisClient\nJedisClient jedisClient = factory.cacheClient();\nJedisManagerFactory jedisLockFactory = new JedisManagerFactory(jedisClient);\n// 设置全局redis manager为jedis实现类\nRedisConfiguration.setDefaultRedisManagerFactory(jedisLockFactory);\n// 完成初始化，之后可在任意位置直接使用：\ntry (RedisLock redisLock = new ReentrantRedisLock(\"test\")) {\n    if (redisLock.tryLock(1000, 1000, TimeUnit.MILLISECONDS)) {\n        System.out.println(\"获取锁成功\");\n    }\n} catch (Exception e) {\n    e.printStackTrace();\n}\n```\nRedis分布式集群任务\n-----------\n### 集群任务Spring环境下用例\nSpring环境静下，无需其他配置\n1. 任务发布 -- ClusterTaskPublisher \u003cbr/\u003e\n    发布任务api\n    ```java\n    /**\n     * 发布集群任务\n     *\n     * @param taskId         任务ID\n     * @param dataNums       待处理数据个数\n     * @param stepSize       步长\n     * @param concurrentNums 单个服务器并发数量\n     * @param desc           是否倒序\n     * @param header         任务头部信息\n     */\n    publish(taskId, dataNums, stepSize, concurrentNums, desc, header);\n    ```\n    发布任务实例:\n    ```java\n    // 注入任务发布者\n    @Resource(name = \"clusterTaskPublisher\")\n    private ClusterTaskPublisher clusterTaskPublisher;\n    \n    // 调用sql查询待处理数据量\n    int dataNums = dataMapper.countData();\n    // 发布了一个数据量为dataNums的任务，指定一个分片（分页）100条数据并且倒序分配，并且指定订阅者开启6条线程执行任务\n    clusterTaskPublisher.publish(\"test\", dataNums, 100, 6, true, null);\n    ```\n2. 任务订阅 -- 继承AbstractClusterTaskSubscriber \u003cbr/\u003e\n    可由多个服务器节点订阅任务信息，多个节点多线程执行任务，充分利用服务器资源。\n    ```java\n    @Component\n    @SubTask(taskId = \"test\")\n    public class TestSub extends AbstractClusterTaskSubscriber {\n    \n        @Override\n        public void subscribe(TaskInfo taskInfo, Limit limit) {\n            // limit为分页的封装对象，num即为分页开始数,size即为分页大小,\n            // 假设前面发布了一个300条数据量的任务，由于前面发布的任务是倒序，\n            // 那么第一次执行任务的num为200,size为100，第二个为{100,100}，第三个为{0,100}。\n            dataMapper.queryData(limit.getNum,limit.getSize);\n        }\n        \n       /**\n        * 所有分片任务执行完将回调此方法\n        */\n        @Override\n        public void afterAllTask() {\n            System.out.println(\"finish task\");\n        }\n    \n    }\n    ```\n3. 特殊用法 -- 利用header构造任务 \u003cbr/\u003e\n    ```java\n    Map\u003cString, Object\u003e header = new HashMap\u003c\u003e();\n    ArrayList\u003cString\u003e list = new ArrayList\u003c\u003e();\n    list.add(\"task1\");\n    list.add(\"task2\");\n    list.add(\"task3\");\n    list.add(\"task4\");\n    list.add(\"task5\");\n    list.add(\"task6\");\n    header.put(\"taskEnum\", list);\n    clusterTaskPublisher.publish(\"test2\", list.size(), 1, 1, true, header);\n    return JsonMessage.success(\"123\");\n   \n   // 订阅方法\n   @Override\n   public void subscribe(TaskInfo taskInfo, Limit limit) {   \n       Map\u003cString, Object\u003e header = taskInfo.getHeader();\n       ArrayList\u003cString\u003e taskEnum = (List\u003cString\u003e)header.get(\"taskEnum\");\n       int num = limit.getNum();\n       String taskEnum = taskEnum.get(num);\n       swtich(taskEnum){\n           // 捕获不同的任务枚举，执行不同的任务\n           case \"task1\": ...\n           case \"task2\": ...\n           case \"task3\": ...\n           case \"task4\": ...\n           case \"task5\": ...\n           case \"task6\": ...\n       }   \n   }\n    ```\n### 集群任务非Spring环境下用例（jedis）\n1. 配置并初始化 \u003cbr/\u003e\n    与配置redis分布式锁类型，但需要调用JedisClusterHelper.initJedisCluster(factory)初始化任务发布订阅器。\n    ```Java\n    JedisClientFactory factory = new JedisClientFactory(\"localhost\", null, null, null);\n    JedisClient jedisClient = factory.cacheClient();\n    RedisConfiguration.setDefaultRedisManagerFactory(new JedisManagerFactory(jedisClient));\n    ClusterTaskPublisher clusterTaskPublisher = JedisClusterHelper.initJedisCluster(factory);\n    clusterTaskPublisher.publish(\"test\", 100, 10, 1, true);\n    Thread.sleep(10000);\n    ```\n    其他与spring环境下使用情况一致。\u003cbr\u003e\n\n// TODO","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheny2151%2Ftoolbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcheny2151%2Ftoolbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheny2151%2Ftoolbox/lists"}