From 648a504581a6f5fe70abb614cb3445a31c75e3e7 Mon Sep 17 00:00:00 2001 From: shanhm1991 Date: Tue, 15 Oct 2024 06:16:35 +0800 Subject: [PATCH] github init github init --- .github/workflows/maven.yml | 35 ++ .gitignore | 7 +- LICENSE.txt | 202 +++++++++ README.md | 26 +- pom.xml | 413 +++++++++--------- .../springframework/fom/DelayedThread.java | 40 +- .../fom/FomBeanDefinitionRegistrar.java | 4 +- .../fom/FomBeanPostProcessor.java | 128 +++--- .../org/springframework/fom/FomFactory.java | 26 +- ...ExternalRegister.java => FomRegister.java} | 35 +- .../org/springframework/fom/FomStarter.java | 2 +- .../springframework/fom/ScheduleConfig.java | 267 +++++------ .../springframework/fom/ScheduleContext.java | 78 ++-- .../org/springframework/fom/ScheduleInfo.java | 82 ++-- .../fom/ScheduleStatistics.java | 46 +- .../java/org/springframework/fom/Task.java | 15 +- .../springframework/fom/annotation/Fom.java | 84 ++-- .../fom/logging/SLF4JBridgeHandler.java | 2 +- .../fom/logging/log4j/Log4jAppender.java | 2 +- .../fom/proxy/ScheduleFactory.java | 4 +- .../fom/proxy/ScheduleProxy.java | 21 +- .../fom/quartz/CronExpression.java | 264 +++++------ 22 files changed, 1001 insertions(+), 782 deletions(-) create mode 100644 .github/workflows/maven.yml create mode 100644 LICENSE.txt rename src/main/java/org/springframework/fom/{FomExternalRegister.java => FomRegister.java} (74%) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..40f7b14 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,35 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: build + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + #- name: Update dependency graph + # uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 diff --git a/.gitignore b/.gitignore index 202f760..ec10551 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ -.settings/ -.project -.classpath - +target/ .idea/ *.iml - -target/ \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 280aecb..b216403 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ -spring-fom -====================== -[![Build Status](https://github.com/alibaba/easyexcel/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/shanhm1991/spring-fom/issues) -[![Maven central](https://img.shields.io/badge/maven%20central-2.7.0-success)](https://search.maven.org/artifact/io.github.shanhm1991/spring-fom/2.7.0/jar) -[![License](http://img.shields.io/:license-apache-brightgreen.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) +[![Build Status](https://github.com/cowave5/spring-fom/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/cowave5/spring-fom/actions) +![Static Badge](https://img.shields.io/badge/Java-17-brightgreen) +![Maven central](https://img.shields.io/badge/maven--central-2.7.1-brightgreen) +[![License](https://img.shields.io/badge/license-Apache--2.0-brightgreen)](http://www.apache.org/licenses/LICENSE-2.0.txt) -- 设计文档:https://shanhm1991.github.io/2020/01/13/20200113/ +## spring-fom -- 使用文档:https://shanhm1991.github.io/2020/01/15/20200115/ +一个轻量级的任务管理,主要针对定时任务,相对Spring Schedule提供了更多的场景支持 -- 使用示例:https://github.com/shanhm1991/spring-fom-demo +- 依赖 -- 联系:shanhm1991@163.com +```xml + + com.cowave.commons + spring-fom + 2.7.1 + +``` + +- 使用说明:[wiki](https://github.com/cowave5/spring-fom/wiki) +- 问题建议:[issues](https://github.com/cowave5/spring-fom/issues) diff --git a/pom.xml b/pom.xml index a88286d..fe8c4b5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,216 +1,223 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - io.github.shanhm1991 - spring-fom - 2.7.0 - jar + com.cowave.commons + spring-fom + 2.7.1 + jar - spring-fom - A task management tool spring-fom based on thread pool - https://github.com/shanhm1991/spring-fom + spring-fom + schedule task + https://github.com/cowave5/spring-fom - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + - - github - https://github.com/shanhm1991/spring-fom/issues - + + github + https://github.com/cowave5/spring-fom/issues + - - scm:git:https://github.com/shanhm1991/spring-fom.git - scm:git:https://github.com/shanhm1991/spring-fom.git - https://github.com/shanhm1991/spring-fom - + + scm:git:https://github.com/cowave5/spring-fom.git + https://github.com/cowave5/spring-fom + - - - shanhm - shanhm1991@163.com - https://shanhm1991.github.io/ - - + + + shanhuiming + shanhuiming@cowave.com + + - - UTF-8 - UTF-8 - UTF-8 - + + UTF-8 + UTF-8 + UTF-8 + - - src/main/java - - - src/main/resources - - META-INF/** - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - - - - org.apache.maven.plugins - maven-release-plugin - - forked-path - false - -spring-fom-release - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - html - xml - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.0 - - true - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.0 - true - - - bundle-sources - package - - jar - - - - - 1024 - UTF-8 - protected - true - false - none - - - - + + + ossrh + https://s01.oss.sonatype.org/content/repositories/releases/ + + + ossrh + https://s01.oss.sonatype.org/content/repositories/snapshots/ + + - - - ossrh - https://s01.oss.sonatype.org/content/repositories/releases/ - - - ossrh - https://s01.oss.sonatype.org/content/repositories/snapshots/ - - + + src/main/java + + + src/main/resources + + META-INF/** + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + UTF-8 + + + + org.apache.maven.plugins + maven-release-plugin + 3.0.0 + + forked-path + false + -spring-feign-release + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + true + + + + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.10.1 + true + + + bundle-sources + package + + jar + + + + + 1024 + UTF-8 + protected + true + false + none + + + + - - - release - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - - - - - + + + release + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + - - - org.springframework.boot - spring-boot-starter-web - 2.1.1.RELEASE - provided - - - - log4j - log4j - 1.2.17 - provided - - - org.slf4j - slf4j-log4j12 - 1.7.30 - provided - - - org.apache.commons - commons-compress - 1.18 - provided - - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.11.1 - provided - - - org.apache.logging.log4j - log4j-api - 2.11.1 - provided - - - org.apache.logging.log4j - log4j-core - 2.11.1 - provided - - - - ch.qos.logback - logback-classic - 1.2.3 - provided - - - ch.qos.logback - logback-core - 1.2.3 - provided - - + + + org.springframework.boot + spring-boot-starter-web + 2.1.1.RELEASE + provided + + + + log4j + log4j + 1.2.17 + provided + + + org.slf4j + slf4j-log4j12 + 1.7.30 + provided + + + org.apache.commons + commons-compress + 1.18 + provided + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.11.1 + provided + + + org.apache.logging.log4j + log4j-api + 2.11.1 + provided + + + org.apache.logging.log4j + log4j-core + 2.11.1 + provided + + + + ch.qos.logback + logback-classic + 1.2.3 + provided + + + ch.qos.logback + logback-core + 1.2.3 + provided + + diff --git a/src/main/java/org/springframework/fom/DelayedThread.java b/src/main/java/org/springframework/fom/DelayedThread.java index 5080ea3..7d735b3 100644 --- a/src/main/java/org/springframework/fom/DelayedThread.java +++ b/src/main/java/org/springframework/fom/DelayedThread.java @@ -9,16 +9,16 @@ import org.springframework.fom.proxy.TaskCancelHandler; /** - * + * * submit 提交任务的超时语义跟 定时任务有点不同, *

提交的任务会重复尝试取消,比如超时时间为五分钟,那么每隔五分钟都会尝试一次 *

而定时任务只会尝试取消一次,然后一直等待任务结束 *

原因在于定时的任务有定时线程可以负责等待,而手动提交的任务没有线程去帮它观察任务什么时候结束,所以暂时先这样实现 - * + * * @author shanhm1991@163.com * */ -class DelayedThread extends Thread { +class DelayedThread extends Thread { private static final Logger LOGGER = LoggerFactory.getLogger(DelayedThread.class); @@ -32,7 +32,7 @@ static void detectTimeout(List futureList, boolean detectTimeoutOnE if(detectTimeoutOnEachTask){ for(TimedFuture future : futureList){ - DELAYQUEUE.add(new DelayedSingleTask(future, future.getTimeOut())); + DELAYQUEUE.add(new DelayedSingleTask(future, future.getTimeOut())); } }else{ DELAYQUEUE.add(new DelayedBatchTask(futureList, futureList.get(0).getTimeOut())); @@ -40,7 +40,7 @@ static void detectTimeout(List futureList, boolean detectTimeoutOnE } public DelayedThread(){ - this.setName("SubmitDemonThread"); + this.setName("SubmitDemonThread"); this.setDaemon(true); } @@ -51,7 +51,7 @@ public void run() { try { delayedTask = DELAYQUEUE.take(); } catch (InterruptedException e) { - LOGGER.info("Thread DaemonSubmitThread interrupted and stoped"); + LOGGER.info("Thread DaemonSubmitThread interrupted and stoped"); return; } @@ -68,28 +68,28 @@ private void waitSingleTask(DelayedSingleTask delayedTask){ TimedFuture future = delayedTask.getFuture(); int overTime = future.getTimeOut(); if(!future.isDone()) { - long startTime = future.getStartTime(); + long startTime = future.getStartTime(); if(startTime == 0){ // startTime = 0 表示任务还没启动 - DELAYQUEUE.add(new DelayedSingleTask(future, overTime)); + DELAYQUEUE.add(new DelayedSingleTask(future, overTime)); }else{ - long cost = System.currentTimeMillis() - future.getStartTime(); + long cost = System.currentTimeMillis() - future.getStartTime(); if(cost >= overTime){ Task task = future.getTask(); ScheduleContext scheduleContext = task.getScheduleContext(); Logger logger = scheduleContext.getLogger(); - logger.info("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); + logger.warn("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); try{ scheduleContext.handleCancel(future.getTaskId(), cost); }catch(Exception e){ - logger.error("", e); + logger.error("", e); } cancleTask(future, cost, logger); }else{ - DELAYQUEUE.add(new DelayedSingleTask(future, overTime - cost)); + DELAYQUEUE.add(new DelayedSingleTask(future, overTime - cost)); } } }else if(future.isEnableTaskConflict()){ - ScheduleContext.cleanCompletedFutures(future.getTaskId()); + ScheduleContext.cleanCompletedFutures(future.getTaskId()); } } @@ -109,21 +109,21 @@ private void waitBatchTask(DelayedBatchTask delayedTask){ if(!future.isDone()) { long cost = 0; if(future.getStartTime() == 0){ - logger.info("cancle task[{}] which has not started, cost={}ms", future.getTaskId(), cost); + logger.warn("cancle task[{}] which has not started, cost={}ms", future.getTaskId(), cost); }else{ - cost = System.currentTimeMillis() - future.getStartTime(); - logger.info("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); + cost = System.currentTimeMillis() - future.getStartTime(); + logger.warn("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); try{ scheduleContext.handleCancel(future.getTaskId(), cost); }catch(Exception e){ - logger.error("", e); + logger.error("", e); } } cancleTask(future, cost, logger); }else{ it.remove(); if(future.isEnableTaskConflict()){ - ScheduleContext.cleanCompletedFutures(future.getTaskId()); + ScheduleContext.cleanCompletedFutures(future.getTaskId()); } } } @@ -136,12 +136,12 @@ private void waitBatchTask(DelayedBatchTask delayedTask){ @SuppressWarnings("rawtypes") private void cancleTask(TimedFuture future, long costTime, Logger logger) { Task task = future.getTask(); - if(costTime > 0 && TaskCancelHandler.class.isAssignableFrom(task.getClass())){ + if(costTime > 0 && TaskCancelHandler.class.isAssignableFrom(task.getClass())){ TaskCancelHandler handler = (TaskCancelHandler)task; try { handler.handleCancel(task.getTaskId(), costTime); } catch (Exception e) { - logger.error("", e); + logger.error("", e); } } future.cancel(true); diff --git a/src/main/java/org/springframework/fom/FomBeanDefinitionRegistrar.java b/src/main/java/org/springframework/fom/FomBeanDefinitionRegistrar.java index a508045..68cda25 100644 --- a/src/main/java/org/springframework/fom/FomBeanDefinitionRegistrar.java +++ b/src/main/java/org/springframework/fom/FomBeanDefinitionRegistrar.java @@ -49,7 +49,7 @@ public void registerBeanDefinitions(AnnotationMetadata meta, BeanDefinitionRegis registry.registerBeanDefinition("fomStarter", fomStarter); // FomExternalRegister - RootBeanDefinition fomExternalRegister = new RootBeanDefinition(FomExternalRegister.class); + RootBeanDefinition fomExternalRegister = new RootBeanDefinition(FomRegister.class); registry.registerBeanDefinition("fomExternalRegister", fomExternalRegister); // FomBeanDefinition @@ -66,7 +66,7 @@ public void registerBeanDefinitions(AnnotationMetadata meta, BeanDefinitionRegis } Fom fom = clazz.getAnnotation(Fom.class); - if(fom != null && !fom.external()){ // 忽略external + if(fom != null && fom.autoLoad()){ parseFomSchedule(beanName, clazz, beanDefinition, fom, registry); } } diff --git a/src/main/java/org/springframework/fom/FomBeanPostProcessor.java b/src/main/java/org/springframework/fom/FomBeanPostProcessor.java index 3631421..c527ec6 100644 --- a/src/main/java/org/springframework/fom/FomBeanPostProcessor.java +++ b/src/main/java/org/springframework/fom/FomBeanPostProcessor.java @@ -28,7 +28,7 @@ import org.springframework.util.StringValueResolver; /** - * + * * @author shanhm1991@163.com * */ @@ -54,24 +54,24 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw if(!(ScheduleContext.class.isAssignableFrom(clazz))){ return bean; } - + ScheduleContext scheduleContext = (ScheduleContext)bean; - + // 插一段external专门处理 - if(scheduleContext.isExternal()) { + if(scheduleContext.isExternal()) { return processExternal(scheduleContext, beanName); } - - String scheduleBeanName = scheduleContext.getScheduleBeanName(); + + String scheduleBeanName = scheduleContext.getScheduleBeanName(); Fom fom = scheduleContext.getClass().getAnnotation(Fom.class); - + // @Bean不处理 if(!StringUtils.hasText(scheduleBeanName) && fom == null){ - scheduleContext.setScheduleName(beanName); + scheduleContext.setScheduleName(beanName); scheduleContext.setLogger(LoggerFactory.getLogger(scheduleContext.getClass())); return bean; } - + Object scheduleBean = null; if(StringUtils.hasText(scheduleBeanName)){ scheduleBean = beanFactory.getBean(scheduleBeanName); @@ -81,8 +81,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw fom = clazz.getAnnotation(Fom.class); if(fom == null){ fom = scheduleBean.getClass().getAnnotation(Fom.class); - scheduleContext.setLogger(LoggerFactory.getLogger(scheduleBean.getClass())); - }else{ + scheduleContext.setLogger(LoggerFactory.getLogger(scheduleBean.getClass())); + }else{ scheduleContext.setLogger(LoggerFactory.getLogger(clazz)); } @@ -102,12 +102,16 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw } catch (Exception e) { throw new ApplicationContextException("", e); } - + // 刷新配置 - scheduleConfig.refresh(); - + if(StringUtils.hasText(scheduleBeanName)){ + scheduleConfig.refresh(scheduleBeanName); + }else{ + scheduleConfig.refresh(beanName); + } + // 初始化时提前设置一下,因为运行过程中不允许修改 - scheduleContext.setEnableTaskConflict(scheduleConfig.getEnableTaskConflict()); + scheduleContext.setEnableTaskConflict(scheduleConfig.enableTaskConflict()); // 创建代理 注册容器 Enhancer enhancer = new Enhancer(); @@ -115,7 +119,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw enhancer.setCallback(new ScheduleProxy(beanName, scheduleContext, scheduleBean)); return enhancer.create(); } - + private Object processExternal(ScheduleContext scheduleContext, String beanName) { beanFactory.registerSingleton("$EXTERNAL$" + beanName, scheduleContext); Object scheduleBean = beanFactory.getBean(scheduleContext.getScheduleBeanName()); @@ -125,7 +129,7 @@ private Object processExternal(ScheduleContext scheduleContext, String beanNa return enhancer.create(); } - private void loadCache(String beanName, ScheduleContext scheduleContext) throws Exception{ + private void loadCache(String beanName, ScheduleContext scheduleContext) throws Exception{ String cacheType = valueResolver.resolveStringValue("${spring.fom.cache.type:file}"); if("file".equalsIgnoreCase(cacheType)){ loadFromFile(beanName, scheduleContext); @@ -133,7 +137,7 @@ private void loadCache(String beanName, ScheduleContext scheduleContext) thro loadFromRedis(beanName, scheduleContext); } } - + @SuppressWarnings("unchecked") private void loadFromFile(String beanName, ScheduleContext scheduleContext) throws Exception{ String cacheFilePath = valueResolver.resolveStringValue("${spring.fom.cache.file.path:cache/schedule}"); @@ -141,14 +145,14 @@ private void loadFromFile(String beanName, ScheduleContext scheduleContext) t if(!file.exists()){ return; } - + try(FileInputStream input = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(input);){ HashMap map = (HashMap)ois.readObject(); String cron = (String)map.remove(ScheduleConfig.KEY_cron); ScheduleConfig scheduleConfig = scheduleContext.getScheduleConfig(); - scheduleConfig.setCron(cron); + scheduleConfig.cron(cron); Map originalMap = scheduleConfig.getOriginalMap(); originalMap.putAll(map); @@ -161,7 +165,7 @@ private void loadFromFile(String beanName, ScheduleContext scheduleContext) t scheduleContext.valueEnvirmentField(envirmentField); } } - + private void loadFromRedis(String beanName, ScheduleContext scheduleContext) throws Exception{ // TODO } @@ -179,7 +183,7 @@ private void setCron(ScheduleConfig scheduleConfig, Fom fom, ScheduleContext private boolean setCron(ScheduleConfig scheduleConfig, String cron){ if(StringUtils.hasText(cron)){ cron = valueResolver.resolveStringValue(cron); - scheduleConfig.setCron(cron); + scheduleConfig.cron(cron); return true; } return false; @@ -188,11 +192,11 @@ private boolean setCron(ScheduleConfig scheduleConfig, String cron){ private boolean setFixedRate(ScheduleConfig scheduleConfig, long fixedRate, String fixedRateString){ if(StringUtils.hasText(fixedRateString)){ fixedRateString = valueResolver.resolveStringValue(fixedRateString); - if(scheduleConfig.setFixedRate(Long.parseLong(fixedRateString))){ + if(scheduleConfig.fixedRate(Long.parseLong(fixedRateString))){ return true; } } - if(scheduleConfig.setFixedRate(fixedRate)){ + if(scheduleConfig.fixedRate(fixedRate)){ return true; } return false; @@ -201,31 +205,31 @@ private boolean setFixedRate(ScheduleConfig scheduleConfig, long fixedRate, Stri private boolean setFixedDelay(ScheduleConfig scheduleConfig, long fixedDelay, String fixedDelayString){ if(StringUtils.hasText(fixedDelayString)){ fixedDelayString = valueResolver.resolveStringValue(fixedDelayString); - if(scheduleConfig.setFixedDelay(Long.parseLong(fixedDelayString))){ + if(scheduleConfig.fixedDelay(Long.parseLong(fixedDelayString))){ return true; } } - if(scheduleConfig.setFixedDelay(fixedDelay)){ + if(scheduleConfig.fixedDelay(fixedDelay)){ return true; } return false; } private void setConf(ScheduleConfig scheduleConfig, Fom fom){ - - scheduleConfig.setInitialDelay(fom.initialDelay()); - - scheduleConfig.setDeadTime(fom.deadTime()); - + + scheduleConfig.initialDelay(fom.initialDelay()); + + scheduleConfig.deadTime(fom.deadTime()); + String threadCoreString = fom.threadCoreString(); if(StringUtils.hasText(threadCoreString)){ threadCoreString = valueResolver.resolveStringValue(threadCoreString); int threadCore = Integer.parseInt(threadCoreString); if(ScheduleConfig.DEFAULT_threadCore != threadCore){ - scheduleConfig.setThreadCore(threadCore); + scheduleConfig.threadCore(threadCore); } }else if(ScheduleConfig.DEFAULT_threadCore != fom.threadCore()){ - scheduleConfig.setThreadCore(fom.threadCore()); + scheduleConfig.threadCore(fom.threadCore()); } String threadMaxString = fom.threadMaxString(); @@ -233,60 +237,54 @@ private void setConf(ScheduleConfig scheduleConfig, Fom fom){ threadMaxString = valueResolver.resolveStringValue(threadMaxString); int threadMax = Integer.parseInt(threadMaxString); if(ScheduleConfig.DEFAULT_threadCore != threadMax){ - scheduleConfig.setThreadMax(threadMax); + scheduleConfig.threadMax(threadMax); } }else if(ScheduleConfig.DEFAULT_threadCore != fom.threadMax()){ - scheduleConfig.setThreadMax(fom.threadMax()); + scheduleConfig.threadMax(fom.threadMax()); } String queueSize = fom.queueSizeString(); - if(!StringUtils.hasText(queueSize) - || !scheduleConfig.setQueueSize(Integer.parseInt(valueResolver.resolveStringValue(queueSize)))){ - scheduleConfig.setQueueSize(fom.queueSize()); + if(!StringUtils.hasText(queueSize) + || !scheduleConfig.queueSize(Integer.parseInt(valueResolver.resolveStringValue(queueSize)))){ + scheduleConfig.queueSize(fom.queueSize()); } String threadAliveTime = fom.threadAliveTimeString(); - if(!StringUtils.hasText(threadAliveTime) - || !scheduleConfig.setThreadAliveTime(Integer.parseInt(valueResolver.resolveStringValue(threadAliveTime)))){ - scheduleConfig.setThreadAliveTime(fom.threadAliveTime()); + if(!StringUtils.hasText(threadAliveTime) + || !scheduleConfig.threadAliveTime(Integer.parseInt(valueResolver.resolveStringValue(threadAliveTime)))){ + scheduleConfig.threadAliveTime(fom.threadAliveTime()); } - scheduleConfig.setRemark(valueResolver.resolveStringValue(fom.remark())); + scheduleConfig.remark(valueResolver.resolveStringValue(fom.remark())); String execOnLoad = fom.execOnLoadString(); - if(!StringUtils.hasText(execOnLoad) - || !scheduleConfig.setExecOnLoad(Boolean.parseBoolean(valueResolver.resolveStringValue(execOnLoad)))){ - scheduleConfig.setExecOnLoad(fom.execOnLoad()); + if(!StringUtils.hasText(execOnLoad) + || !scheduleConfig.execOnLoad(Boolean.parseBoolean(valueResolver.resolveStringValue(execOnLoad)))){ + scheduleConfig.execOnLoad(fom.execOnLoad()); } String taskOverTime = fom.taskOverTimeString(); - if(!StringUtils.hasText(taskOverTime) - || !scheduleConfig.setTaskOverTime(Integer.parseInt(valueResolver.resolveStringValue(taskOverTime)))){ - scheduleConfig.setTaskOverTime(fom.taskOverTime()); + if(!StringUtils.hasText(taskOverTime) + || !scheduleConfig.taskOverTime(Integer.parseInt(valueResolver.resolveStringValue(taskOverTime)))){ + scheduleConfig.taskOverTime(fom.taskOverTime()); } String detectTimeoutOnEachTask = fom.detectTimeoutOnEachTaskString(); - if(!StringUtils.hasText(detectTimeoutOnEachTask) - || !scheduleConfig.setDetectTimeoutOnEachTask(Boolean.parseBoolean(valueResolver.resolveStringValue(detectTimeoutOnEachTask)))){ - scheduleConfig.setDetectTimeoutOnEachTask(fom.detectTimeoutOnEachTask()); + if(!StringUtils.hasText(detectTimeoutOnEachTask) + || !scheduleConfig.detectTimeoutOnEachTask(Boolean.parseBoolean(valueResolver.resolveStringValue(detectTimeoutOnEachTask)))){ + scheduleConfig.detectTimeoutOnEachTask(fom.detectTimeoutOnEachTask()); } - String ignoreExecRequestWhenRunning = fom.ignoreExecRequestWhenRunningString(); - if(!StringUtils.hasText(ignoreExecRequestWhenRunning) - || !scheduleConfig.setIgnoreExecRequestWhenRunning(Boolean.parseBoolean(valueResolver.resolveStringValue(ignoreExecRequestWhenRunning)))){ - scheduleConfig.setIgnoreExecRequestWhenRunning(fom.ignoreExecRequestWhenRunning()); + String ignoreExecRequestWhenRunning = fom.ignoreExecWhenRunningString(); + if(!StringUtils.hasText(ignoreExecRequestWhenRunning) + || !scheduleConfig.ignoreExecWhenRunning(Boolean.parseBoolean(valueResolver.resolveStringValue(ignoreExecRequestWhenRunning)))){ + scheduleConfig.ignoreExecWhenRunning(fom.ignoreExecWhenRunning()); } String enableTaskConflict = fom.enableTaskConflictString(); - if(!StringUtils.hasText(enableTaskConflict) - || !scheduleConfig.setEnableTaskConflict(Boolean.parseBoolean(valueResolver.resolveStringValue(enableTaskConflict)))){ - scheduleConfig.setEnableTaskConflict(fom.enableTaskConflict()); - } - - String enableString = fom.enableString(); - if(!StringUtils.hasText(enableString) - || !scheduleConfig.setEnable(Boolean.parseBoolean(valueResolver.resolveStringValue(enableString)))){ - scheduleConfig.setEnable(fom.enable()); + if(!StringUtils.hasText(enableTaskConflict) + || !scheduleConfig.enableTaskConflict(Boolean.parseBoolean(valueResolver.resolveStringValue(enableTaskConflict)))){ + scheduleConfig.enableTaskConflict(fom.enableTaskConflict()); } } @@ -322,7 +320,7 @@ private void setValue(ScheduleConfig scheduleConfig, ScheduleContext schedule fieldList.add(field); scheduleConfig.set(key, confValue); } - + // 配置集合中的值尽量按照对应属性的类型来(如果可以的话) if(list.size() == 1) { switch(field.getGenericType().toString()){ diff --git a/src/main/java/org/springframework/fom/FomFactory.java b/src/main/java/org/springframework/fom/FomFactory.java index 0085367..9ed7e60 100644 --- a/src/main/java/org/springframework/fom/FomFactory.java +++ b/src/main/java/org/springframework/fom/FomFactory.java @@ -7,28 +7,28 @@ import org.springframework.context.ApplicationContextAware; /** - * + * * @author shanhm1991@163.com * */ public class FomFactory implements FactoryBean>, ApplicationContextAware { - + private Class scheduleClass; - + private String scheduleName; - + private String scheduleBeanName; - + private ScheduleConfig scheduleConfig; - + private ApplicationContext applicationContext; - + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; - + } - + @Override public ScheduleContext getObject() throws Exception { ScheduleContext scheduleContext = new ScheduleContext<>(); @@ -38,9 +38,13 @@ public ScheduleContext getObject() throws Exception { scheduleContext.setScheduleName(scheduleName); scheduleContext.setExternal(true); scheduleContext.setApplicationContext(applicationContext); - + ScheduleConfig config = scheduleContext.getScheduleConfig(); - config.refresh(); + if(scheduleBeanName != null){ + config.refresh(scheduleBeanName); + }else{ + config.refresh(scheduleName); + } return scheduleContext; } diff --git a/src/main/java/org/springframework/fom/FomExternalRegister.java b/src/main/java/org/springframework/fom/FomRegister.java similarity index 74% rename from src/main/java/org/springframework/fom/FomExternalRegister.java rename to src/main/java/org/springframework/fom/FomRegister.java index cec1599..a21df04 100644 --- a/src/main/java/org/springframework/fom/FomExternalRegister.java +++ b/src/main/java/org/springframework/fom/FomRegister.java @@ -13,13 +13,13 @@ import org.springframework.fom.annotation.Fom; /** - * + * * @author shanhm1991@163.com * */ -public class FomExternalRegister implements BeanFactoryAware, ApplicationContextAware { +public class FomRegister implements BeanFactoryAware, ApplicationContextAware { - private static final Logger logger = LoggerFactory.getLogger(FomExternalRegister.class); + private static final Logger logger = LoggerFactory.getLogger(FomRegister.class); private static DefaultListableBeanFactory defaultListableBeanFactory; @@ -27,7 +27,7 @@ public class FomExternalRegister implements BeanFactoryAware, ApplicationContext @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - defaultListableBeanFactory = (DefaultListableBeanFactory)beanFactory; + defaultListableBeanFactory = (DefaultListableBeanFactory)beanFactory; } @Override @@ -37,11 +37,11 @@ public void setApplicationContext(ApplicationContext context) throws BeansExcept /** * 注入外部定时器 - * @param scheduleName 定时器beanName + * @param scheduleName 定时器beanName * @param scheduleClass 被代理Class * @param scheduleConfig 定时配置 */ - public static void regist(String scheduleName, Class scheduleClass, ScheduleConfig scheduleConfig) { + public static ScheduleContext register(String scheduleName, Class scheduleClass, ScheduleConfig scheduleConfig) { Fom fom = scheduleClass.getAnnotation(Fom.class); if(fom == null) { throw new FomException(scheduleClass + " is not a fom"); @@ -50,24 +50,31 @@ public static void regist(String scheduleName, Class scheduleClass, ScheduleC String[] names = applicationContext.getBeanNamesForType(scheduleClass); String scheduleBeanName = names[0]; - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ScheduleContext.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ScheduleContext.class); GenericBeanDefinition beanDefinition = (GenericBeanDefinition)builder.getBeanDefinition(); - beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); + beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); beanDefinition.getPropertyValues().add("scheduleClass", scheduleClass); beanDefinition.getPropertyValues().add("scheduleConfig", scheduleConfig); beanDefinition.getPropertyValues().add("scheduleName", scheduleName); beanDefinition.getPropertyValues().add("scheduleBeanName", scheduleBeanName); beanDefinition.setBeanClass(FomFactory.class); - defaultListableBeanFactory.registerBeanDefinition(scheduleName, beanDefinition); - ScheduleContext schedule = defaultListableBeanFactory.getBean(scheduleName, ScheduleContext.class); // 实例化一下 - + if (defaultListableBeanFactory.containsBeanDefinition(scheduleName)) { + defaultListableBeanFactory.removeBeanDefinition(scheduleName); + if (defaultListableBeanFactory.containsSingleton(scheduleName)) { + defaultListableBeanFactory.destroySingleton(scheduleName); + } + } + defaultListableBeanFactory.registerBeanDefinition(scheduleName, beanDefinition); + ScheduleContext schedule = defaultListableBeanFactory.getBean(scheduleName, ScheduleContext.class); + ScheduleConfig config = schedule.getScheduleConfig(); - if(config.getBoolean(ScheduleConfig.KEY_enable, true)){ + if(config.execOnLoad()){ schedule.scheduleStart(); - logger.info("register and start schedule[{}]: {}", scheduleName, config.getConfMap()); + logger.info("register and start schedule[{}]: {}", scheduleName, config.getConfMap()); }else{ - logger.info("register schedule[{}]: {}", scheduleName, config.getConfMap()); + logger.info("register schedule[{}]: {}", scheduleName, config.getConfMap()); } + return schedule; } } diff --git a/src/main/java/org/springframework/fom/FomStarter.java b/src/main/java/org/springframework/fom/FomStarter.java index 641c019..fe1ea6c 100644 --- a/src/main/java/org/springframework/fom/FomStarter.java +++ b/src/main/java/org/springframework/fom/FomStarter.java @@ -30,7 +30,7 @@ public void start() { for(String scheduleName : scheduleNames){ ScheduleContext schedule = (ScheduleContext)applicationContext.getBean(scheduleName); ScheduleConfig config = schedule.getScheduleConfig(); - if(config.getBoolean(ScheduleConfig.KEY_enable, true)){ + if(config.execOnLoad()){ schedule.scheduleStart(); logger.info("load and start schedule[{}]: {}", scheduleName, schedule.getScheduleConfig().getConfMap()); }else{ diff --git a/src/main/java/org/springframework/fom/ScheduleConfig.java b/src/main/java/org/springframework/fom/ScheduleConfig.java index 7adfd00..7c6828f 100644 --- a/src/main/java/org/springframework/fom/ScheduleConfig.java +++ b/src/main/java/org/springframework/fom/ScheduleConfig.java @@ -4,14 +4,8 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -21,27 +15,22 @@ import org.springframework.util.StringUtils; /** - * + * * @author shanhm1991@163.com * */ public class ScheduleConfig { - - /** - * 加载时是否启动 - */ - public static final String KEY_enable = "enable"; - + /** * 启动时是否执行 */ public static final String KEY_execOnLoad = "execOnLoad"; - + /** * 定时计划:cron */ public static final String KEY_cron = "cron"; - + /** * 定时计划:fixedRate */ @@ -51,7 +40,7 @@ public class ScheduleConfig { * 定时计划:fixedDelay */ public static final String KEY_fixedDelay = "fixedDelay"; - + /** * 线程池任务队列长度 */ @@ -71,107 +60,102 @@ public class ScheduleConfig { * 线程池任务线程最长空闲时间 */ public static final String KEY_threadAliveTime = "threadAliveTime"; - + /** * 任务超时时间 */ public static final String KEY_taskOverTime = "taskOverTime"; - + /** * 是否对每个任务单独检测超时 */ public static final String KEY_detectTimeoutOnEachTask = "detectTimeoutOnEachTask"; - + /** * 是否检测任务冲突 */ public static final String KEY_enableTaskConflict = "enableTaskConflict"; - + /** * Running时是否忽略执行请求 */ - public static final String KEY_ignoreExecRequestWhenRunning = "ignoreExecRequestWhenRunning"; - + public static final String KEY_ignoreExecWhenRunning = "ignoreExecWhenRunning"; + /** * 备注 */ public static final String KEY_remark = "remark"; - + /** * 首次执行延迟时间 */ public static final String KEY_initialDelay = "initialDelay"; - + /** * 任务截止时间 */ public static final String KEY_deadTime = "deadTime"; - - /** - * 默认加载启动 - */ - public static final boolean DEFAULT_enable = true; - + /** - * 启动时默认不执行 + * 加载后默认不立即执行 */ public static final boolean DEFAULT_execOnLoad = false; - + /** * fixedRate 默认0 */ public static final int DEFAULT_fixedRate = 0; - + /** * fixedDelay 默认0 */ public static final int DEFAULT_fixedDelay = 0; - + /** * 线程数 默认1 */ public static final int DEFAULT_threadCore = 1; - + /** * 线程空闲时间:默认1 */ public static final int DEFAULT_threadAliveTime = 10; - + /** * 任务队列长度:默认256 */ public static final int DEFAULT_queueSize = 256; - + /** * 任务超时时间:默认不超时 */ public static final int DEFAULT_taskOverTime = 0; - + /** * 默认不检测任务冲突 */ public static final boolean DEFAULT_enableTaskConflict = false; - + /** * 默认对每个任务单独检测超时 */ public static final boolean DEFAULT_detectTimeoutOnEachTask = true; - + /** * Running状态时默认忽略执行请求 */ - public static final boolean DEFAULT_ignoreExecRequestWhenRunning = true; - + public static final boolean DEFAULT_ignoreExecWhenRunning = true; + /** * 首次执行延迟时间 默认0 */ public static final long DEFAULT_initialDelay = 0; - + /** * 任务截止时间 默认0 */ public static final long DEFAULT_deadTime = 0; - + // 内部配置,不允许直接put private static Map internalConf = new TreeMap<>(); @@ -190,8 +174,7 @@ public class ScheduleConfig { internalConf.put(KEY_execOnLoad, DEFAULT_execOnLoad); internalConf.put(KEY_enableTaskConflict, DEFAULT_enableTaskConflict); internalConf.put(KEY_detectTimeoutOnEachTask, DEFAULT_detectTimeoutOnEachTask); - internalConf.put(KEY_ignoreExecRequestWhenRunning, DEFAULT_ignoreExecRequestWhenRunning); - internalConf.put(KEY_enable, DEFAULT_enable); + internalConf.put(KEY_ignoreExecWhenRunning, DEFAULT_ignoreExecWhenRunning); internalConf.put(KEY_initialDelay, DEFAULT_initialDelay); internalConf.put(KEY_deadTime, DEFAULT_deadTime); } @@ -200,11 +183,11 @@ public class ScheduleConfig { private TimedExecutorPool pool; - public void refresh(){ - int core = getThreadCore(); - int max = getThreadMax(); - int aliveTime = getThreadAliveTime(); - int queueSize = getQueueSize(); + public void refresh(String scheduleName){ + int core = threadCore(); + int max = threadMax(); + int aliveTime = threadAliveTime(); + int queueSize = queueSize(); pool = new TimedExecutorPool(core, max, aliveTime, new LinkedBlockingQueue(queueSize)); pool.allowCoreThreadTimeOut(true); } @@ -224,14 +207,14 @@ TimedExecutorPool getPool() { public Map getConfMap() { Map map = new HashMap<>(); map.putAll(confMap); - map.put(KEY_cron, getCronExpression()); + map.put(KEY_cron, cron()); return map; - } + } Map getOriginalMap() { return confMap; } - + void copy(ScheduleConfig scheduleConfig) { confMap.putAll(scheduleConfig.confMap); } @@ -259,7 +242,7 @@ long getCompleted(){ @SuppressWarnings("unchecked") Map, Thread> getActiveThreads() { - return (Map, Thread>) (pool == null ? new HashMap<>() : pool.getActiveThreads()); + return pool == null ? new HashMap<>() : pool.getActiveThreads(); } @SuppressWarnings("rawtypes") @@ -326,20 +309,20 @@ private String buildMsg(Object... args){ return builder.toString(); } - // get/set of internal config - public CronExpression getCron(){ + // get/set of internal config + public CronExpression cronExpression(){ return (CronExpression)confMap.get(KEY_cron); } - public String getCronExpression(){ - CronExpression cron = getCron(); - if(cron != null){ - return cron.getCronExpression(); + public String cron(){ + CronExpression cronExpression = cronExpression(); + if(cronExpression != null){ + return cronExpression.getCronExpression(); } return null; } - public boolean setCron(String cron){ + public boolean cron(String cron){ if(!StringUtils.hasText(cron)){ return false; } @@ -351,87 +334,87 @@ public boolean setCron(String cron){ throw new IllegalArgumentException("cronExpression cannot parsed", e); } - if(!cron.equals(getCron())){ + if(!cronExpression.equals(cronExpression())){ confMap.put(KEY_cron, cronExpression); return true; } return false; } - public long getFixedRate(){ + public long fixedRate(){ return MapUtils.getLongValue(confMap, KEY_fixedRate, DEFAULT_fixedRate); } - public boolean setFixedRate(long fixedRate){ - if(fixedRate > DEFAULT_fixedRate && fixedRate != getFixedRate()){ + public boolean fixedRate(long fixedRate){ + if(fixedRate > DEFAULT_fixedRate && fixedRate != fixedRate()){ confMap.put(KEY_fixedRate, fixedRate); return true; } return false; } - public long getFixedDelay(){ + public long fixedDelay(){ return MapUtils.getLongValue(confMap, KEY_fixedDelay, DEFAULT_fixedDelay); } - public boolean setFixedDelay(long fixedDelay){ - if(fixedDelay > DEFAULT_fixedDelay && fixedDelay != getFixedDelay()){ + public boolean fixedDelay(long fixedDelay){ + if(fixedDelay > DEFAULT_fixedDelay && fixedDelay != fixedDelay()){ confMap.put(KEY_fixedDelay, fixedDelay); return true; } return false; } - public String getRemark(){ + public String remark(){ return MapUtils.getString(confMap, KEY_remark, ""); } - public boolean setRemark(String remark){ - if(remark.equals(getRemark())){ + public boolean remark(String remark){ + if(remark.equals(remark())){ return false; } confMap.put(KEY_remark, remark); return true; } - public int getThreadCore(){ + public int threadCore(){ return MapUtils.getIntValue(confMap, KEY_threadCore, DEFAULT_threadCore); } - public boolean setThreadCore(int threadCore){ + public boolean threadCore(int threadCore){ Assert.isTrue(threadCore >= DEFAULT_threadCore, buildMsg(KEY_threadCore, " cannot be less than ", DEFAULT_threadCore)); - if(threadCore == getThreadCore()){ + if(threadCore == threadCore()){ return false; } confMap.put(KEY_threadCore, threadCore); - int threadMax = getThreadMax(); - if(threadMax < threadCore){ + int threadMax = threadMax(); + if(threadMax < threadCore){ threadMax = threadCore; confMap.put(KEY_threadMax, threadMax); } if(pool != null && pool.getCorePoolSize() != threadCore){ pool.setCorePoolSize(threadCore); - pool.setMaximumPoolSize(threadMax); + pool.setMaximumPoolSize(threadMax); } return true; } - public int getThreadMax(){ + public int threadMax(){ return MapUtils.getIntValue(confMap, KEY_threadMax, DEFAULT_threadCore); } - public boolean setThreadMax(int threadMax){ + public boolean threadMax(int threadMax){ Assert.isTrue(threadMax >= DEFAULT_threadCore, buildMsg(KEY_threadMax, " cannot be less than ", DEFAULT_threadCore)); - if(threadMax == getThreadMax()){ + if(threadMax == threadMax()){ return false; } confMap.put(KEY_threadMax, threadMax); - int threadCore = getThreadCore(); + int threadCore = threadCore(); if(threadCore > threadMax){ threadCore = threadMax; confMap.put(KEY_threadCore, threadCore); @@ -444,128 +427,116 @@ public boolean setThreadMax(int threadMax){ return true; } - public int getThreadAliveTime(){ + public int threadAliveTime(){ return MapUtils.getIntValue(confMap, KEY_threadAliveTime, DEFAULT_threadAliveTime); } - public boolean setThreadAliveTime(int aliveTime){ + public boolean threadAliveTime(int aliveTime){ Assert.isTrue(aliveTime >= DEFAULT_threadAliveTime, buildMsg(KEY_threadAliveTime, " cannot be less than ", DEFAULT_threadAliveTime)); - if(aliveTime == getThreadAliveTime()){ + if(aliveTime == threadAliveTime()){ return false; } confMap.put(KEY_threadAliveTime, aliveTime); - if(pool != null && pool.getKeepAliveTime(TimeUnit.MILLISECONDS) != aliveTime){ + if(pool != null && pool.getKeepAliveTime(TimeUnit.MILLISECONDS) != aliveTime){ pool.setKeepAliveTime(aliveTime, TimeUnit.MILLISECONDS); } return true; } - public int getTaskOverTime(){ + public int taskOverTime(){ return MapUtils.getIntValue(confMap, DEFAULT_taskOverTime); } - public boolean setTaskOverTime(int overTime){ - Assert.isTrue(overTime == DEFAULT_taskOverTime|| + public boolean taskOverTime(int overTime){ + Assert.isTrue(overTime == DEFAULT_taskOverTime|| overTime > 1000, buildMsg(KEY_taskOverTime, " cannot be less than 1000")); - if(overTime == getTaskOverTime()){ + if(overTime == taskOverTime()){ return false; } confMap.put(KEY_taskOverTime, overTime); return true; } - public boolean getExecOnLoad(){ + public boolean execOnLoad(){ return MapUtils.getBoolean(confMap, KEY_execOnLoad, DEFAULT_execOnLoad); } - public boolean setExecOnLoad(boolean execOnLoad) { - if(execOnLoad == getExecOnLoad()){ + public boolean execOnLoad(boolean execOnLoad) { + if(execOnLoad == execOnLoad()){ return false; } confMap.put(KEY_execOnLoad, execOnLoad); return true; } - public boolean getDetectTimeoutOnEachTask(){ + public boolean detectTimeoutOnEachTask(){ return MapUtils.getBoolean(confMap, KEY_detectTimeoutOnEachTask, DEFAULT_detectTimeoutOnEachTask); } - public boolean setDetectTimeoutOnEachTask(boolean detectTimeoutOnEachTask){ - if(detectTimeoutOnEachTask == getDetectTimeoutOnEachTask()){ + public boolean detectTimeoutOnEachTask(boolean detectTimeoutOnEachTask){ + if(detectTimeoutOnEachTask == detectTimeoutOnEachTask()){ return false; } confMap.put(KEY_detectTimeoutOnEachTask, detectTimeoutOnEachTask); return true; } - public boolean getEnableTaskConflict(){ + public boolean enableTaskConflict(){ return MapUtils.getBoolean(confMap, KEY_enableTaskConflict, DEFAULT_enableTaskConflict); } - public boolean setEnableTaskConflict(boolean enableTaskConflict){ - if(enableTaskConflict == getEnableTaskConflict()){ + public boolean enableTaskConflict(boolean enableTaskConflict){ + if(enableTaskConflict == enableTaskConflict()){ return false; } confMap.put(KEY_enableTaskConflict, enableTaskConflict); return true; } - - public boolean getEnable(){ - return MapUtils.getBoolean(confMap, KEY_enable, DEFAULT_enable); - } - - public boolean setEnable(boolean enable){ - if(enable == getEnable()){ - return false; - } - confMap.put(KEY_enable, enable); - return true; - } - - public long getInitialDelay() { + + public long initialDelay() { return MapUtils.getLong(confMap, KEY_initialDelay, DEFAULT_initialDelay); } - - public boolean setInitialDelay(long initialDelay) { - if(initialDelay == getInitialDelay()) { + + public boolean initialDelay(long initialDelay) { + if(initialDelay == initialDelay()) { return false; } confMap.put(KEY_initialDelay, initialDelay); return true; } - - public long getDeadTime() { - return MapUtils.getLong(confMap, KEY_deadTime, DEFAULT_deadTime); // TODO + + public long deadTime() { + return MapUtils.getLong(confMap, KEY_deadTime, DEFAULT_deadTime); } - - public boolean setDeadTime(long deadTime) { - if(deadTime == getDeadTime()) { + + public boolean deadTime(long deadTime) { + if(deadTime == deadTime()) { return false; } confMap.put(KEY_deadTime, deadTime); return true; } - public boolean getIgnoreExecRequestWhenRunning(){ - return MapUtils.getBoolean(confMap, KEY_ignoreExecRequestWhenRunning, DEFAULT_ignoreExecRequestWhenRunning); + public boolean ignoreExecWhenRunning(){ + return MapUtils.getBoolean(confMap, KEY_ignoreExecWhenRunning, DEFAULT_ignoreExecWhenRunning); } - public boolean setIgnoreExecRequestWhenRunning(boolean ignoreExecRequestWhenRunning){ - if(ignoreExecRequestWhenRunning == getIgnoreExecRequestWhenRunning()){ + public boolean ignoreExecWhenRunning(boolean ignoreExecWhenRunning){ + if(ignoreExecWhenRunning == ignoreExecWhenRunning()){ return false; } - confMap.put(KEY_ignoreExecRequestWhenRunning, ignoreExecRequestWhenRunning); + confMap.put(KEY_ignoreExecWhenRunning, ignoreExecWhenRunning); return true; } - public int getQueueSize(){ + public int queueSize(){ return MapUtils.getIntValue(confMap, KEY_queueSize, DEFAULT_queueSize); } - boolean setQueueSize(int queueSize){ + boolean queueSize(int queueSize){ Assert.isTrue(queueSize >= 1, buildMsg(KEY_queueSize, " cannot be less than 1")); - if(queueSize == getQueueSize()){ + if(queueSize == queueSize()){ return false; } confMap.put(KEY_queueSize, queueSize); @@ -583,7 +554,7 @@ Map getWaitingTasks(){ return map; } Object[] array = pool.getQueue().toArray(); - if(array == null || array.length == 0){ + if(array.length == 0){ return map; } @@ -635,7 +606,7 @@ Set saveConfig(HashMap map){ if(list != null){ envirmentFieldChange.addAll(list); } - + // 保存配置的时候,尽量按照不改变原配置值的类型 Object oldValue = confMap.get(key); if(oldValue != null){ @@ -667,33 +638,31 @@ Set saveConfig(HashMap map){ private void saveInternalConfig(String key, Object value){ switch(key){ case KEY_cron: - setCron(value.toString()); return; + cron(value.toString()); return; case KEY_fixedRate: - setFixedRate(Long.valueOf(value.toString())); return; + fixedRate(Long.valueOf(value.toString())); return; case KEY_fixedDelay: - setFixedDelay(Long.valueOf(value.toString())); return; + fixedDelay(Long.valueOf(value.toString())); return; case KEY_remark: - setRemark(value.toString()); return; + remark(value.toString()); return; case KEY_threadCore: - setThreadCore(Integer.valueOf(value.toString())); return; + threadCore(Integer.valueOf(value.toString())); return; case KEY_threadMax: - setThreadMax(Integer.valueOf(value.toString())); return; + threadMax(Integer.valueOf(value.toString())); return; case KEY_threadAliveTime: - setThreadAliveTime(Integer.valueOf(value.toString())); return; + threadAliveTime(Integer.valueOf(value.toString())); return; case KEY_taskOverTime: - setTaskOverTime(Integer.valueOf(value.toString())); return; + taskOverTime(Integer.valueOf(value.toString())); return; case KEY_detectTimeoutOnEachTask: - setDetectTimeoutOnEachTask(Boolean.valueOf(value.toString())); return; - case KEY_ignoreExecRequestWhenRunning: - setIgnoreExecRequestWhenRunning(Boolean.valueOf(value.toString())); return; + detectTimeoutOnEachTask(Boolean.valueOf(value.toString())); return; + case KEY_ignoreExecWhenRunning: + ignoreExecWhenRunning(Boolean.valueOf(value.toString())); return; case KEY_enableTaskConflict: - setEnableTaskConflict(Boolean.valueOf(value.toString())); return; + enableTaskConflict(Boolean.valueOf(value.toString())); return; case KEY_queueSize: - setQueueSize(Integer.valueOf(value.toString())); return; + queueSize(Integer.valueOf(value.toString())); return; case KEY_execOnLoad: - setExecOnLoad(Boolean.valueOf(value.toString())); return; - case KEY_enable: - setEnable(Boolean.valueOf(value.toString())); return; + execOnLoad(Boolean.valueOf(value.toString())); return; default: throw new UnsupportedOperationException("config[" + key + "] cannot be change"); } diff --git a/src/main/java/org/springframework/fom/ScheduleContext.java b/src/main/java/org/springframework/fom/ScheduleContext.java index 7db3719..de834fb 100644 --- a/src/main/java/org/springframework/fom/ScheduleContext.java +++ b/src/main/java/org/springframework/fom/ScheduleContext.java @@ -17,11 +17,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -49,10 +45,10 @@ public class ScheduleContext implements ScheduleFactory, CompleteHandler, ResultHandler, TerminateHandler, TaskCancelHandler, ApplicationContextAware { // 所有schedule共用,以便根据id检测任务冲突 - private static Map>> submitMap = new HashMap<>(512); + private static final Map>> submitMap = new HashMap<>(512); // 当前提交的任务Future - private List>> submitFutures = new ArrayList<>(); + private final List>> submitFutures = new ArrayList<>(); private final ScheduleConfig scheduleConfig = new ScheduleConfig(); @@ -74,7 +70,7 @@ public class ScheduleContext implements ScheduleFactory, CompleteHandler> newSchedulTasks() throws Exception { + public Collection> newScheduleTasks() throws Exception { ScheduleContext scheduleContext; if(applicationContext != null && (scheduleContext = (ScheduleContext)applicationContext.getBean(scheduleName)) != null && scheduleContext.getClass() != this.getClass()){ - return scheduleContext.newSchedulTasks(); + return scheduleContext.newScheduleTasks(); } Task task = schedul(); @@ -238,10 +234,10 @@ public FomEntity scheduleStart(){ case INITED: case STOPPED: if(scheduleConfig.getPool().isTerminated()){ - scheduleConfig.refresh(); + scheduleConfig.refresh(scheduleBeanName); } - enableTaskConflict = scheduleConfig.getEnableTaskConflict(); // 启动时读取一次,init时也读取一次 + enableTaskConflict = scheduleConfig.enableTaskConflict(); // 启动时读取一次,init时也读取一次 scheduleThread = new ScheduleThread(); scheduleThread.start(); logger.info("schedule[{}] startup", scheduleName); @@ -298,7 +294,7 @@ public FomEntity scheduleRun(){ logger.warn("schedule[{}] is stopping, cann't execut now.", scheduleName); return FomEntity.instance(501, "schedule[" + scheduleName + "] is stopping, cann't execut now."); case RUNNING: - if(scheduleConfig.getIgnoreExecRequestWhenRunning()){ + if(scheduleConfig.ignoreExecWhenRunning()){ logger.warn("schedule[{}] is already running.", scheduleName); return FomEntity.instance(501, "schedule[" + scheduleName + "] is already running."); }else{ @@ -340,8 +336,8 @@ public void run() { return; } - if(scheduleConfig.getDeadTime() != ScheduleConfig.DEFAULT_deadTime - && scheduleConfig.getDeadTime() < System.currentTimeMillis()) { + if(scheduleConfig.deadTime() != ScheduleConfig.DEFAULT_deadTime + && scheduleConfig.deadTime() < System.currentTimeMillis()) { logger.info("schedule[{}] is going to shutdown due to deadTime", scheduleName); terminate(); return; @@ -350,10 +346,10 @@ public void run() { try{ if(isFirstRun){ isFirstRun = false; - if(scheduleConfig.getExecOnLoad()) { + if(scheduleConfig.execOnLoad()) { runSchedul(); - }else if(scheduleConfig.getInitialDelay() != ScheduleConfig.DEFAULT_initialDelay) { - sleep(scheduleConfig.getInitialDelay()); + }else if(scheduleConfig.initialDelay() != ScheduleConfig.DEFAULT_initialDelay) { + sleep(scheduleConfig.initialDelay()); runSchedul(); }else { caculateNextTime(null); @@ -396,20 +392,20 @@ private void caculateNextTime(CompleteLatch completeLatch) { last = new Date(lastTime); } - if(scheduleConfig.getCron() != null){ + if(scheduleConfig.cronExpression() != null){ if(!nextTimeHasSated.compareAndSet(true, false)){ - nextTime = scheduleConfig.getCron().getTimeAfter(last).getTime(); + nextTime = scheduleConfig.cronExpression().getTimeAfter(last).getTime(); } waitTaskCompleted(completeLatch); - }else if(scheduleConfig.getFixedRate() > 0){ + }else if(scheduleConfig.fixedRate() > 0){ if(!nextTimeHasSated.compareAndSet(true, false)){ - nextTime = last.getTime() + scheduleConfig.getFixedRate(); + nextTime = last.getTime() + scheduleConfig.fixedRate(); } waitTaskCompleted(completeLatch); - }else if(scheduleConfig.getFixedDelay() > 0){ + }else if(scheduleConfig.fixedDelay() > 0){ waitTaskCompleted(completeLatch); if(!nextTimeHasSated.compareAndSet(true, false)){ - nextTime = System.currentTimeMillis() + scheduleConfig.getFixedDelay(); + nextTime = System.currentTimeMillis() + scheduleConfig.fixedDelay(); } }else{ waitTaskCompleted(completeLatch); @@ -423,8 +419,8 @@ private void waitTaskCompleted(CompleteLatch completeLatch){ return; } - int overTime = scheduleConfig.getTaskOverTime(); - boolean detectTimeoutOnEachTask = scheduleConfig.getDetectTimeoutOnEachTask(); + int overTime = scheduleConfig.taskOverTime(); + boolean detectTimeoutOnEachTask = scheduleConfig.detectTimeoutOnEachTask(); try { if(ScheduleConfig.DEFAULT_taskOverTime == overTime){ // 默认不检测超时 completeLatch.waitTaskCompleted(); @@ -437,14 +433,14 @@ private void waitTaskCompleted(CompleteLatch completeLatch){ long cost = 0; if(startTime > 0){ cost = System.currentTimeMillis() - future.getStartTime(); - logger.info("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); + logger.warn("cancle task[{}] due to time out, cost={}ms", future.getTaskId(), cost); try{ handleCancel(future.getTaskId(), cost); }catch(Exception e){ logger.error("", e); } }else{ - logger.info("cancle task[{}] which has not started, cost={}ms", future.getTaskId(), cost); + logger.warn("cancle task[{}] which has not started, cost={}ms", future.getTaskId(), cost); } cancleTask(future, cost); } @@ -497,7 +493,7 @@ private void waitTaskFuture(TimedFuture> future, DelayQueue completeLatch = new CompleteLatch<>(true, schedulTimes, lastTime); + CompleteLatch completeLatch = new CompleteLatch<>(true, scheduleTimes.get(), lastTime); try{ - Collection> tasks = newSchedulTasks(); + Collection> tasks = newScheduleTasks(); if(tasks == null || tasks.isEmpty()){ return; } @@ -583,7 +579,7 @@ private void terminate() { scheduleConfig.getPool().shutdown(); if(waitShutDown()){ try{ - onTerminate(schedulTimes, lastTime); + onTerminate(scheduleTimes.get(), lastTime); }catch(Exception e){ logger.error("", e); } @@ -613,7 +609,7 @@ private boolean waitShutDown(){ logger.error("", e); } - logger.info("cancle task[{}] due to terminate, cost={}ms", future.getTaskId(), cost); + logger.warn("cancle task[{}] due to terminate, cost={}ms", future.getTaskId(), cost); cancleTask(future, cost); } } @@ -654,7 +650,7 @@ public Future> submit(Task task) { task.setScheduleContext(ScheduleContext.this); TimedFuture> future = - scheduleConfig.getPool().submit(task, scheduleConfig.getTaskOverTime(), scheduleConfig.getEnableTaskConflict()); + scheduleConfig.getPool().submit(task, scheduleConfig.taskOverTime(), scheduleConfig.enableTaskConflict()); if(task.getCompleteLatch() != null){ task.getCompleteLatch().increaseTaskNotCompleted(); } @@ -682,9 +678,9 @@ public void submitBatch(Collection> tasks) { futureList = submitWithNoConflict(tasks, completeLatch); } - long overTime = scheduleConfig.getTaskOverTime(); + long overTime = scheduleConfig.taskOverTime(); if(ScheduleConfig.DEFAULT_taskOverTime != overTime){ - DelayedThread.detectTimeout(futureList, scheduleConfig.getDetectTimeoutOnEachTask()); + DelayedThread.detectTimeout(futureList, scheduleConfig.detectTimeoutOnEachTask()); } }finally{ completeLatch.submitCompleted(); @@ -896,7 +892,7 @@ public void saveConfig(HashMap map, boolean valueEnvirment) thro } protected void record(Result result){ - scheduleStatistics.record(result); + scheduleStatistics.record(scheduleBeanName, result); try{ handleResult(result); }catch(Exception e){ diff --git a/src/main/java/org/springframework/fom/ScheduleInfo.java b/src/main/java/org/springframework/fom/ScheduleInfo.java index f5ad6ba..736f1fd 100644 --- a/src/main/java/org/springframework/fom/ScheduleInfo.java +++ b/src/main/java/org/springframework/fom/ScheduleInfo.java @@ -9,84 +9,84 @@ import java.util.Map.Entry; /** - * + * * @author shanhm1991@163.com * */ public class ScheduleInfo { - + private final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private final String scheduleName; private final String scheduleBeanName; - + private final String state; - + private final String stateTitile; - + private final String stateImage; - + private final long scheduleTimes; - + private final String loadTime; - + private final String lastTime; - + private final String nextTime; - + private final long success; - + private final long failed; - + private final int waiting; - + private final long active; - + private final List config = new ArrayList<>(); - + private final String loggerName; - + private String loggerLevel; - + public ScheduleInfo(ScheduleContext scheduleContext){ this.scheduleName = scheduleContext.getScheduleName(); this.scheduleBeanName = scheduleContext.getScheduleBeanName(); - this.scheduleTimes = scheduleContext.getSchedulTimes(); + this.scheduleTimes = scheduleContext.getScheduleTimes(); this.loadTime = dateFormat.format(scheduleContext.getLoadTime()); - + if(0 == scheduleContext.getLastTime()){ this.lastTime = ""; }else{ this.lastTime = dateFormat.format(scheduleContext.getLastTime()); } - + if(0 == scheduleContext.getNextTime()){ this.nextTime = ""; }else{ this.nextTime = dateFormat.format(scheduleContext.getNextTime()); } - + this.loggerName = scheduleContext.getLogger().getName(); - + State state = scheduleContext.getState(); this.state = state.name(); this.stateTitile = state.title(); this.stateImage = state.src(); - + ScheduleStatistics scheduleStatistics = scheduleContext.getScheduleStatistics(); this.success = scheduleStatistics.getSuccess(); this.failed = scheduleStatistics.getFailed(); - + ScheduleConfig scheduleConfig = scheduleContext.getScheduleConfig(); this.waiting = scheduleConfig.getWaitings(); this.active = scheduleConfig.getActives(); - + Map configMap = new HashMap<>(); configMap.putAll(scheduleConfig.getConfMap()); - + Map internalConf = ScheduleConfig.getInternalConf(); - + // 内部配置 for(String key : internalConf.keySet()){ Object defaultVal = internalConf.get(key); @@ -95,33 +95,33 @@ public ScheduleInfo(ScheduleContext scheduleContext){ config.add(new Conf(key, defaultVal, true, false, true, false)); }else{ if(ScheduleConfig.KEY_cron.equals(key)){ - config.add(new Conf(key, scheduleConfig.getCronExpression(), true, false, false, false)); + config.add(new Conf(key, scheduleConfig.cron(), true, false, false, false)); }else{ config.add(new Conf(key, val, true, false, false, false)); } } } - + // 自定义配置 已经环境变量 for(Entry entry : configMap.entrySet()){ config.add(new Conf(entry.getKey(), entry.getValue(), false, false, false, false)); } } - + public static class Conf{ - + private boolean internal = false; - + private boolean onlyRead = false; - + private boolean envirment = false; - + private boolean defaultValue = false; - + private final String key; - + private final Object value; - + public Conf(String key, Object value, boolean internal, boolean onlyRead, boolean defaultValue, boolean envirment){ this.key = key; this.value = value; @@ -130,7 +130,7 @@ public Conf(String key, Object value, boolean internal, boolean onlyRead, boolea this.envirment = envirment; this.defaultValue = defaultValue; } - + public boolean isInternal() { return internal; } @@ -167,7 +167,7 @@ public String getScheduleBeanName() { public String getState() { return state; } - + public String getLoadTime() { return loadTime; } @@ -211,7 +211,7 @@ public long getWaiting() { public long getActive() { return active; } - + public String getStateTitile() { return stateTitile; } @@ -219,7 +219,7 @@ public String getStateTitile() { public String getStateImage() { return stateImage; } - + public List getConfig() { return config; } diff --git a/src/main/java/org/springframework/fom/ScheduleStatistics.java b/src/main/java/org/springframework/fom/ScheduleStatistics.java index ca3ee47..e2cac1d 100644 --- a/src/main/java/org/springframework/fom/ScheduleStatistics.java +++ b/src/main/java/org/springframework/fom/ScheduleStatistics.java @@ -21,7 +21,7 @@ import org.springframework.util.Assert; /** - * + * * @author shanhm1991@163.com * */ @@ -93,11 +93,11 @@ private Map>> copy(Map result){ + void record(String scheduleName, Result result){ if(result.isSuccess()){ record(result, success, successMap); }else{ - record(result, failed, failedMap); + record(result, failed, failedMap); } } @@ -107,14 +107,14 @@ private void record(Result result, AtomicLong count, Map> queue = statMap.get(day); // 尽量避免使用同步,虽然api中免不了也有同步的使用 - if(queue == null){ + if(queue == null){ queue = new ConcurrentLinkedQueue<>(); ConcurrentLinkedQueue> exist = statMap.putIfAbsent(day, queue); if(exist == null){ - // dayHasSaved由每天第一个放入queue的线程负责检测,不存在多线程访问场景 + // dayHasSaved由每天第一个放入queue的线程负责检测,不存在多线程访问场景 // 虽然每次不是同一个线程访问,但一天只检测一次,线程安全问题暂且忽略 dayHasSaved.add(day); - while(dayHasSaved.size() > statConfigMap.get(STAT_DAY)){ + while(dayHasSaved.size() > statConfigMap.get(STAT_DAY)){ statMap.remove(dayHasSaved.removeLast()); } }else{ @@ -177,7 +177,7 @@ long getFailed() { } // endDay yyyy/MM/dd - Map getSuccessStat(String statDay) throws ParseException { + Map getSuccessStat(String statDay) throws ParseException { int level_1; int level_2; int level_3; @@ -195,12 +195,12 @@ Map getSuccessStat(String statDay) throws ParseException { } Map> statMap = new HashMap<>(); - int countLv1 = 0; - int countLv2 = 0; - int countLv3 = 0; - int countLv4 = 0; - int countLv5 = 0; - int countLv6 = 0; + int countLv1 = 0; + int countLv2 = 0; + int countLv3 = 0; + int countLv4 = 0; + int countLv5 = 0; + int countLv6 = 0; long min = 0; long max = 0; long total = 0; @@ -210,12 +210,12 @@ Map getSuccessStat(String statDay) throws ParseException { String day = entry.getKey(); Queue> queue = entry.getValue(); - int dayCountLv1 = 0; - int dayCountLv2 = 0; - int dayCountLv3 = 0; - int dayCountLv4 = 0; - int dayCountLv5 = 0; - int dayCountLv6 = 0; + int dayCountLv1 = 0; + int dayCountLv2 = 0; + int dayCountLv3 = 0; + int dayCountLv4 = 0; + int dayCountLv5 = 0; + int dayCountLv6 = 0; long dayMin = 0; long datMax = 0; long dayTotal = 0; @@ -331,12 +331,12 @@ Map getSuccessStat(String statDay) throws ParseException { successMap.put("day" + i, dayMap); calendar.add(Calendar.DAY_OF_MONTH, -1); - statDay = dateFormata.format(calendar.getTime()); + statDay = dateFormata.format(calendar.getTime()); } return successMap; } - List> getFailedStat() { + List> getFailedStat() { List> failes = new ArrayList<>(); DateFormat dateFormata = new SimpleDateFormat("yyyyMMdd HH:mm:ss SSS"); @@ -351,7 +351,7 @@ List> getFailedStat() { for(Result result : queue){ Map map = new HashMap<>(); map.put("id", result.getTaskId()); - map.put("submitTime", dateFormata.format(result.getSubmitTime())); + map.put("submitTime", dateFormata.format(result.getSubmitTime())); map.put("startTime", dateFormata.format(result.getStartTime())); map.put("costTime", result.getCostTime() + "ms"); @@ -365,7 +365,7 @@ List> getFailedStat() { } StringBuilder builder = new StringBuilder(throwable.toString()).append(":
"); - for(StackTraceElement stack : throwable.getStackTrace()){ + for(StackTraceElement stack : throwable.getStackTrace()){ builder.append(stack).append("
"); } map.put("cause", builder.toString()); diff --git a/src/main/java/org/springframework/fom/Task.java b/src/main/java/org/springframework/fom/Task.java index 7ef68be..87dff1d 100644 --- a/src/main/java/org/springframework/fom/Task.java +++ b/src/main/java/org/springframework/fom/Task.java @@ -5,7 +5,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.fom.ScheduleContext.CompleteLatch; -import org.springframework.util.StringUtils; /** * @@ -48,7 +47,6 @@ public static ScheduleContext getCurrentSchedule(){ @Override public final Result call() throws InterruptedException { - Thread.currentThread().setName("schedule[" + id + "]"); localSchedule.set(scheduleContext); logger.debug("task started."); @@ -66,7 +64,11 @@ public final Result call() throws InterruptedException { } if(result.isSuccess()){ - logger.debug("task success, cost={}ms, restult={}", result.getCostTime(), result.getContent()); + if(result.getContent() != null){ + logger.debug("{} complete {}ms {}", id, result.getCostTime(), result.getContent()); + }else{ + logger.debug("{} complete {}ms", id, result.getCostTime()); + } }else{ Throwable e = null; if(result.getThrowable() != null){ @@ -77,7 +79,11 @@ public final Result call() throws InterruptedException { } e = throwable; } - logger.error("task failed, cost={}ms, restult={}", result.getCostTime(), result.getContent(), e); + if(result.getContent() != null){ + logger.error("{} failed {}ms {}", id, result.getCostTime(), result.getContent(), e); + }else{ + logger.error("{} failed {}ms", id, result.getCostTime(), e); + } } return result; } @@ -98,6 +104,7 @@ private void doCall(Result result){ }catch(Throwable e) { logger.error("", e); } + localSchedule.remove(); } } diff --git a/src/main/java/org/springframework/fom/annotation/Fom.java b/src/main/java/org/springframework/fom/annotation/Fom.java index 5cb282b..62df4d9 100644 --- a/src/main/java/org/springframework/fom/annotation/Fom.java +++ b/src/main/java/org/springframework/fom/annotation/Fom.java @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component; /** - * + * * @author shanhm1991@163.com * */ @@ -20,152 +20,142 @@ @Documented @Component public @interface Fom { - + @AliasFor(annotation = Component.class) String value() default ""; - - /** - * 加载时是否启动 - */ - boolean enable() default ScheduleConfig.DEFAULT_enable; - + /** - * 加载时是否启动 + * 是否自动加载 */ - String enableString() default ""; - + boolean autoLoad() default true; + /** - * 启动时是否立即执行 + * 加载后是否立即执行 */ boolean execOnLoad() default ScheduleConfig.DEFAULT_execOnLoad; - + /** - * 启动时是否立即执行 + * 加载后是否立即执行 */ String execOnLoadString() default ""; - + /** * 计划表 */ String cron() default ""; - + /** * 距上一次任务开始时的时间[ms] */ long fixedRate() default ScheduleConfig.DEFAULT_fixedRate; - + /** * 距上一次任务开始时的时间[ms] */ String fixedRateString() default ""; - + /** * 距上一次任务结束时的时间[ms] */ long fixedDelay() default ScheduleConfig.DEFAULT_fixedDelay; - + /** * 距上一次任务结束时的时间[ms] */ String fixedDelayString() default ""; - + /** * 核心线程数 */ int threadCore() default ScheduleConfig.DEFAULT_threadCore; - + /** * 核心线程数 */ String threadCoreString() default ""; - + /** * 最大线程数 */ int threadMax() default ScheduleConfig.DEFAULT_threadCore; - + /** * 最大线程数 */ String threadMaxString() default ""; - + /** * 线程最大空闲时间[ms] */ int threadAliveTime() default ScheduleConfig.DEFAULT_threadAliveTime; - + /** * 线程最大空闲时间[ms] */ String threadAliveTimeString() default ""; - + /** * 队列长度 */ int queueSize() default ScheduleConfig.DEFAULT_queueSize; - + /** * 队列长度 */ String queueSizeString() default ""; - + /** * 任务超时时间[ms] */ int taskOverTime() default ScheduleConfig.DEFAULT_taskOverTime; - + /** * 任务超时时间[ms] */ String taskOverTimeString() default ""; - + /** * 是否对每个任务单独检测超时 */ boolean detectTimeoutOnEachTask() default ScheduleConfig.DEFAULT_detectTimeoutOnEachTask; - + /** * 是否对每个任务单独检测超时 */ String detectTimeoutOnEachTaskString() default ""; - + /** * 是否检测任务冲突 */ - boolean enableTaskConflict() default ScheduleConfig.DEFAULT_enableTaskConflict; - + boolean enableTaskConflict() default ScheduleConfig.DEFAULT_enableTaskConflict; + /** * 是否检测任务冲突 */ String enableTaskConflictString() default ""; - + /** * Running状态时是否忽略执行请求 */ - boolean ignoreExecRequestWhenRunning() default ScheduleConfig.DEFAULT_ignoreExecRequestWhenRunning; - + boolean ignoreExecWhenRunning() default ScheduleConfig.DEFAULT_ignoreExecWhenRunning; + /** * Running状态时是否忽略执行请求 */ - String ignoreExecRequestWhenRunningString() default ""; - + String ignoreExecWhenRunningString() default ""; + /** * 备注 */ String remark() default ""; - - /** - * 是否外部加载 - */ - boolean external() default false; - + /** * 首次执行延迟时间[ms] */ long initialDelay() default ScheduleConfig.DEFAULT_initialDelay; - + /** - * 任务截止时间[ms] + * 任务截止时间[ms] */ long deadTime() default ScheduleConfig.DEFAULT_deadTime; } diff --git a/src/main/java/org/springframework/fom/logging/SLF4JBridgeHandler.java b/src/main/java/org/springframework/fom/logging/SLF4JBridgeHandler.java index 1dbece3..903bbfd 100644 --- a/src/main/java/org/springframework/fom/logging/SLF4JBridgeHandler.java +++ b/src/main/java/org/springframework/fom/logging/SLF4JBridgeHandler.java @@ -166,7 +166,7 @@ public static boolean isInstalled() throws SecurityException { */ public static void removeHandlersForRootLogger() { java.util.logging.Logger rootLogger = getRootLogger(); - java.util.logging.Handler[] handlers = rootLogger.getHandlers(); + Handler[] handlers = rootLogger.getHandlers(); for (int i = 0; i < handlers.length; i++) { rootLogger.removeHandler(handlers[i]); } diff --git a/src/main/java/org/springframework/fom/logging/log4j/Log4jAppender.java b/src/main/java/org/springframework/fom/logging/log4j/Log4jAppender.java index fbd6e14..9e42882 100644 --- a/src/main/java/org/springframework/fom/logging/log4j/Log4jAppender.java +++ b/src/main/java/org/springframework/fom/logging/log4j/Log4jAppender.java @@ -41,7 +41,7 @@ public class Log4jAppender extends FileAppender{ private static final long TARDAY = 180; - private static final long FILESIZE = 20 * 1024 * 1024; + private static final long FILESIZE = 20L * 1024 * 1024; private static final int MAXINDEX = 50; diff --git a/src/main/java/org/springframework/fom/proxy/ScheduleFactory.java b/src/main/java/org/springframework/fom/proxy/ScheduleFactory.java index 4b6af8f..e79e69a 100644 --- a/src/main/java/org/springframework/fom/proxy/ScheduleFactory.java +++ b/src/main/java/org/springframework/fom/proxy/ScheduleFactory.java @@ -5,7 +5,7 @@ import org.springframework.fom.Task; /** - * + * * @author shanhm1991@163.com * */ @@ -16,5 +16,5 @@ public interface ScheduleFactory { * @return * @throws Exception */ - Collection> newSchedulTasks() throws Exception; + Collection> newScheduleTasks() throws Exception; } diff --git a/src/main/java/org/springframework/fom/proxy/ScheduleProxy.java b/src/main/java/org/springframework/fom/proxy/ScheduleProxy.java index 3f64d2d..f91f142 100644 --- a/src/main/java/org/springframework/fom/proxy/ScheduleProxy.java +++ b/src/main/java/org/springframework/fom/proxy/ScheduleProxy.java @@ -46,8 +46,8 @@ public Object intercept(Object object, Method method, Object[] args, MethodProxy return onTerminate(object, method, args, methodProxy); }else if("handleCancel".equals(methodName)){ return handleCancel(object, method, args, methodProxy); - }else if("newSchedulTasks".equals(methodName)){ - return newSchedulTasks(object, method, args, methodProxy); + }else if("newScheduleTasks".equals(methodName)){ + return newScheduleTasks(object, method, args, methodProxy); }else if("handleResult".equals(methodName)){ return handleResult(object, method, args, methodProxy); }else{ @@ -108,9 +108,9 @@ private Object handleCancel(Object object, Method method, Object[] args, MethodP return null; } - // TODO 这里应该过滤掉本身自带的方法,比如在newSchedulTasks上添加@Schedule则忽略 + // TODO 这里应该过滤掉本身自带的方法,比如在newScheduleTasks上添加@Schedule则忽略 @SuppressWarnings({ "unchecked", "rawtypes" }) - private Object newSchedulTasks(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable{ + private Object newScheduleTasks(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable{ Class[] parameterTypes = method.getParameterTypes(); if(parameterTypes.length != 0){ return method.invoke(scheduleContext, args); @@ -129,11 +129,12 @@ private Object newSchedulTasks(Object object, Method method, Object[] args, Meth String scheduleName = beanName; if(scheduleName.startsWith("$")){ - scheduleName = scheduleName.substring(1, scheduleName.length() - 1); + scheduleName = scheduleName.substring(1); } for(final Method m : methods){ - Task task = new Task(scheduleName + "-" + m.getName()){ - @Override + Task task = new Task<>(scheduleName + "." + m.getName()) { + + @Override public Object exec() throws Exception { return m.invoke(scheduleContext); } @@ -143,7 +144,7 @@ public Object exec() throws Exception { }else{ if((ScheduleFactory.class.isAssignableFrom(scheduleBeanClass))){ ScheduleFactory scheduleFactory = (ScheduleFactory)scheduleBean; - Collection> collection = (Collection>)scheduleFactory.newSchedulTasks(); + Collection> collection = (Collection>)scheduleFactory.newScheduleTasks(); if(!CollectionUtils.isEmpty(collection)){ tasks.addAll(collection); } @@ -159,10 +160,10 @@ public Object exec() throws Exception { String scheduleName = beanName; if(scheduleName.startsWith("$")){ - scheduleName = scheduleName.substring(1, scheduleName.length() - 1); + scheduleName = scheduleName.substring(1); } for(final Method m : methods){ - Task task = new Task(scheduleName + "-" + m.getName()){ + Task task = new Task<>(scheduleName + "." + m.getName()){ @Override public Object exec() throws Exception { return m.invoke(scheduleBean); diff --git a/src/main/java/org/springframework/fom/quartz/CronExpression.java b/src/main/java/org/springframework/fom/quartz/CronExpression.java index 2bac08c..87b88ed 100644 --- a/src/main/java/org/springframework/fom/quartz/CronExpression.java +++ b/src/main/java/org/springframework/fom/quartz/CronExpression.java @@ -1,18 +1,18 @@ /* * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations * under the License. - * + * */ package org.springframework.fom.quartz; @@ -31,14 +31,14 @@ import java.util.TreeSet; /** - * Provides a parser and evaluator for unix-like cron expressions. Cron + * Provides a parser and evaluator for unix-like cron expressions. Cron * expressions provide the ability to specify complex time combinations such as - * "At 8:00am every Monday through Friday" or "At 1:30am every - * last Friday of the month". + * "At 8:00am every Monday through Friday" or "At 1:30am every + * last Friday of the month". *

* Cron expressions are comprised of 6 required fields and one optional field * separated by white space. The fields respectively are described as follows: - * + * * * * @@ -98,7 +98,7 @@ * *
Field Name
*

- * The '*' character is used to specify all values. For example, "*" + * The '*' character is used to specify all values. For example, "*" * in the minute field means "every minute". *

* The '?' character is allowed for the day-of-month and day-of-week fields. It @@ -113,55 +113,55 @@ * Wednesday, and Friday". *

* The '/' character is used to specify increments. For example "0/15" - * in the seconds field means "the seconds 0, 15, 30, and 45". And + * in the seconds field means "the seconds 0, 15, 30, and 45". And * "5/15" in the seconds field means "the seconds 5, 20, 35, and * 50". Specifying '*' before the '/' is equivalent to specifying 0 is * the value to start with. Essentially, for each field in the expression, there - * is a set of numbers that can be turned on or off. For seconds and minutes, + * is a set of numbers that can be turned on or off. For seconds and minutes, * the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to * 31, and for months 0 to 11 (JAN to DEC). The "/" character simply helps you turn * on every "nth" value in the given set. Thus "7/6" in the - * month field only turns on month "7", it does NOT mean every 6th - * month, please note that subtlety. + * month field only turns on month "7", it does NOT mean every 6th + * month, please note that subtlety. *

* The 'L' character is allowed for the day-of-month and day-of-week fields. - * This character is short-hand for "last", but it has different - * meaning in each of the two fields. For example, the value "L" in - * the day-of-month field means "the last day of the month" - day 31 - * for January, day 28 for February on non-leap years. If used in the - * day-of-week field by itself, it simply means "7" or + * This character is short-hand for "last", but it has different + * meaning in each of the two fields. For example, the value "L" in + * the day-of-month field means "the last day of the month" - day 31 + * for January, day 28 for February on non-leap years. If used in the + * day-of-week field by itself, it simply means "7" or * "SAT". But if used in the day-of-week field after another value, it * means "the last xxx day of the month" - for example "6L" - * means "the last friday of the month". You can also specify an offset - * from the last day of the month, such as "L-3" which would mean the third-to-last - * day of the calendar month. When using the 'L' option, it is important not to + * means "the last friday of the month". You can also specify an offset + * from the last day of the month, such as "L-3" which would mean the third-to-last + * day of the calendar month. When using the 'L' option, it is important not to * specify lists, or ranges of values, as you'll get confusing/unexpected results. *

- * The 'W' character is allowed for the day-of-month field. This character - * is used to specify the weekday (Monday-Friday) nearest the given day. As an - * example, if you were to specify "15W" as the value for the + * The 'W' character is allowed for the day-of-month field. This character + * is used to specify the weekday (Monday-Friday) nearest the given day. As an + * example, if you were to specify "15W" as the value for the * day-of-month field, the meaning is: "the nearest weekday to the 15th of - * the month". So if the 15th is a Saturday, the trigger will fire on + * the month". So if the 15th is a Saturday, the trigger will fire on * Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the - * 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. + * 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. * However if you specify "1W" as the value for day-of-month, and the - * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not - * 'jump' over the boundary of a month's days. The 'W' character can only be + * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not + * 'jump' over the boundary of a month's days. The 'W' character can only be * specified when the day-of-month is a single day, not a range or list of days. *

- * The 'L' and 'W' characters can also be combined for the day-of-month - * expression to yield 'LW', which translates to "last weekday of the + * The 'L' and 'W' characters can also be combined for the day-of-month + * expression to yield 'LW', which translates to "last weekday of the * month". *

* The '#' character is allowed for the day-of-week field. This character is - * used to specify "the nth" XXX day of the month. For example, the - * value of "6#3" in the day-of-week field means the third Friday of - * the month (day 6 = Friday and "#3" = the 3rd one in the month). - * Other examples: "2#1" = the first Monday of the month and + * used to specify "the nth" XXX day of the month. For example, the + * value of "6#3" in the day-of-week field means the third Friday of + * the month (day 6 = Friday and "#3" = the 3rd one in the month). + * Other examples: "2#1" = the first Monday of the month and * "4#5" = the fifth Wednesday of the month. Note that if you specify * "#5" and there is not 5 of the given day-of-week in the month, then * no firing will occur that month. If the '#' character is used, there can - * only be one expression in the day-of-week field ("3#1,6#3" is + * only be one expression in the day-of-week field ("3#1,6#3" is * not valid, since there are two expressions). *

*