├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE ├── PULL_REQUEST_TEMPLATE └── workflows │ └── docker-image.yml ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── doc ├── XXL-JOB-English-Documentation.md ├── XXL-JOB官方文档.md ├── XXL-JOB架构图.pptx ├── db │ └── tables_xxl_job.sql └── images │ ├── cnblog-首页-每日一博-第一.png │ ├── cnblog-首页-热门动弹-第一.png │ ├── donate-alipay.jpg │ ├── donate-paypal.png │ ├── donate-wechat.png │ ├── gitee-gvp.jpg │ ├── img_1001.png │ ├── img_1002.png │ ├── img_6yC0.png │ ├── img_BPLG.png │ ├── img_EB65.png │ ├── img_Fgql.png │ ├── img_Hr2T.png │ ├── img_Qohm.png │ ├── img_UDSo.png │ ├── img_V3vF.png │ ├── img_Wb2o.png │ ├── img_Ypik.png │ ├── img_Z9Qr.png │ ├── img_ZAhX.png │ ├── img_ZAsz.png │ ├── img_dNUJ.png │ ├── img_eYrv.png │ ├── img_hIci.png │ ├── img_iUw0.png │ ├── img_inc8.png │ ├── img_jOAU.png │ ├── img_jrdI.png │ ├── img_o8HQ.png │ ├── img_tJOq.png │ ├── img_tvGI.png │ ├── qq群-一个xxl同学进了58.png │ ├── xxl-logo.jpg │ └── xxl-logo.png ├── pom.xml ├── xxl-job-admin ├── Dockerfile ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xxl │ │ │ └── job │ │ │ └── admin │ │ │ ├── XxlJobAdminApplication.java │ │ │ ├── config │ │ │ └── Config.java │ │ │ ├── controller │ │ │ ├── IndexController.java │ │ │ ├── JobApiController.java │ │ │ ├── JobCodeController.java │ │ │ ├── JobGroupController.java │ │ │ ├── JobInfoController.java │ │ │ ├── JobLogController.java │ │ │ ├── UserController.java │ │ │ ├── annotation │ │ │ │ └── PermissionLimit.java │ │ │ ├── interceptor │ │ │ │ ├── CookieInterceptor.java │ │ │ │ ├── PermissionInterceptor.java │ │ │ │ └── WebMvcConfig.java │ │ │ └── resolver │ │ │ │ └── WebExceptionResolver.java │ │ │ ├── core │ │ │ ├── alarm │ │ │ │ ├── JobAlarm.java │ │ │ │ ├── JobAlarmer.java │ │ │ │ └── impl │ │ │ │ │ └── EmailJobAlarm.java │ │ │ ├── complete │ │ │ │ └── XxlJobCompleter.java │ │ │ ├── conf │ │ │ │ └── XxlJobAdminConfig.java │ │ │ ├── cron │ │ │ │ └── CronExpression.java │ │ │ ├── exception │ │ │ │ └── XxlJobException.java │ │ │ ├── model │ │ │ │ ├── XxlJobGroup.java │ │ │ │ ├── XxlJobInfo.java │ │ │ │ ├── XxlJobLog.java │ │ │ │ ├── XxlJobLogGlue.java │ │ │ │ ├── XxlJobLogReport.java │ │ │ │ ├── XxlJobRegistry.java │ │ │ │ └── XxlJobUser.java │ │ │ ├── old │ │ │ │ ├── RemoteHttpJobBean.java │ │ │ │ ├── XxlJobDynamicScheduler.java │ │ │ │ └── XxlJobThreadPool.java │ │ │ ├── route │ │ │ │ ├── ExecutorRouteStrategyEnum.java │ │ │ │ ├── ExecutorRouter.java │ │ │ │ └── strategy │ │ │ │ │ ├── ExecutorRouteBusyover.java │ │ │ │ │ ├── ExecutorRouteConsistentHash.java │ │ │ │ │ ├── ExecutorRouteFailover.java │ │ │ │ │ ├── ExecutorRouteFirst.java │ │ │ │ │ ├── ExecutorRouteLFU.java │ │ │ │ │ ├── ExecutorRouteLRU.java │ │ │ │ │ ├── ExecutorRouteLast.java │ │ │ │ │ ├── ExecutorRouteRandom.java │ │ │ │ │ └── ExecutorRouteRound.java │ │ │ ├── scheduler │ │ │ │ ├── MisfireStrategyEnum.java │ │ │ │ ├── ScheduleTypeEnum.java │ │ │ │ └── XxlJobScheduler.java │ │ │ ├── thread │ │ │ │ ├── JobCompleteHelper.java │ │ │ │ ├── JobFailMonitorHelper.java │ │ │ │ ├── JobLogReportHelper.java │ │ │ │ ├── JobRegistryHelper.java │ │ │ │ ├── JobScheduleHelper.java │ │ │ │ └── JobTriggerPoolHelper.java │ │ │ ├── trigger │ │ │ │ ├── TriggerTypeEnum.java │ │ │ │ └── XxlJobTrigger.java │ │ │ └── util │ │ │ │ ├── CookieUtil.java │ │ │ │ ├── FtlUtil.java │ │ │ │ ├── I18nUtil.java │ │ │ │ ├── JacksonUtil.java │ │ │ │ └── LocalCacheUtil.java │ │ │ ├── dao │ │ │ ├── XxlJobGroupDao.java │ │ │ ├── XxlJobInfoDao.java │ │ │ ├── XxlJobLogDao.java │ │ │ ├── XxlJobLogGlueDao.java │ │ │ ├── XxlJobLogReportDao.java │ │ │ ├── XxlJobRegistryDao.java │ │ │ └── XxlJobUserDao.java │ │ │ └── service │ │ │ ├── LoginService.java │ │ │ ├── XxlJobService.java │ │ │ └── impl │ │ │ ├── AdminBizImpl.java │ │ │ └── XxlJobServiceImpl.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-docker.properties │ │ ├── application.properties │ │ ├── i18n │ │ ├── message_en.properties │ │ ├── message_zh_CN.properties │ │ └── message_zh_TC.properties │ │ ├── logback.xml │ │ ├── mybatis-mapper │ │ ├── XxlJobGroupMapper.xml │ │ ├── XxlJobInfoMapper.xml │ │ ├── XxlJobLogGlueMapper.xml │ │ ├── XxlJobLogMapper.xml │ │ ├── XxlJobLogReportMapper.xml │ │ ├── XxlJobRegistryMapper.xml │ │ └── XxlJobUserMapper.xml │ │ ├── static │ │ ├── adminlte │ │ │ ├── bower_components │ │ │ │ ├── Ionicons │ │ │ │ │ ├── css │ │ │ │ │ │ └── ionicons.min.css │ │ │ │ │ └── fonts │ │ │ │ │ │ ├── ionicons.eot │ │ │ │ │ │ ├── ionicons.svg │ │ │ │ │ │ ├── ionicons.ttf │ │ │ │ │ │ └── ionicons.woff │ │ │ │ ├── PACE │ │ │ │ │ ├── pace.min.js │ │ │ │ │ └── themes │ │ │ │ │ │ └── blue │ │ │ │ │ │ └── pace-theme-flash.css │ │ │ │ ├── bootstrap-daterangepicker │ │ │ │ │ ├── daterangepicker.css │ │ │ │ │ └── daterangepicker.js │ │ │ │ ├── bootstrap-select │ │ │ │ │ ├── bootstrap-select.min.css │ │ │ │ │ └── bootstrap-select.min.js │ │ │ │ ├── bootstrap │ │ │ │ │ ├── css │ │ │ │ │ │ ├── bootstrap.min.css │ │ │ │ │ │ └── bootstrap.min.css.map │ │ │ │ │ ├── fonts │ │ │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ │ │ └── js │ │ │ │ │ │ └── bootstrap.min.js │ │ │ │ ├── datatables.net-bs │ │ │ │ │ ├── css │ │ │ │ │ │ └── dataTables.bootstrap.min.css │ │ │ │ │ └── js │ │ │ │ │ │ └── dataTables.bootstrap.min.js │ │ │ │ ├── datatables.net │ │ │ │ │ └── js │ │ │ │ │ │ └── jquery.dataTables.min.js │ │ │ │ ├── fastclick │ │ │ │ │ └── fastclick.js │ │ │ │ ├── font-awesome │ │ │ │ │ ├── css │ │ │ │ │ │ ├── font-awesome.css.map │ │ │ │ │ │ └── font-awesome.min.css │ │ │ │ │ └── fonts │ │ │ │ │ │ ├── FontAwesome.otf │ │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ │ ├── jquery-slimscroll │ │ │ │ │ └── jquery.slimscroll.min.js │ │ │ │ ├── jquery │ │ │ │ │ └── jquery.min.js │ │ │ │ └── moment │ │ │ │ │ └── moment.min.js │ │ │ ├── dist │ │ │ │ ├── css │ │ │ │ │ ├── AdminLTE.min.css │ │ │ │ │ └── skins │ │ │ │ │ │ └── _all-skins.min.css │ │ │ │ └── js │ │ │ │ │ └── adminlte.min.js │ │ │ └── plugins │ │ │ │ └── iCheck │ │ │ │ ├── icheck.min.js │ │ │ │ └── square │ │ │ │ ├── blue.css │ │ │ │ ├── blue.png │ │ │ │ └── blue@2x.png │ │ ├── favicon.ico │ │ ├── js │ │ │ ├── common.1.js │ │ │ ├── index.js │ │ │ ├── jobcode.index.1.js │ │ │ ├── jobgroup.index.1.js │ │ │ ├── jobinfo.index.1.js │ │ │ ├── joblog.detail.1.js │ │ │ ├── joblog.index.1.js │ │ │ ├── login.1.js │ │ │ └── user.index.1.js │ │ └── plugins │ │ │ ├── codemirror │ │ │ ├── addon │ │ │ │ └── hint │ │ │ │ │ ├── anyword-hint.js │ │ │ │ │ ├── show-hint.css │ │ │ │ │ └── show-hint.js │ │ │ ├── lib │ │ │ │ ├── codemirror.css │ │ │ │ └── codemirror.js │ │ │ └── mode │ │ │ │ ├── clike │ │ │ │ └── clike.js │ │ │ │ ├── javascript │ │ │ │ └── javascript.js │ │ │ │ ├── php │ │ │ │ └── php.js │ │ │ │ ├── powershell │ │ │ │ └── powershell.js │ │ │ │ ├── python │ │ │ │ └── python.js │ │ │ │ └── shell │ │ │ │ └── shell.js │ │ │ ├── cronGen │ │ │ ├── cronGen.js │ │ │ └── cronGen_en.js │ │ │ ├── echarts │ │ │ └── echarts.common.min.js │ │ │ ├── jquery │ │ │ ├── jquery.cookie.js │ │ │ └── jquery.validate.min.js │ │ │ └── layer │ │ │ ├── layer.js │ │ │ └── theme │ │ │ └── default │ │ │ ├── icon-ext.png │ │ │ ├── icon.png │ │ │ ├── layer.css │ │ │ ├── loading-0.gif │ │ │ ├── loading-1.gif │ │ │ └── loading-2.gif │ │ └── templates │ │ ├── common │ │ ├── common.exception.ftl │ │ └── common.macro.ftl │ │ ├── help.ftl │ │ ├── index.ftl │ │ ├── jobcode │ │ └── jobcode.index.ftl │ │ ├── jobgroup │ │ └── jobgroup.index.ftl │ │ ├── jobinfo │ │ └── jobinfo.index.ftl │ │ ├── joblog │ │ ├── joblog.detail.ftl │ │ └── joblog.index.ftl │ │ ├── login.ftl │ │ └── user │ │ └── user.index.ftl │ └── test │ └── java │ └── com │ └── xxl │ └── job │ ├── admin │ ├── controller │ │ ├── AbstractSpringMvcTest.java │ │ └── JobInfoControllerTest.java │ ├── core │ │ └── util │ │ │ └── JacksonUtilTest.java │ ├── dao │ │ ├── XxlJobGroupDaoTest.java │ │ ├── XxlJobInfoDaoTest.java │ │ ├── XxlJobLogDaoTest.java │ │ ├── XxlJobLogGlueDaoTest.java │ │ └── XxlJobRegistryDaoTest.java │ └── util │ │ └── I18nUtilTest.java │ ├── adminbiz │ └── AdminBizTest.java │ └── executorbiz │ └── ExecutorBizTest.java ├── xxl-job-core ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── xxl │ │ └── job │ │ └── core │ │ ├── biz │ │ ├── AdminBiz.java │ │ ├── ExecutorBiz.java │ │ ├── client │ │ │ ├── AdminBizClient.java │ │ │ └── ExecutorBizClient.java │ │ ├── impl │ │ │ └── ExecutorBizImpl.java │ │ └── model │ │ │ ├── HandleCallbackParam.java │ │ │ ├── IdleBeatParam.java │ │ │ ├── KillParam.java │ │ │ ├── LogParam.java │ │ │ ├── LogResult.java │ │ │ ├── RegistryParam.java │ │ │ ├── ReturnT.java │ │ │ └── TriggerParam.java │ │ ├── config │ │ └── Config.java │ │ ├── context │ │ ├── XxlJobContext.java │ │ └── XxlJobHelper.java │ │ ├── controller │ │ └── XxlJobController.java │ │ ├── enums │ │ ├── ExecutorBlockStrategyEnum.java │ │ └── RegistryConfig.java │ │ ├── executor │ │ ├── XxlJobExecutor.java │ │ └── impl │ │ │ ├── XxlJobSimpleExecutor.java │ │ │ └── XxlJobSpringExecutor.java │ │ ├── glue │ │ ├── GlueFactory.java │ │ ├── GlueTypeEnum.java │ │ └── impl │ │ │ └── SpringGlueFactory.java │ │ ├── handler │ │ ├── IJobHandler.java │ │ ├── annotation │ │ │ ├── JobHandler.java │ │ │ └── XxlJob.java │ │ └── impl │ │ │ ├── GlueJobHandler.java │ │ │ ├── MethodJobHandler.java │ │ │ └── ScriptJobHandler.java │ │ ├── log │ │ └── XxlJobFileAppender.java │ │ ├── server │ │ └── EmbedServer.java │ │ ├── thread │ │ ├── ExecutorRegistryThread.java │ │ ├── JobLogFileCleanThread.java │ │ ├── JobThread.java │ │ └── TriggerCallbackThread.java │ │ └── util │ │ ├── DateUtil.java │ │ ├── FileUtil.java │ │ ├── GsonTool.java │ │ ├── IpUtil.java │ │ ├── JdkSerializeTool.java │ │ ├── NetUtil.java │ │ ├── ScriptUtil.java │ │ ├── ShardingUtil.java │ │ ├── ThrowableUtil.java │ │ └── XxlJobRemotingUtil.java │ └── resources │ └── META-INF │ └── spring.factories └── xxl-job-executor-samples ├── pom.xml ├── xxl-job-executor-sample-frameless ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xxl │ │ │ └── job │ │ │ └── executor │ │ │ └── sample │ │ │ └── frameless │ │ │ ├── FramelessApplication.java │ │ │ ├── config │ │ │ └── FrameLessXxlJobConfig.java │ │ │ └── jobhandler │ │ │ └── SampleXxlJob.java │ └── resources │ │ ├── log4j.xml │ │ └── xxl-job-executor.properties │ └── test │ └── java │ └── com │ └── xxl │ └── job │ └── executor │ └── sample │ └── frameless │ └── test │ └── FramelessApplicationTest.java └── xxl-job-executor-sample-springboot ├── Dockerfile ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── xxl │ │ └── job │ │ └── executor │ │ ├── XxlJobExecutorApplication.java │ │ ├── core │ │ └── config │ │ │ └── XxlJobConfig.java │ │ ├── mvc │ │ └── controller │ │ │ └── IndexController.java │ │ └── service │ │ └── jobhandler │ │ └── SampleXxlJob.java └── resources │ ├── application.properties │ └── logback.xml └── test └── java └── com └── xxl └── job └── executor └── test └── XxlJobExecutorExampleBootApplicationTests.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=Java 2 | *.css linguist-language=Java 3 | *.html linguist-language=Java 4 | *.ftl linguist-language=Java -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.xuxueli.com/page/donate.html'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | Please answer some questions before submitting your issue. Thanks! 2 | 3 | ### Which version of XXL-JOB do you using? 4 | 5 | ### Expected behavior 6 | 7 | ### Actual behavior 8 | 9 | ### Steps to reproduce the behavior 10 | 11 | ### Other information -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE: -------------------------------------------------------------------------------- 1 | **What kind of change does this PR introduce?** (check at least one) 2 | 3 | - [ ] Bugfix 4 | - [ ] Feature 5 | - [ ] Code style update 6 | - [ ] Refactor 7 | - [ ] Build-related changes 8 | - [ ] Other, please describe: 9 | 10 | 11 | **The description of the PR:** 12 | 13 | 14 | **Other information:** -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Set up JDK 1.8 14 | uses: actions/setup-java@v1 15 | with: 16 | java-version: 1.8 17 | - name: Build with Maven 18 | run: mvn clean package -DskipTests 19 | 20 | - name: Build the Docker image 21 | run: | 22 | docker version 23 | # 登录阿里云镜像仓库 24 | docker login --username=${{ secrets.DOCKER_USERNAME }} --password=${{ secrets.DOCKER_PASSWORD }} registry.cn-hangzhou.aliyuncs.com 25 | cd xxl-job-admin 26 | # 使用Dockerfile构建镜像 27 | docker build . --file Dockerfile --tag registry.cn-hangzhou.aliyuncs.com/kdyzm/xxl-job-admin:2.4.2 28 | # 推送镜像到镜像仓库 29 | docker push registry.cn-hangzhou.aliyuncs.com/kdyzm/xxl-job-admin:2.4.2 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .classpath 3 | .project 4 | logs/ 5 | log/ 6 | *.iml 7 | target/ 8 | .DS_Store 9 | .gitattributes 10 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-present, xuxueli. 2 | 3 | Dependencies: 4 | ================================================================ 5 | 6 | Spring: 7 | 8 | * LICENSE: 9 | * http://www.apache.org/licenses/LICENSE-2.0 (Apache License 2.0) 10 | * HOMEPAGE: 11 | * http://www.springsource.org 12 | 13 | Netty: 14 | 15 | * LICENSE: 16 | * http://www.apache.org/licenses/LICENSE-2.0 (Apache License 2.0) 17 | * HOMEPAGE: 18 | * https://github.com/netty/netty 19 | 20 | Hessian: 21 | 22 | * LICENSE: 23 | * http://www.apache.org/licenses/LICENSE-2.0 (Apache License 2.0) 24 | * HOMEPAGE: 25 | * http://hessian.caucho.com 26 | 27 | SLF4J: 28 | 29 | * LICENSE: 30 | * http://www.apache.org/licenses/LICENSE-2.0 (Apache License 2.0) 31 | * HOMEPAGE: 32 | * http://www.slf4j.org 33 | -------------------------------------------------------------------------------- /doc/XXL-JOB架构图.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/XXL-JOB架构图.pptx -------------------------------------------------------------------------------- /doc/images/cnblog-首页-每日一博-第一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/cnblog-首页-每日一博-第一.png -------------------------------------------------------------------------------- /doc/images/cnblog-首页-热门动弹-第一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/cnblog-首页-热门动弹-第一.png -------------------------------------------------------------------------------- /doc/images/donate-alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/donate-alipay.jpg -------------------------------------------------------------------------------- /doc/images/donate-paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/donate-paypal.png -------------------------------------------------------------------------------- /doc/images/donate-wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/donate-wechat.png -------------------------------------------------------------------------------- /doc/images/gitee-gvp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/gitee-gvp.jpg -------------------------------------------------------------------------------- /doc/images/img_1001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_1001.png -------------------------------------------------------------------------------- /doc/images/img_1002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_1002.png -------------------------------------------------------------------------------- /doc/images/img_6yC0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_6yC0.png -------------------------------------------------------------------------------- /doc/images/img_BPLG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_BPLG.png -------------------------------------------------------------------------------- /doc/images/img_EB65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_EB65.png -------------------------------------------------------------------------------- /doc/images/img_Fgql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Fgql.png -------------------------------------------------------------------------------- /doc/images/img_Hr2T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Hr2T.png -------------------------------------------------------------------------------- /doc/images/img_Qohm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Qohm.png -------------------------------------------------------------------------------- /doc/images/img_UDSo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_UDSo.png -------------------------------------------------------------------------------- /doc/images/img_V3vF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_V3vF.png -------------------------------------------------------------------------------- /doc/images/img_Wb2o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Wb2o.png -------------------------------------------------------------------------------- /doc/images/img_Ypik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Ypik.png -------------------------------------------------------------------------------- /doc/images/img_Z9Qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_Z9Qr.png -------------------------------------------------------------------------------- /doc/images/img_ZAhX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_ZAhX.png -------------------------------------------------------------------------------- /doc/images/img_ZAsz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_ZAsz.png -------------------------------------------------------------------------------- /doc/images/img_dNUJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_dNUJ.png -------------------------------------------------------------------------------- /doc/images/img_eYrv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_eYrv.png -------------------------------------------------------------------------------- /doc/images/img_hIci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_hIci.png -------------------------------------------------------------------------------- /doc/images/img_iUw0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_iUw0.png -------------------------------------------------------------------------------- /doc/images/img_inc8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_inc8.png -------------------------------------------------------------------------------- /doc/images/img_jOAU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_jOAU.png -------------------------------------------------------------------------------- /doc/images/img_jrdI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_jrdI.png -------------------------------------------------------------------------------- /doc/images/img_o8HQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_o8HQ.png -------------------------------------------------------------------------------- /doc/images/img_tJOq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_tJOq.png -------------------------------------------------------------------------------- /doc/images/img_tvGI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/img_tvGI.png -------------------------------------------------------------------------------- /doc/images/qq群-一个xxl同学进了58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/qq群-一个xxl同学进了58.png -------------------------------------------------------------------------------- /doc/images/xxl-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/xxl-logo.jpg -------------------------------------------------------------------------------- /doc/images/xxl-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/doc/images/xxl-logo.png -------------------------------------------------------------------------------- /xxl-job-admin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-slim 2 | MAINTAINER xuxueli 3 | 4 | ENV PARAMS="" 5 | 6 | ENV TZ=PRC 7 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 8 | 9 | ADD target/xxl-job-admin-*.jar /app.jar 10 | 11 | ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS -Dspring.profiles.active=$SPRING_PROFILE_ACTIVE /app.jar $PARAMS"] -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author xuxueli 2018-10-28 00:38:13 8 | */ 9 | @SpringBootApplication 10 | public class XxlJobAdminApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(XxlJobAdminApplication.class, args); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/config/Config.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.config; 2 | 3 | import com.alibaba.ttl.threadpool.TtlExecutors; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.concurrent.*; 8 | 9 | /** 10 | * @author kdyzm 11 | * @date 2021/9/16 12 | */ 13 | @Configuration 14 | public class Config { 15 | 16 | /** 17 | * 线程池 18 | */ 19 | /*@Bean 20 | public ExecutorService threadPoolExecutor() { 21 | return TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor( 22 | 8, 23 | 12, 24 | 60L, 25 | TimeUnit.SECONDS, 26 | new ArrayBlockingQueue<>(1000), 27 | Executors.defaultThreadFactory(), 28 | new ThreadPoolExecutor.CallerRunsPolicy() 29 | )); 30 | }*/ 31 | } 32 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobApiController.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller; 2 | 3 | import com.xxl.job.admin.controller.annotation.PermissionLimit; 4 | import com.xxl.job.admin.core.conf.XxlJobAdminConfig; 5 | import com.xxl.job.core.biz.AdminBiz; 6 | import com.xxl.job.core.biz.model.HandleCallbackParam; 7 | import com.xxl.job.core.biz.model.RegistryParam; 8 | import com.xxl.job.core.biz.model.ReturnT; 9 | import com.xxl.job.core.util.GsonTool; 10 | import com.xxl.job.core.util.XxlJobRemotingUtil; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.ResponseBody; 16 | 17 | import javax.annotation.Resource; 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.util.List; 20 | 21 | /** 22 | * Created by xuxueli on 17/5/10. 23 | */ 24 | @Controller 25 | @RequestMapping("/api") 26 | public class JobApiController { 27 | 28 | @Resource 29 | private AdminBiz adminBiz; 30 | 31 | /** 32 | * api 33 | * 34 | * @param uri 35 | * @param data 36 | * @return 37 | */ 38 | @RequestMapping("/{uri}") 39 | @ResponseBody 40 | @PermissionLimit(limit=false) 41 | public ReturnT api(HttpServletRequest request, @PathVariable("uri") String uri, @RequestBody(required = false) String data) { 42 | 43 | // valid 44 | if (!"POST".equalsIgnoreCase(request.getMethod())) { 45 | return new ReturnT(ReturnT.FAIL_CODE, "invalid request, HttpMethod not support."); 46 | } 47 | if (uri==null || uri.trim().length()==0) { 48 | return new ReturnT(ReturnT.FAIL_CODE, "invalid request, uri-mapping empty."); 49 | } 50 | if (XxlJobAdminConfig.getAdminConfig().getAccessToken()!=null 51 | && XxlJobAdminConfig.getAdminConfig().getAccessToken().trim().length()>0 52 | && !XxlJobAdminConfig.getAdminConfig().getAccessToken().equals(request.getHeader(XxlJobRemotingUtil.XXL_JOB_ACCESS_TOKEN))) { 53 | return new ReturnT(ReturnT.FAIL_CODE, "The access token is wrong."); 54 | } 55 | 56 | // services mapping 57 | if ("callback".equals(uri)) { 58 | List callbackParamList = GsonTool.fromJson(data, List.class, HandleCallbackParam.class); 59 | return adminBiz.callback(callbackParamList); 60 | } else if ("registry".equals(uri)) { 61 | RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class); 62 | return adminBiz.registry(registryParam); 63 | } else if ("registryRemove".equals(uri)) { 64 | RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class); 65 | return adminBiz.registryRemove(registryParam); 66 | } else { 67 | return new ReturnT(ReturnT.FAIL_CODE, "invalid request, uri-mapping("+ uri +") not found."); 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/annotation/PermissionLimit.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 权限限制 11 | * @author xuxueli 2015-12-12 18:29:02 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface PermissionLimit { 16 | 17 | /** 18 | * 登录拦截 (默认拦截) 19 | */ 20 | boolean limit() default true; 21 | 22 | /** 23 | * 要求管理员权限 24 | * 25 | * @return 26 | */ 27 | boolean adminuser() default false; 28 | 29 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.interceptor; 2 | 3 | import com.xxl.job.admin.core.util.FtlUtil; 4 | import com.xxl.job.admin.core.util.I18nUtil; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.servlet.ModelAndView; 7 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 8 | 9 | import javax.servlet.http.Cookie; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.util.HashMap; 13 | 14 | /** 15 | * push cookies to model as cookieMap 16 | * 17 | * @author xuxueli 2015-12-12 18:09:04 18 | */ 19 | @Component 20 | public class CookieInterceptor extends HandlerInterceptorAdapter { 21 | 22 | @Override 23 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 24 | ModelAndView modelAndView) throws Exception { 25 | 26 | // cookie 27 | if (modelAndView!=null && request.getCookies()!=null && request.getCookies().length>0) { 28 | HashMap cookieMap = new HashMap(); 29 | for (Cookie ck : request.getCookies()) { 30 | cookieMap.put(ck.getName(), ck); 31 | } 32 | modelAndView.addObject("cookieMap", cookieMap); 33 | } 34 | 35 | // static method 36 | if (modelAndView != null) { 37 | modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName())); 38 | } 39 | 40 | super.postHandle(request, response, handler, modelAndView); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.interceptor; 2 | 3 | import com.xxl.job.admin.controller.annotation.PermissionLimit; 4 | import com.xxl.job.admin.core.model.XxlJobUser; 5 | import com.xxl.job.admin.core.util.I18nUtil; 6 | import com.xxl.job.admin.service.LoginService; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.method.HandlerMethod; 9 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 10 | 11 | import javax.annotation.Resource; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | /** 16 | * 权限拦截 17 | * 18 | * @author xuxueli 2015-12-12 18:09:04 19 | */ 20 | @Component 21 | public class PermissionInterceptor extends HandlerInterceptorAdapter { 22 | 23 | @Resource 24 | private LoginService loginService; 25 | 26 | @Override 27 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 28 | 29 | if (!(handler instanceof HandlerMethod)) { 30 | return super.preHandle(request, response, handler); 31 | } 32 | 33 | // if need login 34 | boolean needLogin = true; 35 | boolean needAdminuser = false; 36 | HandlerMethod method = (HandlerMethod)handler; 37 | PermissionLimit permission = method.getMethodAnnotation(PermissionLimit.class); 38 | if (permission!=null) { 39 | needLogin = permission.limit(); 40 | needAdminuser = permission.adminuser(); 41 | } 42 | 43 | if (needLogin) { 44 | XxlJobUser loginUser = loginService.ifLogin(request, response); 45 | if (loginUser == null) { 46 | response.setStatus(302); 47 | response.setHeader("location", request.getContextPath()+"/toLogin"); 48 | return false; 49 | } 50 | if (needAdminuser && loginUser.getRole()!=1) { 51 | throw new RuntimeException(I18nUtil.getString("system_permission_limit")); 52 | } 53 | request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser); 54 | } 55 | 56 | return super.preHandle(request, response, handler); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.interceptor; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | import javax.annotation.Resource; 8 | 9 | /** 10 | * web mvc config 11 | * 12 | * @author xuxueli 2018-04-02 20:48:20 13 | */ 14 | @Configuration 15 | public class WebMvcConfig implements WebMvcConfigurer { 16 | 17 | @Resource 18 | private PermissionInterceptor permissionInterceptor; 19 | @Resource 20 | private CookieInterceptor cookieInterceptor; 21 | 22 | @Override 23 | public void addInterceptors(InterceptorRegistry registry) { 24 | registry.addInterceptor(permissionInterceptor).addPathPatterns("/**"); 25 | registry.addInterceptor(cookieInterceptor).addPathPatterns("/**"); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/controller/resolver/WebExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.resolver; 2 | 3 | import com.xxl.job.admin.core.exception.XxlJobException; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.admin.core.util.JacksonUtil; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.method.HandlerMethod; 11 | import org.springframework.web.servlet.HandlerExceptionResolver; 12 | import org.springframework.web.servlet.ModelAndView; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | 18 | /** 19 | * common exception resolver 20 | * 21 | * @author xuxueli 2016-1-6 19:22:18 22 | */ 23 | @Component 24 | public class WebExceptionResolver implements HandlerExceptionResolver { 25 | private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class); 26 | 27 | @Override 28 | public ModelAndView resolveException(HttpServletRequest request, 29 | HttpServletResponse response, Object handler, Exception ex) { 30 | 31 | if (!(ex instanceof XxlJobException)) { 32 | logger.error("WebExceptionResolver:{}", ex); 33 | } 34 | 35 | // if json 36 | boolean isJson = false; 37 | if (handler instanceof HandlerMethod) { 38 | HandlerMethod method = (HandlerMethod)handler; 39 | ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class); 40 | if (responseBody != null) { 41 | isJson = true; 42 | } 43 | } 44 | 45 | // error result 46 | ReturnT errorResult = new ReturnT(ReturnT.FAIL_CODE, ex.toString().replaceAll("\n", "
")); 47 | 48 | // response 49 | ModelAndView mv = new ModelAndView(); 50 | if (isJson) { 51 | try { 52 | response.setContentType("application/json;charset=utf-8"); 53 | response.getWriter().print(JacksonUtil.writeValueAsString(errorResult)); 54 | } catch (IOException e) { 55 | logger.error(e.getMessage(), e); 56 | } 57 | return mv; 58 | } else { 59 | 60 | mv.addObject("exceptionMsg", errorResult.getMsg()); 61 | mv.setViewName("/common/common.exception"); 62 | return mv; 63 | } 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/alarm/JobAlarm.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.alarm; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobInfo; 4 | import com.xxl.job.admin.core.model.XxlJobLog; 5 | 6 | /** 7 | * @author xuxueli 2020-01-19 8 | */ 9 | public interface JobAlarm { 10 | 11 | /** 12 | * job alarm 13 | * 14 | * @param info 15 | * @param jobLog 16 | * @return 17 | */ 18 | public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/alarm/JobAlarmer.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.alarm; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobInfo; 4 | import com.xxl.job.admin.core.model.XxlJobLog; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.beans.factory.InitializingBean; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.context.ApplicationContextAware; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | @Component 18 | public class JobAlarmer implements ApplicationContextAware, InitializingBean { 19 | private static Logger logger = LoggerFactory.getLogger(JobAlarmer.class); 20 | 21 | private ApplicationContext applicationContext; 22 | private List jobAlarmList; 23 | 24 | @Override 25 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 26 | this.applicationContext = applicationContext; 27 | } 28 | 29 | @Override 30 | public void afterPropertiesSet() throws Exception { 31 | Map serviceBeanMap = applicationContext.getBeansOfType(JobAlarm.class); 32 | if (serviceBeanMap != null && serviceBeanMap.size() > 0) { 33 | jobAlarmList = new ArrayList(serviceBeanMap.values()); 34 | } 35 | } 36 | 37 | /** 38 | * job alarm 39 | * 40 | * @param info 41 | * @param jobLog 42 | * @return 43 | */ 44 | public boolean alarm(XxlJobInfo info, XxlJobLog jobLog) { 45 | 46 | boolean result = false; 47 | if (jobAlarmList!=null && jobAlarmList.size()>0) { 48 | result = true; // success means all-success 49 | for (JobAlarm alarm: jobAlarmList) { 50 | boolean resultItem = false; 51 | try { 52 | resultItem = alarm.doAlarm(info, jobLog); 53 | } catch (Exception e) { 54 | logger.error(e.getMessage(), e); 55 | } 56 | if (!resultItem) { 57 | result = false; 58 | } 59 | } 60 | } 61 | 62 | return result; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/exception/XxlJobException.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.exception; 2 | 3 | /** 4 | * @author xuxueli 2019-05-04 23:19:29 5 | */ 6 | public class XxlJobException extends RuntimeException { 7 | 8 | public XxlJobException() { 9 | } 10 | public XxlJobException(String message) { 11 | super(message); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Date; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by xuxueli on 16/9/30. 10 | */ 11 | public class XxlJobGroup { 12 | 13 | private int id; 14 | private String appname; 15 | private String title; 16 | private int addressType; // 执行器地址类型:0=自动注册、1=手动录入 17 | private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入) 18 | private Date updateTime; 19 | 20 | // registry list 21 | private List registryList; // 执行器地址列表(系统注册) 22 | public List getRegistryList() { 23 | if (addressList!=null && addressList.trim().length()>0) { 24 | registryList = new ArrayList(Arrays.asList(addressList.split(","))); 25 | } 26 | return registryList; 27 | } 28 | 29 | public int getId() { 30 | return id; 31 | } 32 | 33 | public void setId(int id) { 34 | this.id = id; 35 | } 36 | 37 | public String getAppname() { 38 | return appname; 39 | } 40 | 41 | public void setAppname(String appname) { 42 | this.appname = appname; 43 | } 44 | 45 | public String getTitle() { 46 | return title; 47 | } 48 | 49 | public void setTitle(String title) { 50 | this.title = title; 51 | } 52 | 53 | public int getAddressType() { 54 | return addressType; 55 | } 56 | 57 | public void setAddressType(int addressType) { 58 | this.addressType = addressType; 59 | } 60 | 61 | public String getAddressList() { 62 | return addressList; 63 | } 64 | 65 | public Date getUpdateTime() { 66 | return updateTime; 67 | } 68 | 69 | public void setUpdateTime(Date updateTime) { 70 | this.updateTime = updateTime; 71 | } 72 | 73 | public void setAddressList(String addressList) { 74 | this.addressList = addressList; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLogGlue.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * xxl-job log for glue, used to track job code process 7 | * @author xuxueli 2016-5-19 17:57:46 8 | */ 9 | public class XxlJobLogGlue { 10 | 11 | private int id; 12 | private int jobId; // 任务主键ID 13 | private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum 14 | private String glueSource; 15 | private String glueRemark; 16 | private Date addTime; 17 | private Date updateTime; 18 | 19 | public int getId() { 20 | return id; 21 | } 22 | 23 | public void setId(int id) { 24 | this.id = id; 25 | } 26 | 27 | public int getJobId() { 28 | return jobId; 29 | } 30 | 31 | public void setJobId(int jobId) { 32 | this.jobId = jobId; 33 | } 34 | 35 | public String getGlueType() { 36 | return glueType; 37 | } 38 | 39 | public void setGlueType(String glueType) { 40 | this.glueType = glueType; 41 | } 42 | 43 | public String getGlueSource() { 44 | return glueSource; 45 | } 46 | 47 | public void setGlueSource(String glueSource) { 48 | this.glueSource = glueSource; 49 | } 50 | 51 | public String getGlueRemark() { 52 | return glueRemark; 53 | } 54 | 55 | public void setGlueRemark(String glueRemark) { 56 | this.glueRemark = glueRemark; 57 | } 58 | 59 | public Date getAddTime() { 60 | return addTime; 61 | } 62 | 63 | public void setAddTime(Date addTime) { 64 | this.addTime = addTime; 65 | } 66 | 67 | public Date getUpdateTime() { 68 | return updateTime; 69 | } 70 | 71 | public void setUpdateTime(Date updateTime) { 72 | this.updateTime = updateTime; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLogReport.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.Date; 4 | 5 | public class XxlJobLogReport { 6 | 7 | private int id; 8 | 9 | private Date triggerDay; 10 | 11 | private int runningCount; 12 | private int sucCount; 13 | private int failCount; 14 | 15 | public int getId() { 16 | return id; 17 | } 18 | 19 | public void setId(int id) { 20 | this.id = id; 21 | } 22 | 23 | public Date getTriggerDay() { 24 | return triggerDay; 25 | } 26 | 27 | public void setTriggerDay(Date triggerDay) { 28 | this.triggerDay = triggerDay; 29 | } 30 | 31 | public int getRunningCount() { 32 | return runningCount; 33 | } 34 | 35 | public void setRunningCount(int runningCount) { 36 | this.runningCount = runningCount; 37 | } 38 | 39 | public int getSucCount() { 40 | return sucCount; 41 | } 42 | 43 | public void setSucCount(int sucCount) { 44 | this.sucCount = sucCount; 45 | } 46 | 47 | public int getFailCount() { 48 | return failCount; 49 | } 50 | 51 | public void setFailCount(int failCount) { 52 | this.failCount = failCount; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobRegistry.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Created by xuxueli on 16/9/30. 7 | */ 8 | public class XxlJobRegistry { 9 | 10 | private int id; 11 | private String registryGroup; 12 | private String registryKey; 13 | private String registryValue; 14 | private Date updateTime; 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getRegistryGroup() { 25 | return registryGroup; 26 | } 27 | 28 | public void setRegistryGroup(String registryGroup) { 29 | this.registryGroup = registryGroup; 30 | } 31 | 32 | public String getRegistryKey() { 33 | return registryKey; 34 | } 35 | 36 | public void setRegistryKey(String registryKey) { 37 | this.registryKey = registryKey; 38 | } 39 | 40 | public String getRegistryValue() { 41 | return registryValue; 42 | } 43 | 44 | public void setRegistryValue(String registryValue) { 45 | this.registryValue = registryValue; 46 | } 47 | 48 | public Date getUpdateTime() { 49 | return updateTime; 50 | } 51 | 52 | public void setUpdateTime(Date updateTime) { 53 | this.updateTime = updateTime; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobUser.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import org.springframework.util.StringUtils; 4 | 5 | /** 6 | * @author xuxueli 2019-05-04 16:43:12 7 | */ 8 | public class XxlJobUser { 9 | 10 | private int id; 11 | private String username; // 账号 12 | private String password; // 密码 13 | private int role; // 角色:0-普通用户、1-管理员 14 | private String permission; // 权限:执行器ID列表,多个逗号分割 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getUsername() { 25 | return username; 26 | } 27 | 28 | public void setUsername(String username) { 29 | this.username = username; 30 | } 31 | 32 | public String getPassword() { 33 | return password; 34 | } 35 | 36 | public void setPassword(String password) { 37 | this.password = password; 38 | } 39 | 40 | public int getRole() { 41 | return role; 42 | } 43 | 44 | public void setRole(int role) { 45 | this.role = role; 46 | } 47 | 48 | public String getPermission() { 49 | return permission; 50 | } 51 | 52 | public void setPermission(String permission) { 53 | this.permission = permission; 54 | } 55 | 56 | // plugin 57 | public boolean validPermission(int jobGroup){ 58 | if (this.role == 1) { 59 | return true; 60 | } else { 61 | if (StringUtils.hasText(this.permission)) { 62 | for (String permissionItem : this.permission.split(",")) { 63 | if (String.valueOf(jobGroup).equals(permissionItem)) { 64 | return true; 65 | } 66 | } 67 | } 68 | return false; 69 | } 70 | 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/old/RemoteHttpJobBean.java: -------------------------------------------------------------------------------- 1 | //package com.xxl.job.admin.core.jobbean; 2 | // 3 | //import com.xxl.job.admin.core.thread.JobTriggerPoolHelper; 4 | //import com.xxl.job.admin.core.trigger.TriggerTypeEnum; 5 | //import org.quartz.JobExecutionContext; 6 | //import org.quartz.JobExecutionException; 7 | //import org.quartz.JobKey; 8 | //import org.slf4j.Logger; 9 | //import org.slf4j.LoggerFactory; 10 | //import org.springframework.scheduling.quartz.QuartzJobBean; 11 | // 12 | ///** 13 | // * http job bean 14 | // * “@DisallowConcurrentExecution” disable concurrent, thread size can not be only one, better given more 15 | // * @author xuxueli 2015-12-17 18:20:34 16 | // */ 17 | ////@DisallowConcurrentExecution 18 | //public class RemoteHttpJobBean extends QuartzJobBean { 19 | // private static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class); 20 | // 21 | // @Override 22 | // protected void executeInternal(JobExecutionContext context) 23 | // throws JobExecutionException { 24 | // 25 | // // load jobId 26 | // JobKey jobKey = context.getTrigger().getJobKey(); 27 | // Integer jobId = Integer.valueOf(jobKey.getName()); 28 | // 29 | // 30 | // } 31 | // 32 | //} -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/old/XxlJobThreadPool.java: -------------------------------------------------------------------------------- 1 | //package com.xxl.job.admin.core.quartz; 2 | // 3 | //import org.quartz.SchedulerConfigException; 4 | //import org.quartz.spi.ThreadPool; 5 | // 6 | ///** 7 | // * single thread pool, for async trigger 8 | // * 9 | // * @author xuxueli 2019-03-06 10 | // */ 11 | //public class XxlJobThreadPool implements ThreadPool { 12 | // 13 | // @Override 14 | // public boolean runInThread(Runnable runnable) { 15 | // 16 | // // async run 17 | // runnable.run(); 18 | // return true; 19 | // 20 | // //return false; 21 | // } 22 | // 23 | // @Override 24 | // public int blockForAvailableThreads() { 25 | // return 1; 26 | // } 27 | // 28 | // @Override 29 | // public void initialize() throws SchedulerConfigException { 30 | // 31 | // } 32 | // 33 | // @Override 34 | // public void shutdown(boolean waitForJobsToComplete) { 35 | // 36 | // } 37 | // 38 | // @Override 39 | // public int getPoolSize() { 40 | // return 1; 41 | // } 42 | // 43 | // @Override 44 | // public void setInstanceId(String schedInstId) { 45 | // 46 | // } 47 | // 48 | // @Override 49 | // public void setInstanceName(String schedName) { 50 | // 51 | // } 52 | // 53 | // // support 54 | // public void setThreadCount(int count) { 55 | // // 56 | // } 57 | // 58 | //} 59 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouteStrategyEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route; 2 | 3 | import com.xxl.job.admin.core.route.strategy.*; 4 | import com.xxl.job.admin.core.util.I18nUtil; 5 | 6 | /** 7 | * Created by xuxueli on 17/3/10. 8 | */ 9 | public enum ExecutorRouteStrategyEnum { 10 | 11 | FIRST(I18nUtil.getString("jobconf_route_first"), new ExecutorRouteFirst()), 12 | LAST(I18nUtil.getString("jobconf_route_last"), new ExecutorRouteLast()), 13 | ROUND(I18nUtil.getString("jobconf_route_round"), new ExecutorRouteRound()), 14 | RANDOM(I18nUtil.getString("jobconf_route_random"), new ExecutorRouteRandom()), 15 | CONSISTENT_HASH(I18nUtil.getString("jobconf_route_consistenthash"), new ExecutorRouteConsistentHash()), 16 | LEAST_FREQUENTLY_USED(I18nUtil.getString("jobconf_route_lfu"), new ExecutorRouteLFU()), 17 | LEAST_RECENTLY_USED(I18nUtil.getString("jobconf_route_lru"), new ExecutorRouteLRU()), 18 | FAILOVER(I18nUtil.getString("jobconf_route_failover"), new ExecutorRouteFailover()), 19 | BUSYOVER(I18nUtil.getString("jobconf_route_busyover"), new ExecutorRouteBusyover()), 20 | SHARDING_BROADCAST(I18nUtil.getString("jobconf_route_shard"), null); 21 | 22 | ExecutorRouteStrategyEnum(String title, ExecutorRouter router) { 23 | this.title = title; 24 | this.router = router; 25 | } 26 | 27 | private String title; 28 | private ExecutorRouter router; 29 | 30 | public String getTitle() { 31 | return title; 32 | } 33 | public ExecutorRouter getRouter() { 34 | return router; 35 | } 36 | 37 | public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){ 38 | if (name != null) { 39 | for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) { 40 | if (item.name().equals(name)) { 41 | return item; 42 | } 43 | } 44 | } 45 | return defaultItem; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouter.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route; 2 | 3 | import com.xxl.job.core.biz.model.ReturnT; 4 | import com.xxl.job.core.biz.model.TriggerParam; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by xuxueli on 17/3/10. 12 | */ 13 | public abstract class ExecutorRouter { 14 | protected static Logger logger = LoggerFactory.getLogger(ExecutorRouter.class); 15 | 16 | /** 17 | * route address 18 | * 19 | * @param addressList 20 | * @return ReturnT.content=address 21 | */ 22 | public abstract ReturnT route(TriggerParam triggerParam, List addressList); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteBusyover.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.scheduler.XxlJobScheduler; 4 | import com.xxl.job.admin.core.route.ExecutorRouter; 5 | import com.xxl.job.admin.core.util.I18nUtil; 6 | import com.xxl.job.core.biz.ExecutorBiz; 7 | import com.xxl.job.core.biz.model.IdleBeatParam; 8 | import com.xxl.job.core.biz.model.ReturnT; 9 | import com.xxl.job.core.biz.model.TriggerParam; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Created by xuxueli on 17/3/10. 15 | */ 16 | public class ExecutorRouteBusyover extends ExecutorRouter { 17 | 18 | @Override 19 | public ReturnT route(TriggerParam triggerParam, List addressList) { 20 | StringBuffer idleBeatResultSB = new StringBuffer(); 21 | for (String address : addressList) { 22 | // beat 23 | ReturnT idleBeatResult = null; 24 | try { 25 | ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address); 26 | idleBeatResult = executorBiz.idleBeat(new IdleBeatParam(triggerParam.getJobId())); 27 | } catch (Exception e) { 28 | logger.error(e.getMessage(), e); 29 | idleBeatResult = new ReturnT(ReturnT.FAIL_CODE, ""+e ); 30 | } 31 | idleBeatResultSB.append( (idleBeatResultSB.length()>0)?"

":"") 32 | .append(I18nUtil.getString("jobconf_idleBeat") + ":") 33 | .append("
address:").append(address) 34 | .append("
code:").append(idleBeatResult.getCode()) 35 | .append("
msg:").append(idleBeatResult.getMsg()); 36 | 37 | // beat success 38 | if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) { 39 | idleBeatResult.setMsg(idleBeatResultSB.toString()); 40 | idleBeatResult.setContent(address); 41 | return idleBeatResult; 42 | } 43 | } 44 | 45 | return new ReturnT(ReturnT.FAIL_CODE, idleBeatResultSB.toString()); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteConsistentHash.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.io.UnsupportedEncodingException; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.util.List; 11 | import java.util.SortedMap; 12 | import java.util.TreeMap; 13 | 14 | /** 15 | * 分组下机器地址相同,不同JOB均匀散列在不同机器上,保证分组下机器分配JOB平均;且每个JOB固定调度其中一台机器; 16 | * a、virtual node:解决不均衡问题 17 | * b、hash method replace hashCode:String的hashCode可能重复,需要进一步扩大hashCode的取值范围 18 | * Created by xuxueli on 17/3/10. 19 | */ 20 | public class ExecutorRouteConsistentHash extends ExecutorRouter { 21 | 22 | private static int VIRTUAL_NODE_NUM = 100; 23 | 24 | /** 25 | * get hash code on 2^32 ring (md5散列的方式计算hash值) 26 | * @param key 27 | * @return 28 | */ 29 | private static long hash(String key) { 30 | 31 | // md5 byte 32 | MessageDigest md5; 33 | try { 34 | md5 = MessageDigest.getInstance("MD5"); 35 | } catch (NoSuchAlgorithmException e) { 36 | throw new RuntimeException("MD5 not supported", e); 37 | } 38 | md5.reset(); 39 | byte[] keyBytes = null; 40 | try { 41 | keyBytes = key.getBytes("UTF-8"); 42 | } catch (UnsupportedEncodingException e) { 43 | throw new RuntimeException("Unknown string :" + key, e); 44 | } 45 | 46 | md5.update(keyBytes); 47 | byte[] digest = md5.digest(); 48 | 49 | // hash code, Truncate to 32-bits 50 | long hashCode = ((long) (digest[3] & 0xFF) << 24) 51 | | ((long) (digest[2] & 0xFF) << 16) 52 | | ((long) (digest[1] & 0xFF) << 8) 53 | | (digest[0] & 0xFF); 54 | 55 | long truncateHashCode = hashCode & 0xffffffffL; 56 | return truncateHashCode; 57 | } 58 | 59 | public String hashJob(int jobId, List addressList) { 60 | 61 | // ------A1------A2-------A3------ 62 | // -----------J1------------------ 63 | TreeMap addressRing = new TreeMap(); 64 | for (String address: addressList) { 65 | for (int i = 0; i < VIRTUAL_NODE_NUM; i++) { 66 | long addressHash = hash("SHARD-" + address + "-NODE-" + i); 67 | addressRing.put(addressHash, address); 68 | } 69 | } 70 | 71 | long jobHash = hash(String.valueOf(jobId)); 72 | SortedMap lastRing = addressRing.tailMap(jobHash); 73 | if (!lastRing.isEmpty()) { 74 | return lastRing.get(lastRing.firstKey()); 75 | } 76 | return addressRing.firstEntry().getValue(); 77 | } 78 | 79 | @Override 80 | public ReturnT route(TriggerParam triggerParam, List addressList) { 81 | String address = hashJob(triggerParam.getJobId(), addressList); 82 | return new ReturnT(address); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFailover.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.scheduler.XxlJobScheduler; 4 | import com.xxl.job.admin.core.route.ExecutorRouter; 5 | import com.xxl.job.admin.core.util.I18nUtil; 6 | import com.xxl.job.core.biz.ExecutorBiz; 7 | import com.xxl.job.core.biz.model.ReturnT; 8 | import com.xxl.job.core.biz.model.TriggerParam; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by xuxueli on 17/3/10. 14 | */ 15 | public class ExecutorRouteFailover extends ExecutorRouter { 16 | 17 | @Override 18 | public ReturnT route(TriggerParam triggerParam, List addressList) { 19 | 20 | StringBuffer beatResultSB = new StringBuffer(); 21 | for (String address : addressList) { 22 | // beat 23 | ReturnT beatResult = null; 24 | try { 25 | ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address); 26 | beatResult = executorBiz.beat(); 27 | } catch (Exception e) { 28 | logger.error(e.getMessage(), e); 29 | beatResult = new ReturnT(ReturnT.FAIL_CODE, ""+e ); 30 | } 31 | beatResultSB.append( (beatResultSB.length()>0)?"

":"") 32 | .append(I18nUtil.getString("jobconf_beat") + ":") 33 | .append("
address:").append(address) 34 | .append("
code:").append(beatResult.getCode()) 35 | .append("
msg:").append(beatResult.getMsg()); 36 | 37 | // beat success 38 | if (beatResult.getCode() == ReturnT.SUCCESS_CODE) { 39 | 40 | beatResult.setMsg(beatResultSB.toString()); 41 | beatResult.setContent(address); 42 | return beatResult; 43 | } 44 | } 45 | return new ReturnT(ReturnT.FAIL_CODE, beatResultSB.toString()); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFirst.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 17/3/10. 11 | */ 12 | public class ExecutorRouteFirst extends ExecutorRouter { 13 | 14 | @Override 15 | public ReturnT route(TriggerParam triggerParam, List addressList){ 16 | return new ReturnT(addressList.get(0)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLFU.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.*; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import java.util.concurrent.ConcurrentMap; 10 | 11 | /** 12 | * 单个JOB对应的每个执行器,使用频率最低的优先被选举 13 | * a(*)、LFU(Least Frequently Used):最不经常使用,频率/次数 14 | * b、LRU(Least Recently Used):最近最久未使用,时间 15 | * 16 | * Created by xuxueli on 17/3/10. 17 | */ 18 | public class ExecutorRouteLFU extends ExecutorRouter { 19 | 20 | private static ConcurrentMap> jobLfuMap = new ConcurrentHashMap>(); 21 | private static long CACHE_VALID_TIME = 0; 22 | 23 | public String route(int jobId, List addressList) { 24 | 25 | // cache clear 26 | if (System.currentTimeMillis() > CACHE_VALID_TIME) { 27 | jobLfuMap.clear(); 28 | CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24; 29 | } 30 | 31 | // lfu item init 32 | HashMap lfuItemMap = jobLfuMap.get(jobId); // Key排序可以用TreeMap+构造入参Compare;Value排序暂时只能通过ArrayList; 33 | if (lfuItemMap == null) { 34 | lfuItemMap = new HashMap(); 35 | jobLfuMap.putIfAbsent(jobId, lfuItemMap); // 避免重复覆盖 36 | } 37 | 38 | // put new 39 | for (String address: addressList) { 40 | if (!lfuItemMap.containsKey(address) || lfuItemMap.get(address) >1000000 ) { 41 | lfuItemMap.put(address, new Random().nextInt(addressList.size())); // 初始化时主动Random一次,缓解首次压力 42 | } 43 | } 44 | // remove old 45 | List delKeys = new ArrayList<>(); 46 | for (String existKey: lfuItemMap.keySet()) { 47 | if (!addressList.contains(existKey)) { 48 | delKeys.add(existKey); 49 | } 50 | } 51 | if (delKeys.size() > 0) { 52 | for (String delKey: delKeys) { 53 | lfuItemMap.remove(delKey); 54 | } 55 | } 56 | 57 | // load least userd count address 58 | List> lfuItemList = new ArrayList>(lfuItemMap.entrySet()); 59 | Collections.sort(lfuItemList, new Comparator>() { 60 | @Override 61 | public int compare(Map.Entry o1, Map.Entry o2) { 62 | return o1.getValue().compareTo(o2.getValue()); 63 | } 64 | }); 65 | 66 | Map.Entry addressItem = lfuItemList.get(0); 67 | String minAddress = addressItem.getKey(); 68 | addressItem.setValue(addressItem.getValue() + 1); 69 | 70 | return addressItem.getKey(); 71 | } 72 | 73 | @Override 74 | public ReturnT route(TriggerParam triggerParam, List addressList) { 75 | String address = route(triggerParam.getJobId(), addressList); 76 | return new ReturnT(address); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLRU.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.ArrayList; 8 | import java.util.LinkedHashMap; 9 | import java.util.List; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | import java.util.concurrent.ConcurrentMap; 12 | 13 | /** 14 | * 单个JOB对应的每个执行器,最久为使用的优先被选举 15 | * a、LFU(Least Frequently Used):最不经常使用,频率/次数 16 | * b(*)、LRU(Least Recently Used):最近最久未使用,时间 17 | * 18 | * Created by xuxueli on 17/3/10. 19 | */ 20 | public class ExecutorRouteLRU extends ExecutorRouter { 21 | 22 | private static ConcurrentMap> jobLRUMap = new ConcurrentHashMap>(); 23 | private static long CACHE_VALID_TIME = 0; 24 | 25 | public String route(int jobId, List addressList) { 26 | 27 | // cache clear 28 | if (System.currentTimeMillis() > CACHE_VALID_TIME) { 29 | jobLRUMap.clear(); 30 | CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24; 31 | } 32 | 33 | // init lru 34 | LinkedHashMap lruItem = jobLRUMap.get(jobId); 35 | if (lruItem == null) { 36 | /** 37 | * LinkedHashMap 38 | * a、accessOrder:true=访问顺序排序(get/put时排序);false=插入顺序排期; 39 | * b、removeEldestEntry:新增元素时将会调用,返回true时会删除最老元素;可封装LinkedHashMap并重写该方法,比如定义最大容量,超出是返回true即可实现固定长度的LRU算法; 40 | */ 41 | lruItem = new LinkedHashMap(16, 0.75f, true); 42 | jobLRUMap.putIfAbsent(jobId, lruItem); 43 | } 44 | 45 | // put new 46 | for (String address: addressList) { 47 | if (!lruItem.containsKey(address)) { 48 | lruItem.put(address, address); 49 | } 50 | } 51 | // remove old 52 | List delKeys = new ArrayList<>(); 53 | for (String existKey: lruItem.keySet()) { 54 | if (!addressList.contains(existKey)) { 55 | delKeys.add(existKey); 56 | } 57 | } 58 | if (delKeys.size() > 0) { 59 | for (String delKey: delKeys) { 60 | lruItem.remove(delKey); 61 | } 62 | } 63 | 64 | // load 65 | String eldestKey = lruItem.entrySet().iterator().next().getKey(); 66 | String eldestValue = lruItem.get(eldestKey); 67 | return eldestValue; 68 | } 69 | 70 | @Override 71 | public ReturnT route(TriggerParam triggerParam, List addressList) { 72 | String address = route(triggerParam.getJobId(), addressList); 73 | return new ReturnT(address); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLast.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 17/3/10. 11 | */ 12 | public class ExecutorRouteLast extends ExecutorRouter { 13 | 14 | @Override 15 | public ReturnT route(TriggerParam triggerParam, List addressList) { 16 | return new ReturnT(addressList.get(addressList.size()-1)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRandom.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | /** 11 | * Created by xuxueli on 17/3/10. 12 | */ 13 | public class ExecutorRouteRandom extends ExecutorRouter { 14 | 15 | private static Random localRandom = new Random(); 16 | 17 | @Override 18 | public ReturnT route(TriggerParam triggerParam, List addressList) { 19 | String address = addressList.get(localRandom.nextInt(addressList.size())); 20 | return new ReturnT(address); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRound.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | import java.util.Random; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.ConcurrentMap; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | 13 | /** 14 | * Created by xuxueli on 17/3/10. 15 | */ 16 | public class ExecutorRouteRound extends ExecutorRouter { 17 | 18 | private static ConcurrentMap routeCountEachJob = new ConcurrentHashMap<>(); 19 | private static long CACHE_VALID_TIME = 0; 20 | 21 | private static int count(int jobId) { 22 | // cache clear 23 | if (System.currentTimeMillis() > CACHE_VALID_TIME) { 24 | routeCountEachJob.clear(); 25 | CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24; 26 | } 27 | 28 | AtomicInteger count = routeCountEachJob.get(jobId); 29 | if (count == null || count.get() > 1000000) { 30 | // 初始化时主动Random一次,缓解首次压力 31 | count = new AtomicInteger(new Random().nextInt(100)); 32 | } else { 33 | // count++ 34 | count.addAndGet(1); 35 | } 36 | routeCountEachJob.put(jobId, count); 37 | return count.get(); 38 | } 39 | 40 | @Override 41 | public ReturnT route(TriggerParam triggerParam, List addressList) { 42 | String address = addressList.get(count(triggerParam.getJobId())%addressList.size()); 43 | return new ReturnT(address); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/scheduler/MisfireStrategyEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.scheduler; 2 | 3 | import com.xxl.job.admin.core.util.I18nUtil; 4 | 5 | /** 6 | * @author xuxueli 2020-10-29 21:11:23 7 | */ 8 | public enum MisfireStrategyEnum { 9 | 10 | /** 11 | * do nothing 12 | */ 13 | DO_NOTHING(I18nUtil.getString("misfire_strategy_do_nothing")), 14 | 15 | /** 16 | * fire once now 17 | */ 18 | FIRE_ONCE_NOW(I18nUtil.getString("misfire_strategy_fire_once_now")); 19 | 20 | private String title; 21 | 22 | MisfireStrategyEnum(String title) { 23 | this.title = title; 24 | } 25 | 26 | public String getTitle() { 27 | return title; 28 | } 29 | 30 | public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem){ 31 | for (MisfireStrategyEnum item: MisfireStrategyEnum.values()) { 32 | if (item.name().equals(name)) { 33 | return item; 34 | } 35 | } 36 | return defaultItem; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/scheduler/ScheduleTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.scheduler; 2 | 3 | import com.xxl.job.admin.core.util.I18nUtil; 4 | 5 | /** 6 | * @author xuxueli 2020-10-29 21:11:23 7 | */ 8 | public enum ScheduleTypeEnum { 9 | 10 | NONE(I18nUtil.getString("schedule_type_none")), 11 | 12 | /** 13 | * schedule by cron 14 | */ 15 | CRON(I18nUtil.getString("schedule_type_cron")), 16 | 17 | /** 18 | * schedule by fixed rate (in seconds) 19 | */ 20 | FIX_RATE(I18nUtil.getString("schedule_type_fix_rate")), 21 | 22 | /** 23 | * schedule by fix delay (in seconds), after the last time 24 | */ 25 | /*FIX_DELAY(I18nUtil.getString("schedule_type_fix_delay"))*/; 26 | 27 | private String title; 28 | 29 | ScheduleTypeEnum(String title) { 30 | this.title = title; 31 | } 32 | 33 | public String getTitle() { 34 | return title; 35 | } 36 | 37 | public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem){ 38 | for (ScheduleTypeEnum item: ScheduleTypeEnum.values()) { 39 | if (item.name().equals(name)) { 40 | return item; 41 | } 42 | } 43 | return defaultItem; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/TriggerTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.trigger; 2 | 3 | import com.xxl.job.admin.core.util.I18nUtil; 4 | 5 | /** 6 | * trigger type enum 7 | * 8 | * @author xuxueli 2018-09-16 04:56:41 9 | */ 10 | public enum TriggerTypeEnum { 11 | 12 | MANUAL(I18nUtil.getString("jobconf_trigger_type_manual")), 13 | CRON(I18nUtil.getString("jobconf_trigger_type_cron")), 14 | RETRY(I18nUtil.getString("jobconf_trigger_type_retry")), 15 | PARENT(I18nUtil.getString("jobconf_trigger_type_parent")), 16 | API(I18nUtil.getString("jobconf_trigger_type_api")), 17 | MISFIRE(I18nUtil.getString("jobconf_trigger_type_misfire")); 18 | 19 | private TriggerTypeEnum(String title){ 20 | this.title = title; 21 | } 22 | private String title; 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/CookieUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import javax.servlet.http.Cookie; 4 | import javax.servlet.http.HttpServletRequest; 5 | import javax.servlet.http.HttpServletResponse; 6 | 7 | /** 8 | * Cookie.Util 9 | * 10 | * @author xuxueli 2015-12-12 18:01:06 11 | */ 12 | public class CookieUtil { 13 | 14 | // 默认缓存时间,单位/秒, 2H 15 | private static final int COOKIE_MAX_AGE = Integer.MAX_VALUE; 16 | // 保存路径,根路径 17 | private static final String COOKIE_PATH = "/"; 18 | 19 | /** 20 | * 保存 21 | * 22 | * @param response 23 | * @param key 24 | * @param value 25 | * @param ifRemember 26 | */ 27 | public static void set(HttpServletResponse response, String key, String value, boolean ifRemember) { 28 | int age = ifRemember?COOKIE_MAX_AGE:-1; 29 | set(response, key, value, null, COOKIE_PATH, age, true); 30 | } 31 | 32 | /** 33 | * 保存 34 | * 35 | * @param response 36 | * @param key 37 | * @param value 38 | * @param maxAge 39 | */ 40 | private static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) { 41 | Cookie cookie = new Cookie(key, value); 42 | if (domain != null) { 43 | cookie.setDomain(domain); 44 | } 45 | cookie.setPath(path); 46 | cookie.setMaxAge(maxAge); 47 | cookie.setHttpOnly(isHttpOnly); 48 | response.addCookie(cookie); 49 | } 50 | 51 | /** 52 | * 查询value 53 | * 54 | * @param request 55 | * @param key 56 | * @return 57 | */ 58 | public static String getValue(HttpServletRequest request, String key) { 59 | Cookie cookie = get(request, key); 60 | if (cookie != null) { 61 | return cookie.getValue(); 62 | } 63 | return null; 64 | } 65 | 66 | /** 67 | * 查询Cookie 68 | * 69 | * @param request 70 | * @param key 71 | */ 72 | private static Cookie get(HttpServletRequest request, String key) { 73 | Cookie[] arr_cookie = request.getCookies(); 74 | if (arr_cookie != null && arr_cookie.length > 0) { 75 | for (Cookie cookie : arr_cookie) { 76 | if (cookie.getName().equals(key)) { 77 | return cookie; 78 | } 79 | } 80 | } 81 | return null; 82 | } 83 | 84 | /** 85 | * 删除Cookie 86 | * 87 | * @param request 88 | * @param response 89 | * @param key 90 | */ 91 | public static void remove(HttpServletRequest request, HttpServletResponse response, String key) { 92 | Cookie cookie = get(request, key); 93 | if (cookie != null) { 94 | set(response, key, "", null, COOKIE_PATH, 0, true); 95 | } 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/FtlUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import freemarker.ext.beans.BeansWrapper; 4 | import freemarker.ext.beans.BeansWrapperBuilder; 5 | import freemarker.template.Configuration; 6 | import freemarker.template.TemplateHashModel; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * ftl util 12 | * 13 | * @author xuxueli 2018-01-17 20:37:48 14 | */ 15 | public class FtlUtil { 16 | private static Logger logger = LoggerFactory.getLogger(FtlUtil.class); 17 | 18 | private static BeansWrapper wrapper = new BeansWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build(); //BeansWrapper.getDefaultInstance(); 19 | 20 | public static TemplateHashModel generateStaticModel(String packageName) { 21 | try { 22 | TemplateHashModel staticModels = wrapper.getStaticModels(); 23 | TemplateHashModel fileStatics = (TemplateHashModel) staticModels.get(packageName); 24 | return fileStatics; 25 | } catch (Exception e) { 26 | logger.error(e.getMessage(), e); 27 | } 28 | return null; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/I18nUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import com.xxl.job.admin.core.conf.XxlJobAdminConfig; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.core.io.ClassPathResource; 7 | import org.springframework.core.io.Resource; 8 | import org.springframework.core.io.support.EncodedResource; 9 | import org.springframework.core.io.support.PropertiesLoaderUtils; 10 | 11 | import java.io.IOException; 12 | import java.text.MessageFormat; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Properties; 16 | 17 | /** 18 | * i18n util 19 | * 20 | * @author xuxueli 2018-01-17 20:39:06 21 | */ 22 | public class I18nUtil { 23 | private static Logger logger = LoggerFactory.getLogger(I18nUtil.class); 24 | 25 | private static Properties prop = null; 26 | public static Properties loadI18nProp(){ 27 | if (prop != null) { 28 | return prop; 29 | } 30 | try { 31 | // build i18n prop 32 | String i18n = XxlJobAdminConfig.getAdminConfig().getI18n(); 33 | String i18nFile = MessageFormat.format("i18n/message_{0}.properties", i18n); 34 | 35 | // load prop 36 | Resource resource = new ClassPathResource(i18nFile); 37 | EncodedResource encodedResource = new EncodedResource(resource,"UTF-8"); 38 | prop = PropertiesLoaderUtils.loadProperties(encodedResource); 39 | } catch (IOException e) { 40 | logger.error(e.getMessage(), e); 41 | } 42 | return prop; 43 | } 44 | 45 | /** 46 | * get val of i18n key 47 | * 48 | * @param key 49 | * @return 50 | */ 51 | public static String getString(String key) { 52 | return loadI18nProp().getProperty(key); 53 | } 54 | 55 | /** 56 | * get mult val of i18n mult key, as json 57 | * 58 | * @param keys 59 | * @return 60 | */ 61 | public static String getMultString(String... keys) { 62 | Map map = new HashMap(); 63 | 64 | Properties prop = loadI18nProp(); 65 | if (keys!=null && keys.length>0) { 66 | for (String key: keys) { 67 | map.put(key, prop.getProperty(key)); 68 | } 69 | } else { 70 | for (String key: prop.stringPropertyNames()) { 71 | map.put(key, prop.getProperty(key)); 72 | } 73 | } 74 | 75 | String json = JacksonUtil.writeValueAsString(map); 76 | return json; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/JacksonUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerationException; 4 | import com.fasterxml.jackson.core.JsonParseException; 5 | import com.fasterxml.jackson.databind.JavaType; 6 | import com.fasterxml.jackson.databind.JsonMappingException; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * Jackson util 15 | * 16 | * 1、obj need private and set/get; 17 | * 2、do not support inner class; 18 | * 19 | * @author xuxueli 2015-9-25 18:02:56 20 | */ 21 | public class JacksonUtil { 22 | private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class); 23 | 24 | private final static ObjectMapper objectMapper = new ObjectMapper(); 25 | public static ObjectMapper getInstance() { 26 | return objectMapper; 27 | } 28 | 29 | /** 30 | * bean、array、List、Map --> json 31 | * 32 | * @param obj 33 | * @return json string 34 | * @throws Exception 35 | */ 36 | public static String writeValueAsString(Object obj) { 37 | try { 38 | return getInstance().writeValueAsString(obj); 39 | } catch (JsonGenerationException e) { 40 | logger.error(e.getMessage(), e); 41 | } catch (JsonMappingException e) { 42 | logger.error(e.getMessage(), e); 43 | } catch (IOException e) { 44 | logger.error(e.getMessage(), e); 45 | } 46 | return null; 47 | } 48 | 49 | /** 50 | * string --> bean、Map、List(array) 51 | * 52 | * @param jsonStr 53 | * @param clazz 54 | * @return obj 55 | * @throws Exception 56 | */ 57 | public static T readValue(String jsonStr, Class clazz) { 58 | try { 59 | return getInstance().readValue(jsonStr, clazz); 60 | } catch (JsonParseException e) { 61 | logger.error(e.getMessage(), e); 62 | } catch (JsonMappingException e) { 63 | logger.error(e.getMessage(), e); 64 | } catch (IOException e) { 65 | logger.error(e.getMessage(), e); 66 | } 67 | return null; 68 | } 69 | 70 | /** 71 | * string --> List... 72 | * 73 | * @param jsonStr 74 | * @param parametrized 75 | * @param parameterClasses 76 | * @param 77 | * @return 78 | */ 79 | public static T readValue(String jsonStr, Class parametrized, Class... parameterClasses) { 80 | try { 81 | JavaType javaType = getInstance().getTypeFactory().constructParametricType(parametrized, parameterClasses); 82 | return getInstance().readValue(jsonStr, javaType); 83 | } catch (JsonParseException e) { 84 | logger.error(e.getMessage(), e); 85 | } catch (JsonMappingException e) { 86 | logger.error(e.getMessage(), e); 87 | } catch (IOException e) { 88 | logger.error(e.getMessage(), e); 89 | } 90 | return null; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobGroupDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobGroup; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 16/9/30. 11 | */ 12 | @Mapper 13 | public interface XxlJobGroupDao { 14 | 15 | public List findAll(); 16 | 17 | public List findByAddressType(@Param("addressType") int addressType); 18 | 19 | public int save(XxlJobGroup xxlJobGroup); 20 | 21 | public int update(XxlJobGroup xxlJobGroup); 22 | 23 | public int remove(@Param("id") int id); 24 | 25 | public XxlJobGroup load(@Param("id") int id); 26 | 27 | public List pageList(@Param("offset") int offset, 28 | @Param("pagesize") int pagesize, 29 | @Param("appname") String appname, 30 | @Param("title") String title); 31 | 32 | public int pageListCount(@Param("offset") int offset, 33 | @Param("pagesize") int pagesize, 34 | @Param("appname") String appname, 35 | @Param("title") String title); 36 | 37 | /** 38 | * 批量查询 39 | * 40 | * @param jobGroupIds 41 | * @return 42 | */ 43 | List selectByIds(@Param("ids") List jobGroupIds); 44 | } 45 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobInfo; 4 | import com.xxl.job.core.handler.annotation.XxlJob; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | 11 | /** 12 | * job info 13 | * @author xuxueli 2016-1-12 18:03:45 14 | */ 15 | @Mapper 16 | public interface XxlJobInfoDao { 17 | 18 | public List pageList(@Param("offset") int offset, 19 | @Param("pagesize") int pagesize, 20 | @Param("jobGroup") int jobGroup, 21 | @Param("triggerStatus") int triggerStatus, 22 | @Param("jobDesc") String jobDesc, 23 | @Param("executorHandler") String executorHandler, 24 | @Param("author") String author); 25 | public int pageListCount(@Param("offset") int offset, 26 | @Param("pagesize") int pagesize, 27 | @Param("jobGroup") int jobGroup, 28 | @Param("triggerStatus") int triggerStatus, 29 | @Param("jobDesc") String jobDesc, 30 | @Param("executorHandler") String executorHandler, 31 | @Param("author") String author); 32 | 33 | public int save(XxlJobInfo info); 34 | 35 | public XxlJobInfo loadById(@Param("id") int id); 36 | 37 | public int update(XxlJobInfo xxlJobInfo); 38 | 39 | public int delete(@Param("id") long id); 40 | 41 | public List getJobsByGroup(@Param("jobGroup") int jobGroup); 42 | 43 | public int findAllCount(); 44 | 45 | public List scheduleJobQuery(@Param("maxNextTime") long maxNextTime, @Param("pagesize") int pagesize ); 46 | 47 | public int scheduleUpdate(XxlJobInfo xxlJobInfo); 48 | 49 | 50 | List selectByIds(@Param("ids") List jobIds); 51 | } 52 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLog; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * job log 13 | * @author xuxueli 2016-1-12 18:03:06 14 | */ 15 | @Mapper 16 | public interface XxlJobLogDao { 17 | 18 | // exist jobId not use jobGroup, not exist use jobGroup 19 | public List pageList(@Param("offset") int offset, 20 | @Param("pagesize") int pagesize, 21 | @Param("jobGroup") int jobGroup, 22 | @Param("jobId") int jobId, 23 | @Param("triggerTimeStart") Date triggerTimeStart, 24 | @Param("triggerTimeEnd") Date triggerTimeEnd, 25 | @Param("logStatus") int logStatus); 26 | public int pageListCount(@Param("offset") int offset, 27 | @Param("pagesize") int pagesize, 28 | @Param("jobGroup") int jobGroup, 29 | @Param("jobId") int jobId, 30 | @Param("triggerTimeStart") Date triggerTimeStart, 31 | @Param("triggerTimeEnd") Date triggerTimeEnd, 32 | @Param("logStatus") int logStatus); 33 | 34 | public XxlJobLog load(@Param("id") long id); 35 | 36 | public long save(XxlJobLog xxlJobLog); 37 | 38 | public int updateTriggerInfo(XxlJobLog xxlJobLog); 39 | 40 | public int updateHandleInfo(XxlJobLog xxlJobLog); 41 | 42 | public int delete(@Param("jobId") int jobId); 43 | 44 | public Map findLogReport(@Param("from") Date from, 45 | @Param("to") Date to); 46 | 47 | public List findClearLogIds(@Param("jobGroup") int jobGroup, 48 | @Param("jobId") int jobId, 49 | @Param("clearBeforeTime") Date clearBeforeTime, 50 | @Param("clearBeforeNum") int clearBeforeNum, 51 | @Param("pagesize") int pagesize); 52 | public int clearLog(@Param("logIds") List logIds); 53 | 54 | public List findFailJobLogIds(@Param("pagesize") int pagesize); 55 | 56 | public int updateAlarmStatus(@Param("logId") long logId, 57 | @Param("oldAlarmStatus") int oldAlarmStatus, 58 | @Param("newAlarmStatus") int newAlarmStatus); 59 | 60 | public List findLostJobIds(@Param("losedTime") Date losedTime); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogGlueDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLogGlue; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * job log for glue 11 | * @author xuxueli 2016-5-19 18:04:56 12 | */ 13 | @Mapper 14 | public interface XxlJobLogGlueDao { 15 | 16 | public int save(XxlJobLogGlue xxlJobLogGlue); 17 | 18 | public List findByJobId(@Param("jobId") int jobId); 19 | 20 | public int removeOld(@Param("jobId") int jobId, @Param("limit") int limit); 21 | 22 | public int deleteByJobId(@Param("jobId") int jobId); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogReportDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLogReport; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | /** 11 | * job log 12 | * @author xuxueli 2019-11-22 13 | */ 14 | @Mapper 15 | public interface XxlJobLogReportDao { 16 | 17 | public int save(XxlJobLogReport xxlJobLogReport); 18 | 19 | public int update(XxlJobLogReport xxlJobLogReport); 20 | 21 | public List queryLogReport(@Param("triggerDayFrom") Date triggerDayFrom, 22 | @Param("triggerDayTo") Date triggerDayTo); 23 | 24 | public XxlJobLogReport queryLogReportTotal(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobRegistryDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobRegistry; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by xuxueli on 16/9/30. 12 | */ 13 | @Mapper 14 | public interface XxlJobRegistryDao { 15 | 16 | public List findDead(@Param("timeout") int timeout, 17 | @Param("nowTime") Date nowTime); 18 | 19 | public int removeDead(@Param("ids") List ids); 20 | 21 | public List findAll(@Param("timeout") int timeout, 22 | @Param("nowTime") Date nowTime); 23 | 24 | public int registryUpdate(@Param("registryGroup") String registryGroup, 25 | @Param("registryKey") String registryKey, 26 | @Param("registryValue") String registryValue, 27 | @Param("updateTime") Date updateTime); 28 | 29 | public int registrySave(@Param("registryGroup") String registryGroup, 30 | @Param("registryKey") String registryKey, 31 | @Param("registryValue") String registryValue, 32 | @Param("updateTime") Date updateTime); 33 | 34 | public int registryDelete(@Param("registryGroup") String registryGroup, 35 | @Param("registryKey") String registryKey, 36 | @Param("registryValue") String registryValue); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobUserDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobUser; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import java.util.List; 7 | 8 | /** 9 | * @author xuxueli 2019-05-04 16:44:59 10 | */ 11 | @Mapper 12 | public interface XxlJobUserDao { 13 | 14 | public List pageList(@Param("offset") int offset, 15 | @Param("pagesize") int pagesize, 16 | @Param("username") String username, 17 | @Param("role") int role); 18 | public int pageListCount(@Param("offset") int offset, 19 | @Param("pagesize") int pagesize, 20 | @Param("username") String username, 21 | @Param("role") int role); 22 | 23 | public XxlJobUser loadByUserName(@Param("username") String username); 24 | 25 | public int save(XxlJobUser xxlJobUser); 26 | 27 | public int update(XxlJobUser xxlJobUser); 28 | 29 | public int delete(@Param("id") int id); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/service/XxlJobService.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.service; 2 | 3 | 4 | import com.xxl.job.admin.core.model.XxlJobInfo; 5 | import com.xxl.job.core.biz.model.ReturnT; 6 | 7 | import java.util.Date; 8 | import java.util.Map; 9 | 10 | /** 11 | * core job action for xxl-job 12 | * 13 | * @author xuxueli 2016-5-28 15:30:33 14 | */ 15 | public interface XxlJobService { 16 | 17 | /** 18 | * page list 19 | * 20 | * @param start 21 | * @param length 22 | * @param jobGroup 23 | * @param jobDesc 24 | * @param executorHandler 25 | * @param author 26 | * @return 27 | */ 28 | public Map pageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author); 29 | 30 | /** 31 | * add job 32 | * 33 | * @param jobInfo 34 | * @return 35 | */ 36 | public ReturnT add(XxlJobInfo jobInfo); 37 | 38 | /** 39 | * update job 40 | * 41 | * @param jobInfo 42 | * @return 43 | */ 44 | public ReturnT update(XxlJobInfo jobInfo); 45 | 46 | /** 47 | * remove job 48 | * * 49 | * @param id 50 | * @return 51 | */ 52 | public ReturnT remove(int id); 53 | 54 | /** 55 | * start job 56 | * 57 | * @param id 58 | * @return 59 | */ 60 | public ReturnT start(int id); 61 | 62 | /** 63 | * stop job 64 | * 65 | * @param id 66 | * @return 67 | */ 68 | public ReturnT stop(int id); 69 | 70 | /** 71 | * dashboard info 72 | * 73 | * @return 74 | */ 75 | public Map dashboardInfo(); 76 | 77 | /** 78 | * chart info 79 | * 80 | * @param startDate 81 | * @param endDate 82 | * @return 83 | */ 84 | public ReturnT> chartInfo(Date startDate, Date endDate); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/AdminBizImpl.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.service.impl; 2 | 3 | import com.xxl.job.admin.core.thread.JobCompleteHelper; 4 | import com.xxl.job.admin.core.thread.JobRegistryHelper; 5 | import com.xxl.job.core.biz.AdminBiz; 6 | import com.xxl.job.core.biz.model.HandleCallbackParam; 7 | import com.xxl.job.core.biz.model.RegistryParam; 8 | import com.xxl.job.core.biz.model.ReturnT; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author xuxueli 2017-07-27 21:54:20 15 | */ 16 | @Service 17 | public class AdminBizImpl implements AdminBiz { 18 | 19 | 20 | @Override 21 | public ReturnT callback(List callbackParamList) { 22 | return JobCompleteHelper.getInstance().callback(callbackParamList); 23 | } 24 | 25 | @Override 26 | public ReturnT registry(RegistryParam registryParam) { 27 | return JobRegistryHelper.getInstance().registry(registryParam); 28 | } 29 | 30 | @Override 31 | public ReturnT registryRemove(RegistryParam registryParam) { 32 | return JobRegistryHelper.getInstance().registryRemove(registryParam); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | ### xxl-job, datasource 2 | spring.datasource.url=jdbc:mysql://49.234.14.191:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai 3 | spring.datasource.username=root 4 | spring.datasource.password=skydt324 5 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 6 | 7 | 8 | ### xxl-job, email 9 | spring.mail.host=smtp.163.com 10 | spring.mail.port=465 11 | spring.mail.username=xxx@163.com 12 | spring.mail.from=xxx@163.com 13 | spring.mail.password=xxx 14 | spring.mail.properties.mail.smtp.auth=true 15 | spring.mail.properties.mail.smtp.starttls.enable=true 16 | spring.mail.properties.mail.smtp.starttls.required=true 17 | spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/application-docker.properties: -------------------------------------------------------------------------------- 1 | ### xxl-job, datasource 2 | spring.datasource.url=${SPRING_DATASOURCE_URL} 3 | spring.datasource.username=${SPRING_DATASOURCE_USERNAME} 4 | spring.datasource.password=${SPRING_DATASOURCE_PASSWORD} 5 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 6 | 7 | 8 | ### xxl-job, email 9 | spring.mail.host=${SPRING_MAIL_HOST} 10 | spring.mail.port=${SPRING_MAIL_PORT} 11 | spring.mail.username=${SPRING_MAIL_USERNAME} 12 | spring.mail.from=${SPRING_MAIL_FROM} 13 | spring.mail.password=${SPRING_MAIL_PASSWORD} 14 | spring.mail.properties.mail.smtp.auth=${SPRING_MAIL_PROPERTIES_MAIL_SMTP_AUTH} 15 | spring.mail.properties.mail.smtp.starttls.enable=${SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_ENABLE} 16 | spring.mail.properties.mail.smtp.starttls.required=${SPRING_MAIL_PROPERTIES_MAIL_SMTP_STARTTLS_REQUIRED} 17 | spring.mail.properties.mail.smtp.socketFactory.class=${SPRING_MAIL_PROPERTIES_MAIL_SMTP_SOCKETFACTORY_CLASS} -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ### web 2 | server.port=8080 3 | server.servlet.context-path=/xxl-job-admin 4 | 5 | spring.profiles.include=dev 6 | 7 | ### actuator 8 | management.server.servlet.context-path=/actuator 9 | management.health.mail.enabled=false 10 | 11 | ### resources 12 | spring.mvc.servlet.load-on-startup=0 13 | spring.mvc.static-path-pattern=/static/** 14 | spring.resources.static-locations=classpath:/static/ 15 | 16 | ### freemarker 17 | spring.freemarker.templateLoaderPath=classpath:/templates/ 18 | spring.freemarker.suffix=.ftl 19 | spring.freemarker.charset=UTF-8 20 | spring.freemarker.request-context-attribute=request 21 | spring.freemarker.settings.number_format=0.########## 22 | 23 | ### mybatis 24 | mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml 25 | #mybatis.type-aliases-package=com.xxl.job.admin.core.model 26 | 27 | ### datasource-pool 28 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 29 | spring.datasource.hikari.minimum-idle=10 30 | spring.datasource.hikari.maximum-pool-size=30 31 | spring.datasource.hikari.auto-commit=true 32 | spring.datasource.hikari.idle-timeout=30000 33 | spring.datasource.hikari.pool-name=HikariCP 34 | spring.datasource.hikari.max-lifetime=900000 35 | spring.datasource.hikari.connection-timeout=10000 36 | spring.datasource.hikari.connection-test-query=SELECT 1 37 | spring.datasource.hikari.validation-timeout=1000 38 | 39 | 40 | ### xxl-job, access token 41 | xxl.job.accessToken= 42 | 43 | ### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en") 44 | xxl.job.i18n=zh_CN 45 | 46 | ## xxl-job, triggerpool max size 47 | xxl.job.triggerpool.fast.max=200 48 | xxl.job.triggerpool.slow.max=100 49 | 50 | ### xxl-job, log retention days 51 | xxl.job.logretentiondays=30 52 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logback 5 | 6 | 7 | 8 | 9 | %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | ${log.path} 15 | 16 | ${log.path}.%d{yyyy-MM-dd}.zip 17 | 18 | 19 | %date %level [%thread] %logger{36} [%file : %line] %msg%n 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogGlueMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | t.id, 18 | t.job_id, 19 | t.glue_type, 20 | t.glue_source, 21 | t.glue_remark, 22 | t.add_time, 23 | t.update_time 24 | 25 | 26 | 27 | INSERT INTO xxl_job_logglue ( 28 | `job_id`, 29 | `glue_type`, 30 | `glue_source`, 31 | `glue_remark`, 32 | `add_time`, 33 | `update_time` 34 | ) VALUES ( 35 | #{jobId}, 36 | #{glueType}, 37 | #{glueSource}, 38 | #{glueRemark}, 39 | #{addTime}, 40 | #{updateTime} 41 | ); 42 | 45 | 46 | 47 | 53 | 54 | 55 | DELETE FROM xxl_job_logglue 56 | WHERE id NOT in( 57 | SELECT id FROM( 58 | SELECT id FROM xxl_job_logglue 59 | WHERE `job_id` = #{jobId} 60 | ORDER BY update_time desc 61 | LIMIT 0, #{limit} 62 | ) t1 63 | ) AND `job_id` = #{jobId} 64 | 65 | 66 | 67 | DELETE FROM xxl_job_logglue 68 | WHERE `job_id` = #{jobId} 69 | 70 | 71 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogReportMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | t.id, 16 | t.trigger_day, 17 | t.running_count, 18 | t.suc_count, 19 | t.fail_count 20 | 21 | 22 | 23 | INSERT INTO xxl_job_log_report ( 24 | `trigger_day`, 25 | `running_count`, 26 | `suc_count`, 27 | `fail_count` 28 | ) VALUES ( 29 | #{triggerDay}, 30 | #{runningCount}, 31 | #{sucCount}, 32 | #{failCount} 33 | ); 34 | 37 | 38 | 39 | 40 | UPDATE xxl_job_log_report 41 | SET `running_count` = #{runningCount}, 42 | `suc_count` = #{sucCount}, 43 | `fail_count` = #{failCount} 44 | WHERE `trigger_day` = #{triggerDay} 45 | 46 | 47 | 53 | 54 | 61 | 62 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobRegistryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | t.id, 16 | t.registry_group, 17 | t.registry_key, 18 | t.registry_value, 19 | t.update_time 20 | 21 | 22 | 27 | 28 | 29 | DELETE FROM xxl_job_registry 30 | WHERE id in 31 | 32 | #{item} 33 | 34 | 35 | 36 | 41 | 42 | 43 | UPDATE xxl_job_registry 44 | SET `update_time` = #{updateTime} 45 | WHERE `registry_group` = #{registryGroup} 46 | AND `registry_key` = #{registryKey} 47 | AND `registry_value` = #{registryValue} 48 | 49 | 50 | 51 | INSERT INTO xxl_job_registry( `registry_group` , `registry_key` , `registry_value`, `update_time`) 52 | VALUES( #{registryGroup} , #{registryKey} , #{registryValue}, #{updateTime}) 53 | 54 | 55 | 56 | DELETE FROM xxl_job_registry 57 | WHERE registry_group = #{registryGroup} 58 | AND registry_key = #{registryKey} 59 | AND registry_value = #{registryValue} 60 | 61 | 62 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | t.id, 16 | t.username, 17 | t.password, 18 | t.role, 19 | t.permission 20 | 21 | 22 | 36 | 37 | 49 | 50 | 55 | 56 | 57 | INSERT INTO xxl_job_user ( 58 | username, 59 | password, 60 | role, 61 | permission 62 | ) VALUES ( 63 | #{username}, 64 | #{password}, 65 | #{role}, 66 | #{permission} 67 | ); 68 | 69 | 70 | 71 | UPDATE xxl_job_user 72 | SET 73 | 74 | password = #{password}, 75 | 76 | role = #{role}, 77 | permission = #{permission} 78 | WHERE id = #{id} 79 | 80 | 81 | 82 | DELETE 83 | FROM xxl_job_user 84 | WHERE id = #{id} 85 | 86 | 87 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.eot -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.ttf -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.woff -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/PACE/themes/blue/pace-theme-flash.css: -------------------------------------------------------------------------------- 1 | /* This is a compiled file, you should be editing the file in the templates directory */ 2 | .pace { 3 | -webkit-pointer-events: none; 4 | pointer-events: none; 5 | -webkit-user-select: none; 6 | -moz-user-select: none; 7 | user-select: none; 8 | } 9 | 10 | .pace-inactive { 11 | display: none; 12 | } 13 | 14 | .pace .pace-progress { 15 | background: #2299dd; 16 | position: fixed; 17 | z-index: 2000; 18 | top: 0; 19 | right: 100%; 20 | width: 100%; 21 | height: 2px; 22 | } 23 | 24 | .pace .pace-progress-inner { 25 | display: block; 26 | position: absolute; 27 | right: 0px; 28 | width: 100px; 29 | height: 100%; 30 | box-shadow: 0 0 10px #2299dd, 0 0 5px #2299dd; 31 | opacity: 1.0; 32 | -webkit-transform: rotate(3deg) translate(0px, -4px); 33 | -moz-transform: rotate(3deg) translate(0px, -4px); 34 | -ms-transform: rotate(3deg) translate(0px, -4px); 35 | -o-transform: rotate(3deg) translate(0px, -4px); 36 | transform: rotate(3deg) translate(0px, -4px); 37 | } 38 | 39 | .pace .pace-activity { 40 | display: block; 41 | position: fixed; 42 | z-index: 2000; 43 | top: 15px; 44 | right: 15px; 45 | width: 14px; 46 | height: 14px; 47 | border: solid 2px transparent; 48 | border-top-color: #2299dd; 49 | border-left-color: #2299dd; 50 | border-radius: 10px; 51 | -webkit-animation: pace-spinner 400ms linear infinite; 52 | -moz-animation: pace-spinner 400ms linear infinite; 53 | -ms-animation: pace-spinner 400ms linear infinite; 54 | -o-animation: pace-spinner 400ms linear infinite; 55 | animation: pace-spinner 400ms linear infinite; 56 | } 57 | 58 | @-webkit-keyframes pace-spinner { 59 | 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 60 | 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } 61 | } 62 | @-moz-keyframes pace-spinner { 63 | 0% { -moz-transform: rotate(0deg); transform: rotate(0deg); } 64 | 100% { -moz-transform: rotate(360deg); transform: rotate(360deg); } 65 | } 66 | @-o-keyframes pace-spinner { 67 | 0% { -o-transform: rotate(0deg); transform: rotate(0deg); } 68 | 100% { -o-transform: rotate(360deg); transform: rotate(360deg); } 69 | } 70 | @-ms-keyframes pace-spinner { 71 | 0% { -ms-transform: rotate(0deg); transform: rotate(0deg); } 72 | 100% { -ms-transform: rotate(360deg); transform: rotate(360deg); } 73 | } 74 | @keyframes pace-spinner { 75 | 0% { transform: rotate(0deg); transform: rotate(0deg); } 76 | 100% { transform: rotate(360deg); transform: rotate(360deg); } 77 | } 78 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 3 integration 3 | ©2011-2015 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});b.extend(f.ext.classes, 6 | {sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")}; 7 | l=0;for(h=f.length;l",{"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#", 8 | "aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('
    ').children("ul"),s);i!==m&&b(h).find("[data-dt-idx="+i+"]").focus()};return f}); 9 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/bower_components/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/plugins/iCheck/square/blue.css: -------------------------------------------------------------------------------- 1 | /* iCheck plugin Square skin, blue 2 | ----------------------------------- */ 3 | .icheckbox_square-blue, 4 | .iradio_square-blue { 5 | display: inline-block; 6 | *display: inline; 7 | vertical-align: middle; 8 | margin: 0; 9 | padding: 0; 10 | width: 22px; 11 | height: 22px; 12 | background: url(blue.png) no-repeat; 13 | border: none; 14 | cursor: pointer; 15 | } 16 | 17 | .icheckbox_square-blue { 18 | background-position: 0 0; 19 | } 20 | .icheckbox_square-blue.hover { 21 | background-position: -24px 0; 22 | } 23 | .icheckbox_square-blue.checked { 24 | background-position: -48px 0; 25 | } 26 | .icheckbox_square-blue.disabled { 27 | background-position: -72px 0; 28 | cursor: default; 29 | } 30 | .icheckbox_square-blue.checked.disabled { 31 | background-position: -96px 0; 32 | } 33 | 34 | .iradio_square-blue { 35 | background-position: -120px 0; 36 | } 37 | .iradio_square-blue.hover { 38 | background-position: -144px 0; 39 | } 40 | .iradio_square-blue.checked { 41 | background-position: -168px 0; 42 | } 43 | .iradio_square-blue.disabled { 44 | background-position: -192px 0; 45 | cursor: default; 46 | } 47 | .iradio_square-blue.checked.disabled { 48 | background-position: -216px 0; 49 | } 50 | 51 | /* Retina support */ 52 | @media only screen and (-webkit-min-device-pixel-ratio: 1.5), 53 | only screen and (-moz-min-device-pixel-ratio: 1.5), 54 | only screen and (-o-min-device-pixel-ratio: 3/2), 55 | only screen and (min-device-pixel-ratio: 1.5) { 56 | .icheckbox_square-blue, 57 | .iradio_square-blue { 58 | background-image: url(blue@2x.png); 59 | -webkit-background-size: 240px 24px; 60 | background-size: 240px 24px; 61 | } 62 | } -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/plugins/iCheck/square/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/plugins/iCheck/square/blue.png -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/adminlte/plugins/iCheck/square/blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/adminlte/plugins/iCheck/square/blue@2x.png -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/js/jobcode.index.1.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // init code editor 4 | var codeEditor; 5 | function initIde(glueSource) { 6 | if (codeEditor == null) { 7 | codeEditor = CodeMirror(document.getElementById("ideWindow"), { 8 | mode : ideMode, 9 | lineNumbers : true, 10 | matchBrackets : true, 11 | value: glueSource 12 | }); 13 | } else { 14 | codeEditor.setValue(glueSource); 15 | } 16 | } 17 | 18 | initIde($("#version_now").val()); 19 | 20 | // code change 21 | $(".source_version").click(function(){ 22 | var sourceId = $(this).attr('version'); 23 | var temp = $( "#" + sourceId ).val(); 24 | 25 | //codeEditor.setValue(''); 26 | initIde(temp); 27 | }); 28 | 29 | // code source save 30 | $("#save").click(function() { 31 | $('#saveModal').modal({backdrop: false, keyboard: false}).modal('show'); 32 | }); 33 | 34 | $("#saveModal .ok").click(function() { 35 | 36 | var glueSource = codeEditor.getValue(); 37 | var glueRemark = $("#glueRemark").val(); 38 | 39 | if (!glueRemark) { 40 | layer.open({ 41 | title: I18n.system_tips, 42 | btn: [ I18n.system_ok], 43 | content: I18n.system_please_input + I18n.jobinfo_glue_remark , 44 | icon: '2' 45 | }); 46 | return; 47 | } 48 | if (glueRemark.length <4 || glueRemark.length > 100) { 49 | layer.open({ 50 | title: I18n.system_tips , 51 | btn: [ I18n.system_ok ], 52 | content: I18n.jobinfo_glue_remark_limit , 53 | icon: '2' 54 | }); 55 | return; 56 | } 57 | 58 | $.ajax({ 59 | type : 'POST', 60 | url : base_url + '/jobcode/save', 61 | data : { 62 | 'id' : id, 63 | 'glueSource' : glueSource, 64 | 'glueRemark' : glueRemark 65 | }, 66 | dataType : "json", 67 | success : function(data){ 68 | if (data.code == 200) { 69 | layer.open({ 70 | title: I18n.system_tips, 71 | btn: [ I18n.system_ok ], 72 | content: (I18n.system_save + I18n.system_success) , 73 | icon: '1', 74 | end: function(layero, index){ 75 | //$(window).unbind('beforeunload'); 76 | window.location.reload(); 77 | } 78 | }); 79 | } else { 80 | layer.open({ 81 | title: I18n.system_tips, 82 | btn: [ I18n.system_ok ], 83 | content: (data.msg || (I18n.system_save + I18n.system_fail) ), 84 | icon: '2' 85 | }); 86 | } 87 | } 88 | }); 89 | 90 | }); 91 | 92 | // before upload 93 | /*$(window).bind('beforeunload',function(){ 94 | return 'Glue尚未保存,确定离开Glue编辑器?'; 95 | });*/ 96 | 97 | }); 98 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/js/joblog.detail.1.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // trigger fail, end 4 | if ( !(triggerCode == 200 || handleCode != 0) ) { 5 | $('#logConsoleRunning').hide(); 6 | $('#logConsole').append(''+ I18n.joblog_rolling_log_triggerfail +''); 7 | return; 8 | } 9 | 10 | // pull log 11 | var fromLineNum = 1; // [from, to], start as 1 12 | var pullFailCount = 0; 13 | function pullLog() { 14 | // pullFailCount, max=20 15 | if (pullFailCount++ > 20) { 16 | logRunStop(''+ I18n.joblog_rolling_log_failoften +''); 17 | return; 18 | } 19 | 20 | // load 21 | console.log("pullLog, fromLineNum:" + fromLineNum); 22 | 23 | $.ajax({ 24 | type : 'POST', 25 | async: false, // sync, make log ordered 26 | url : base_url + '/joblog/logDetailCat', 27 | data : { 28 | "executorAddress":executorAddress, 29 | "triggerTime":triggerTime, 30 | "logId":logId, 31 | "fromLineNum":fromLineNum 32 | }, 33 | dataType : "json", 34 | success : function(data){ 35 | 36 | if (data.code == 200) { 37 | if (!data.content) { 38 | console.log('pullLog fail'); 39 | return; 40 | } 41 | if (fromLineNum != data.content.fromLineNum) { 42 | console.log('pullLog fromLineNum not match'); 43 | return; 44 | } 45 | if (fromLineNum > data.content.toLineNum ) { 46 | console.log('pullLog already line-end'); 47 | 48 | // valid end 49 | if (data.content.end) { 50 | logRunStop('
    [Rolling Log Finish]'); 51 | return; 52 | } 53 | 54 | return; 55 | } 56 | 57 | // append content 58 | fromLineNum = data.content.toLineNum + 1; 59 | $('#logConsole').append(data.content.logContent); 60 | pullFailCount = 0; 61 | 62 | // scroll to bottom 63 | scrollTo(0, document.body.scrollHeight); // $('#logConsolePre').scrollTop( document.body.scrollHeight + 300 ); 64 | 65 | } else { 66 | console.log('pullLog fail:'+data.msg); 67 | } 68 | } 69 | }); 70 | } 71 | 72 | // pull first page 73 | pullLog(); 74 | 75 | // handler already callback, end 76 | if (handleCode > 0) { 77 | logRunStop('
    [Load Log Finish]'); 78 | return; 79 | } 80 | 81 | // round until end 82 | var logRun = setInterval(function () { 83 | pullLog() 84 | }, 3000); 85 | function logRunStop(content){ 86 | $('#logConsoleRunning').hide(); 87 | logRun = window.clearInterval(logRun); 88 | $('#logConsole').append(content); 89 | } 90 | 91 | }); 92 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/js/login.1.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | // input iCheck 4 | $('input').iCheck({ 5 | checkboxClass: 'icheckbox_square-blue', 6 | radioClass: 'iradio_square-blue', 7 | increaseArea: '20%' // optional 8 | }); 9 | 10 | // login Form Valid 11 | var loginFormValid = $("#loginForm").validate({ 12 | errorElement : 'span', 13 | errorClass : 'help-block', 14 | focusInvalid : true, 15 | rules : { 16 | userName : { 17 | required : true , 18 | minlength: 4, 19 | maxlength: 18 20 | }, 21 | password : { 22 | required : true , 23 | minlength: 4, 24 | maxlength: 18 25 | } 26 | }, 27 | messages : { 28 | userName : { 29 | required : I18n.login_username_empty, 30 | minlength : I18n.login_username_lt_4 31 | }, 32 | password : { 33 | required : I18n.login_password_empty , 34 | minlength : I18n.login_password_lt_4 35 | /*,maxlength:"登录密码不应超过18位"*/ 36 | } 37 | }, 38 | highlight : function(element) { 39 | $(element).closest('.form-group').addClass('has-error'); 40 | }, 41 | success : function(label) { 42 | label.closest('.form-group').removeClass('has-error'); 43 | label.remove(); 44 | }, 45 | errorPlacement : function(error, element) { 46 | element.parent('div').append(error); 47 | }, 48 | submitHandler : function(form) { 49 | $.post(base_url + "/login", $("#loginForm").serialize(), function(data, status) { 50 | if (data.code == "200") { 51 | layer.msg( I18n.login_success ); 52 | setTimeout(function(){ 53 | window.location.href = base_url + "/"; 54 | }, 500); 55 | } else { 56 | layer.open({ 57 | title: I18n.system_tips, 58 | btn: [ I18n.system_ok ], 59 | content: (data.msg || I18n.login_fail ), 60 | icon: '2' 61 | }); 62 | } 63 | }); 64 | } 65 | }); 66 | }); -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/codemirror/addon/hint/anyword-hint.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | var WORD = /[\w$]+/, RANGE = 500; 15 | 16 | CodeMirror.registerHelper("hint", "anyword", function(editor, options) { 17 | var word = options && options.word || WORD; 18 | var range = options && options.range || RANGE; 19 | var cur = editor.getCursor(), curLine = editor.getLine(cur.line); 20 | var end = cur.ch, start = end; 21 | while (start && word.test(curLine.charAt(start - 1))) --start; 22 | var curWord = start != end && curLine.slice(start, end); 23 | 24 | var list = options && options.list || [], seen = {}; 25 | var re = new RegExp(word.source, "g"); 26 | for (var dir = -1; dir <= 1; dir += 2) { 27 | var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir; 28 | for (; line != endLine; line += dir) { 29 | var text = editor.getLine(line), m; 30 | while (m = re.exec(text)) { 31 | if (line == cur.line && m[0] === curWord) continue; 32 | if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) { 33 | seen[m[0]] = true; 34 | list.push(m[0]); 35 | } 36 | } 37 | } 38 | } 39 | return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)}; 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/codemirror/addon/hint/show-hint.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-hints { 2 | position: absolute; 3 | z-index: 10; 4 | overflow: hidden; 5 | list-style: none; 6 | 7 | margin: 0; 8 | padding: 2px; 9 | 10 | -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 11 | -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 12 | box-shadow: 2px 3px 5px rgba(0,0,0,.2); 13 | border-radius: 3px; 14 | border: 1px solid silver; 15 | 16 | background: white; 17 | font-size: 90%; 18 | font-family: monospace; 19 | 20 | max-height: 20em; 21 | overflow-y: auto; 22 | } 23 | 24 | .CodeMirror-hint { 25 | margin: 0; 26 | padding: 0 4px; 27 | border-radius: 2px; 28 | white-space: pre; 29 | color: black; 30 | cursor: pointer; 31 | } 32 | 33 | li.CodeMirror-hint-active { 34 | background: #08f; 35 | color: white; 36 | } 37 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/icon-ext.png -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/icon.png -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-0.gif -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-1.gif -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdyzm/xxl-job/9cdc32b54d9d2025fb019f9aac39d2d91306696f/xxl-job-admin/src/main/resources/static/plugins/layer/theme/default/loading-2.gif -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/templates/common/common.exception.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 18 | 19 | 20 | 21 | 22 | 23 |
    29 | 30 | 31 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/templates/help.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <#import "./common/common.macro.ftl" as netCommon> 5 | <@netCommon.commonStyle /> 6 | ${I18n.admin_name} 7 | 8 | sidebar-collapse "> 9 |
    10 | 11 | <@netCommon.commonHeader /> 12 | 13 | <@netCommon.commonLeft "help" /> 14 | 15 | 16 |
    17 | 18 |
    19 |

    ${I18n.job_help}

    20 |
    21 | 22 | 23 |
    24 |
    25 |

    ${I18n.admin_name_full}

    26 |
    27 |

    28 | Github     29 | 30 |

    31 | ${I18n.job_help_document} 32 |

    33 | 34 |

    35 |

    36 |
    37 |
    38 | 39 |
    40 | 41 | 42 | 43 | <@netCommon.commonFooter /> 44 |
    45 | <@netCommon.commonScript /> 46 | 47 | 48 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/templates/joblog/joblog.detail.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <#import "../common/common.macro.ftl" as netCommon> 5 | <@netCommon.commonStyle /> 6 | ${I18n.admin_name} 7 | 8 | 9 | 10 |
    11 | 12 |
    13 | 44 |
    45 | 46 |
    47 |
    48 |
    49 |                 
    50 |
  • 51 |
    52 |
    53 |
    54 | 55 | 56 | <@netCommon.commonFooter /> 57 | 58 |
    59 | 60 | <@netCommon.commonScript /> 61 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /xxl-job-admin/src/main/resources/templates/login.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <#import "./common/common.macro.ftl" as netCommon> 5 | <@netCommon.commonStyle /> 6 | 7 | ${I18n.admin_name} 8 | 9 | 10 | 40 | <@netCommon.commonScript /> 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/controller/AbstractSpringMvcTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.web.servlet.MockMvc; 7 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 8 | import org.springframework.web.context.WebApplicationContext; 9 | 10 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 11 | public class AbstractSpringMvcTest { 12 | 13 | @Autowired 14 | private WebApplicationContext applicationContext; 15 | protected MockMvc mockMvc; 16 | 17 | @BeforeEach 18 | public void setup() { 19 | this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext).build(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/controller/JobInfoControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller; 2 | 3 | import com.xxl.job.admin.service.LoginService; 4 | import org.junit.jupiter.api.BeforeEach; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.test.web.servlet.MvcResult; 8 | import org.springframework.util.LinkedMultiValueMap; 9 | import org.springframework.util.MultiValueMap; 10 | 11 | import javax.servlet.http.Cookie; 12 | 13 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 14 | 15 | public class JobInfoControllerTest extends AbstractSpringMvcTest { 16 | 17 | private Cookie cookie; 18 | 19 | @BeforeEach 20 | public void login() throws Exception { 21 | MvcResult ret = mockMvc.perform( 22 | post("/login") 23 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 24 | .param("userName", "admin") 25 | .param("password", "123456") 26 | ).andReturn(); 27 | cookie = ret.getResponse().getCookie(LoginService.LOGIN_IDENTITY_KEY); 28 | } 29 | 30 | @Test 31 | public void testAdd() throws Exception { 32 | MultiValueMap parameters = new LinkedMultiValueMap(); 33 | parameters.add("jobGroup", "1"); 34 | parameters.add("triggerStatus", "-1"); 35 | 36 | MvcResult ret = mockMvc.perform( 37 | post("/jobinfo/pageList") 38 | .contentType(MediaType.APPLICATION_FORM_URLENCODED) 39 | //.content(paramsJson) 40 | .params(parameters) 41 | .cookie(cookie) 42 | ).andReturn(); 43 | 44 | System.out.println(ret.getResponse().getContentAsString()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/core/util/JacksonUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import static com.xxl.job.admin.core.util.JacksonUtil.writeValueAsString; 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | public class JacksonUtilTest { 12 | 13 | @Test 14 | public void shouldWriteValueAsString() { 15 | //given 16 | Map map = new HashMap<>(); 17 | map.put("aaa", "111"); 18 | map.put("bbb", "222"); 19 | 20 | //when 21 | String json = writeValueAsString(map); 22 | 23 | //then 24 | assertEquals(json, "{\"aaa\":\"111\",\"bbb\":\"222\"}"); 25 | } 26 | 27 | @Test 28 | public void shouldReadValueAsObject() { 29 | //given 30 | String jsonString = "{\"aaa\":\"111\",\"bbb\":\"222\"}"; 31 | 32 | //when 33 | Map result = JacksonUtil.readValue(jsonString, Map.class); 34 | 35 | //then 36 | assertEquals(result.get("aaa"), "111"); 37 | assertEquals(result.get("bbb"),"222"); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/dao/XxlJobGroupDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobGroup; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 12 | public class XxlJobGroupDaoTest { 13 | 14 | @Resource 15 | private XxlJobGroupDao xxlJobGroupDao; 16 | 17 | @Test 18 | public void test(){ 19 | List list = xxlJobGroupDao.findAll(); 20 | 21 | List list2 = xxlJobGroupDao.findByAddressType(0); 22 | 23 | XxlJobGroup group = new XxlJobGroup(); 24 | group.setAppname("setAppName"); 25 | group.setTitle("setTitle"); 26 | group.setAddressType(0); 27 | group.setAddressList("setAddressList"); 28 | group.setUpdateTime(new Date()); 29 | 30 | int ret = xxlJobGroupDao.save(group); 31 | 32 | XxlJobGroup group2 = xxlJobGroupDao.load(group.getId()); 33 | group2.setAppname("setAppName2"); 34 | group2.setTitle("setTitle2"); 35 | group2.setAddressType(2); 36 | group2.setAddressList("setAddressList2"); 37 | group2.setUpdateTime(new Date()); 38 | 39 | int ret2 = xxlJobGroupDao.update(group2); 40 | 41 | int ret3 = xxlJobGroupDao.remove(group.getId()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/dao/XxlJobInfoDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobInfo; 4 | import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum; 5 | import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import javax.annotation.Resource; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 14 | public class XxlJobInfoDaoTest { 15 | 16 | @Resource 17 | private XxlJobInfoDao xxlJobInfoDao; 18 | 19 | @Test 20 | public void pageList(){ 21 | List list = xxlJobInfoDao.pageList(0, 20, 0, -1, null, null, null); 22 | int list_count = xxlJobInfoDao.pageListCount(0, 20, 0, -1, null, null, null); 23 | 24 | System.out.println(list); 25 | System.out.println(list_count); 26 | 27 | List list2 = xxlJobInfoDao.getJobsByGroup(1); 28 | } 29 | 30 | @Test 31 | public void save_load(){ 32 | XxlJobInfo info = new XxlJobInfo(); 33 | info.setJobGroup(1); 34 | info.setJobDesc("desc"); 35 | info.setAuthor("setAuthor"); 36 | info.setAlarmEmail("setAlarmEmail"); 37 | info.setScheduleType(ScheduleTypeEnum.FIX_RATE.name()); 38 | info.setScheduleConf(String.valueOf(33)); 39 | info.setMisfireStrategy(MisfireStrategyEnum.DO_NOTHING.name()); 40 | info.setExecutorRouteStrategy("setExecutorRouteStrategy"); 41 | info.setExecutorHandler("setExecutorHandler"); 42 | info.setExecutorParam("setExecutorParam"); 43 | info.setExecutorBlockStrategy("setExecutorBlockStrategy"); 44 | info.setGlueType("setGlueType"); 45 | info.setGlueSource("setGlueSource"); 46 | info.setGlueRemark("setGlueRemark"); 47 | info.setChildJobId("1"); 48 | 49 | info.setAddTime(new Date()); 50 | info.setUpdateTime(new Date()); 51 | info.setGlueUpdatetime(new Date()); 52 | 53 | int count = xxlJobInfoDao.save(info); 54 | 55 | XxlJobInfo info2 = xxlJobInfoDao.loadById(info.getId()); 56 | info.setScheduleType(ScheduleTypeEnum.FIX_RATE.name()); 57 | info.setScheduleConf(String.valueOf(44)); 58 | info.setMisfireStrategy(MisfireStrategyEnum.FIRE_ONCE_NOW.name()); 59 | info2.setJobDesc("desc2"); 60 | info2.setAuthor("setAuthor2"); 61 | info2.setAlarmEmail("setAlarmEmail2"); 62 | info2.setExecutorRouteStrategy("setExecutorRouteStrategy2"); 63 | info2.setExecutorHandler("setExecutorHandler2"); 64 | info2.setExecutorParam("setExecutorParam2"); 65 | info2.setExecutorBlockStrategy("setExecutorBlockStrategy2"); 66 | info2.setGlueType("setGlueType2"); 67 | info2.setGlueSource("setGlueSource2"); 68 | info2.setGlueRemark("setGlueRemark2"); 69 | info2.setGlueUpdatetime(new Date()); 70 | info2.setChildJobId("1"); 71 | 72 | info2.setUpdateTime(new Date()); 73 | int item2 = xxlJobInfoDao.update(info2); 74 | 75 | xxlJobInfoDao.delete(info2.getId()); 76 | 77 | List list2 = xxlJobInfoDao.getJobsByGroup(1); 78 | 79 | int ret3 = xxlJobInfoDao.findAllCount(); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/dao/XxlJobLogDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLog; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 12 | public class XxlJobLogDaoTest { 13 | 14 | @Resource 15 | private XxlJobLogDao xxlJobLogDao; 16 | 17 | @Test 18 | public void test(){ 19 | List list = xxlJobLogDao.pageList(0, 10, 1, 1, null, null, 1); 20 | int list_count = xxlJobLogDao.pageListCount(0, 10, 1, 1, null, null, 1); 21 | 22 | XxlJobLog log = new XxlJobLog(); 23 | log.setJobGroup(1); 24 | log.setJobId(1); 25 | 26 | long ret1 = xxlJobLogDao.save(log); 27 | XxlJobLog dto = xxlJobLogDao.load(log.getId()); 28 | 29 | log.setTriggerTime(new Date()); 30 | log.setTriggerCode(1); 31 | log.setTriggerMsg("1"); 32 | log.setExecutorAddress("1"); 33 | log.setExecutorHandler("1"); 34 | log.setExecutorParam("1"); 35 | ret1 = xxlJobLogDao.updateTriggerInfo(log); 36 | dto = xxlJobLogDao.load(log.getId()); 37 | 38 | 39 | log.setHandleTime(new Date()); 40 | log.setHandleCode(2); 41 | log.setHandleMsg("2"); 42 | ret1 = xxlJobLogDao.updateHandleInfo(log); 43 | dto = xxlJobLogDao.load(log.getId()); 44 | 45 | 46 | List ret4 = xxlJobLogDao.findClearLogIds(1, 1, new Date(), 100, 100); 47 | 48 | int ret2 = xxlJobLogDao.delete(log.getJobId()); 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/dao/XxlJobLogGlueDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLogGlue; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 12 | public class XxlJobLogGlueDaoTest { 13 | 14 | @Resource 15 | private XxlJobLogGlueDao xxlJobLogGlueDao; 16 | 17 | @Test 18 | public void test(){ 19 | XxlJobLogGlue logGlue = new XxlJobLogGlue(); 20 | logGlue.setJobId(1); 21 | logGlue.setGlueType("1"); 22 | logGlue.setGlueSource("1"); 23 | logGlue.setGlueRemark("1"); 24 | 25 | logGlue.setAddTime(new Date()); 26 | logGlue.setUpdateTime(new Date()); 27 | int ret = xxlJobLogGlueDao.save(logGlue); 28 | 29 | List list = xxlJobLogGlueDao.findByJobId(1); 30 | 31 | int ret2 = xxlJobLogGlueDao.removeOld(1, 1); 32 | 33 | int ret3 =xxlJobLogGlueDao.deleteByJobId(1); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/dao/XxlJobRegistryDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobRegistry; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import javax.annotation.Resource; 8 | import java.util.Arrays; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 13 | public class XxlJobRegistryDaoTest { 14 | 15 | @Resource 16 | private XxlJobRegistryDao xxlJobRegistryDao; 17 | 18 | @Test 19 | public void test(){ 20 | int ret = xxlJobRegistryDao.registryUpdate("g1", "k1", "v1", new Date()); 21 | if (ret < 1) { 22 | ret = xxlJobRegistryDao.registrySave("g1", "k1", "v1", new Date()); 23 | } 24 | 25 | List list = xxlJobRegistryDao.findAll(1, new Date()); 26 | 27 | int ret2 = xxlJobRegistryDao.removeDead(Arrays.asList(1)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/admin/util/I18nUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.util; 2 | 3 | import com.xxl.job.admin.core.util.I18nUtil; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | /** 8 | * email util test 9 | * 10 | * @author xuxueli 2017-12-22 17:16:23 11 | */ 12 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 13 | public class I18nUtilTest { 14 | 15 | @Test 16 | public void test(){ 17 | System.out.println(I18nUtil.getString("admin_name")); 18 | System.out.println(I18nUtil.getMultString("admin_name", "admin_name_full")); 19 | System.out.println(I18nUtil.getMultString()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /xxl-job-admin/src/test/java/com/xxl/job/adminbiz/AdminBizTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.adminbiz; 2 | 3 | import com.xxl.job.core.biz.AdminBiz; 4 | import com.xxl.job.core.biz.client.AdminBizClient; 5 | import com.xxl.job.core.biz.model.HandleCallbackParam; 6 | import com.xxl.job.core.biz.model.RegistryParam; 7 | import com.xxl.job.core.biz.model.ReturnT; 8 | import com.xxl.job.core.context.XxlJobContext; 9 | import com.xxl.job.core.enums.RegistryConfig; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertTrue; 16 | 17 | /** 18 | * admin api test 19 | * 20 | * @author xuxueli 2017-07-28 22:14:52 21 | */ 22 | public class AdminBizTest { 23 | 24 | // admin-client 25 | private static String addressUrl = "http://127.0.0.1:8080/xxl-job-admin/"; 26 | private static String accessToken = null; 27 | 28 | 29 | @Test 30 | public void callback() throws Exception { 31 | AdminBiz adminBiz = new AdminBizClient(addressUrl, accessToken); 32 | 33 | HandleCallbackParam param = new HandleCallbackParam(); 34 | param.setLogId(1); 35 | param.setHandleCode(XxlJobContext.HANDLE_COCE_SUCCESS); 36 | 37 | List callbackParamList = Arrays.asList(param); 38 | 39 | ReturnT returnT = adminBiz.callback(callbackParamList); 40 | 41 | assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE); 42 | } 43 | 44 | /** 45 | * registry executor 46 | * 47 | * @throws Exception 48 | */ 49 | @Test 50 | public void registry() throws Exception { 51 | AdminBiz adminBiz = new AdminBizClient(addressUrl, accessToken); 52 | 53 | RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), "xxl-job-executor-example", "127.0.0.1:9999"); 54 | ReturnT returnT = adminBiz.registry(registryParam); 55 | 56 | assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE); 57 | } 58 | 59 | /** 60 | * registry executor remove 61 | * 62 | * @throws Exception 63 | */ 64 | @Test 65 | public void registryRemove() throws Exception { 66 | AdminBiz adminBiz = new AdminBizClient(addressUrl, accessToken); 67 | 68 | RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), "xxl-job-executor-example", "127.0.0.1:9999"); 69 | ReturnT returnT = adminBiz.registryRemove(registryParam); 70 | 71 | assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE); 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /xxl-job-core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.xuxueli 6 | xxl-job 7 | 2.3.0 8 | 9 | xxl-job-core 10 | jar 11 | 12 | ${project.artifactId} 13 | A distributed task scheduling framework. 14 | https://www.xuxueli.com/ 15 | 16 | 17 | 18 | com.google.code.gson 19 | gson 20 | ${gson.version} 21 | 22 | 23 | 24 | 25 | 26 | org.codehaus.groovy 27 | groovy 28 | ${groovy.version} 29 | 30 | 31 | 32 | 33 | org.springframework 34 | spring-context 35 | ${spring.version} 36 | provided 37 | 38 | 39 | 40 | 41 | org.springframework 42 | spring-web 43 | ${spring.version} 44 | provided 45 | 46 | 47 | 48 | 49 | 50 | org.slf4j 51 | slf4j-api 52 | ${slf4j-api.version} 53 | 54 | 55 | 56 | 57 | javax.annotation 58 | javax.annotation-api 59 | ${javax.annotation-api.version} 60 | provided 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/AdminBiz.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz; 2 | 3 | import com.xxl.job.core.biz.model.HandleCallbackParam; 4 | import com.xxl.job.core.biz.model.RegistryParam; 5 | import com.xxl.job.core.biz.model.ReturnT; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author xuxueli 2017-07-27 21:52:49 11 | */ 12 | public interface AdminBiz { 13 | 14 | 15 | // ---------------------- callback ---------------------- 16 | 17 | /** 18 | * callback 19 | * 20 | * @param callbackParamList 21 | * @return 22 | */ 23 | public ReturnT callback(List callbackParamList); 24 | 25 | 26 | // ---------------------- registry ---------------------- 27 | 28 | /** 29 | * registry 30 | * 31 | * @param registryParam 32 | * @return 33 | */ 34 | public ReturnT registry(RegistryParam registryParam); 35 | 36 | /** 37 | * registry remove 38 | * 39 | * @param registryParam 40 | * @return 41 | */ 42 | public ReturnT registryRemove(RegistryParam registryParam); 43 | 44 | 45 | // ---------------------- biz (custome) ---------------------- 46 | // group、job ... manage 47 | 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/ExecutorBiz.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz; 2 | 3 | import com.xxl.job.core.biz.model.*; 4 | 5 | /** 6 | * Created by xuxueli on 17/3/1. 7 | */ 8 | public interface ExecutorBiz { 9 | 10 | /** 11 | * beat 12 | * @return 13 | */ 14 | public ReturnT beat(); 15 | 16 | /** 17 | * idle beat 18 | * 19 | * @param idleBeatParam 20 | * @return 21 | */ 22 | public ReturnT idleBeat(IdleBeatParam idleBeatParam); 23 | 24 | /** 25 | * run 26 | * @param triggerParam 27 | * @return 28 | */ 29 | public ReturnT run(TriggerParam triggerParam); 30 | 31 | /** 32 | * kill 33 | * @param killParam 34 | * @return 35 | */ 36 | public ReturnT kill(KillParam killParam); 37 | 38 | /** 39 | * log 40 | * @param logParam 41 | * @return 42 | */ 43 | public ReturnT log(LogParam logParam); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/client/AdminBizClient.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.client; 2 | 3 | import com.xxl.job.core.biz.AdminBiz; 4 | import com.xxl.job.core.biz.model.HandleCallbackParam; 5 | import com.xxl.job.core.biz.model.RegistryParam; 6 | import com.xxl.job.core.biz.model.ReturnT; 7 | import com.xxl.job.core.util.XxlJobRemotingUtil; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * admin api test 13 | * 14 | * @author xuxueli 2017-07-28 22:14:52 15 | */ 16 | public class AdminBizClient implements AdminBiz { 17 | 18 | public AdminBizClient() { 19 | } 20 | public AdminBizClient(String addressUrl, String accessToken) { 21 | this.addressUrl = addressUrl; 22 | this.accessToken = accessToken; 23 | 24 | // valid 25 | if (!this.addressUrl.endsWith("/")) { 26 | this.addressUrl = this.addressUrl + "/"; 27 | } 28 | } 29 | 30 | private String addressUrl ; 31 | private String accessToken; 32 | private int timeout = 3; 33 | 34 | 35 | @Override 36 | public ReturnT callback(List callbackParamList) { 37 | return XxlJobRemotingUtil.postBody(addressUrl+"api/callback", accessToken, timeout, callbackParamList, String.class); 38 | } 39 | 40 | @Override 41 | public ReturnT registry(RegistryParam registryParam) { 42 | return XxlJobRemotingUtil.postBody(addressUrl + "api/registry", accessToken, timeout, registryParam, String.class); 43 | } 44 | 45 | @Override 46 | public ReturnT registryRemove(RegistryParam registryParam) { 47 | return XxlJobRemotingUtil.postBody(addressUrl + "api/registryRemove", accessToken, timeout, registryParam, String.class); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/client/ExecutorBizClient.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.client; 2 | 3 | import com.xxl.job.core.biz.ExecutorBiz; 4 | import com.xxl.job.core.biz.model.*; 5 | import com.xxl.job.core.util.XxlJobRemotingUtil; 6 | 7 | /** 8 | * admin api test 9 | * 10 | * @author xuxueli 2017-07-28 22:14:52 11 | */ 12 | public class ExecutorBizClient implements ExecutorBiz { 13 | 14 | public ExecutorBizClient() { 15 | } 16 | public ExecutorBizClient(String addressUrl, String accessToken) { 17 | this.addressUrl = addressUrl; 18 | this.accessToken = accessToken; 19 | 20 | // valid 21 | if (!this.addressUrl.endsWith("/")) { 22 | this.addressUrl = this.addressUrl + "/"; 23 | } 24 | } 25 | 26 | private String addressUrl ; 27 | private String accessToken; 28 | private int timeout = 3; 29 | 30 | 31 | @Override 32 | public ReturnT beat() { 33 | return XxlJobRemotingUtil.postBody(addressUrl+"xxl-job/beat", accessToken, timeout, "", String.class); 34 | } 35 | 36 | @Override 37 | public ReturnT idleBeat(IdleBeatParam idleBeatParam){ 38 | return XxlJobRemotingUtil.postBody(addressUrl+"xxl-job/idleBeat", accessToken, timeout, idleBeatParam, String.class); 39 | } 40 | 41 | @Override 42 | public ReturnT run(TriggerParam triggerParam) { 43 | return XxlJobRemotingUtil.postBody(addressUrl + "xxl-job/run", accessToken, timeout, triggerParam, String.class); 44 | } 45 | 46 | @Override 47 | public ReturnT kill(KillParam killParam) { 48 | return XxlJobRemotingUtil.postBody(addressUrl + "xxl-job/kill", accessToken, timeout, killParam, String.class); 49 | } 50 | 51 | @Override 52 | public ReturnT log(LogParam logParam) { 53 | return XxlJobRemotingUtil.postBody(addressUrl + "xxl-job/log", accessToken, timeout, logParam, LogResult.class); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/HandleCallbackParam.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by xuxueli on 17/3/2. 7 | */ 8 | public class HandleCallbackParam implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | private long logId; 12 | private long logDateTim; 13 | 14 | private int handleCode; 15 | private String handleMsg; 16 | 17 | public HandleCallbackParam(){} 18 | public HandleCallbackParam(long logId, long logDateTim, int handleCode, String handleMsg) { 19 | this.logId = logId; 20 | this.logDateTim = logDateTim; 21 | this.handleCode = handleCode; 22 | this.handleMsg = handleMsg; 23 | } 24 | 25 | public long getLogId() { 26 | return logId; 27 | } 28 | 29 | public void setLogId(long logId) { 30 | this.logId = logId; 31 | } 32 | 33 | public long getLogDateTim() { 34 | return logDateTim; 35 | } 36 | 37 | public void setLogDateTim(long logDateTim) { 38 | this.logDateTim = logDateTim; 39 | } 40 | 41 | public int getHandleCode() { 42 | return handleCode; 43 | } 44 | 45 | public void setHandleCode(int handleCode) { 46 | this.handleCode = handleCode; 47 | } 48 | 49 | public String getHandleMsg() { 50 | return handleMsg; 51 | } 52 | 53 | public void setHandleMsg(String handleMsg) { 54 | this.handleMsg = handleMsg; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "HandleCallbackParam{" + 60 | "logId=" + logId + 61 | ", logDateTim=" + logDateTim + 62 | ", handleCode=" + handleCode + 63 | ", handleMsg='" + handleMsg + '\'' + 64 | '}'; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/IdleBeatParam.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author xuxueli 2020-04-11 22:27 7 | */ 8 | public class IdleBeatParam implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | public IdleBeatParam() { 12 | } 13 | public IdleBeatParam(int jobId) { 14 | this.jobId = jobId; 15 | } 16 | 17 | private int jobId; 18 | 19 | 20 | public int getJobId() { 21 | return jobId; 22 | } 23 | 24 | public void setJobId(int jobId) { 25 | this.jobId = jobId; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/KillParam.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author xuxueli 2020-04-11 22:27 7 | */ 8 | public class KillParam implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | public KillParam() { 12 | } 13 | public KillParam(int jobId) { 14 | this.jobId = jobId; 15 | } 16 | 17 | private int jobId; 18 | 19 | 20 | public int getJobId() { 21 | return jobId; 22 | } 23 | 24 | public void setJobId(int jobId) { 25 | this.jobId = jobId; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/LogParam.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author xuxueli 2020-04-11 22:27 7 | */ 8 | public class LogParam implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | public LogParam() { 12 | } 13 | public LogParam(long logDateTim, long logId, int fromLineNum) { 14 | this.logDateTim = logDateTim; 15 | this.logId = logId; 16 | this.fromLineNum = fromLineNum; 17 | } 18 | 19 | private long logDateTim; 20 | private long logId; 21 | private int fromLineNum; 22 | 23 | public long getLogDateTim() { 24 | return logDateTim; 25 | } 26 | 27 | public void setLogDateTim(long logDateTim) { 28 | this.logDateTim = logDateTim; 29 | } 30 | 31 | public long getLogId() { 32 | return logId; 33 | } 34 | 35 | public void setLogId(long logId) { 36 | this.logId = logId; 37 | } 38 | 39 | public int getFromLineNum() { 40 | return fromLineNum; 41 | } 42 | 43 | public void setFromLineNum(int fromLineNum) { 44 | this.fromLineNum = fromLineNum; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/LogResult.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by xuxueli on 17/3/23. 7 | */ 8 | public class LogResult implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | public LogResult() { 12 | } 13 | public LogResult(int fromLineNum, int toLineNum, String logContent, boolean isEnd) { 14 | this.fromLineNum = fromLineNum; 15 | this.toLineNum = toLineNum; 16 | this.logContent = logContent; 17 | this.isEnd = isEnd; 18 | } 19 | 20 | private int fromLineNum; 21 | private int toLineNum; 22 | private String logContent; 23 | private boolean isEnd; 24 | 25 | public int getFromLineNum() { 26 | return fromLineNum; 27 | } 28 | 29 | public void setFromLineNum(int fromLineNum) { 30 | this.fromLineNum = fromLineNum; 31 | } 32 | 33 | public int getToLineNum() { 34 | return toLineNum; 35 | } 36 | 37 | public void setToLineNum(int toLineNum) { 38 | this.toLineNum = toLineNum; 39 | } 40 | 41 | public String getLogContent() { 42 | return logContent; 43 | } 44 | 45 | public void setLogContent(String logContent) { 46 | this.logContent = logContent; 47 | } 48 | 49 | public boolean isEnd() { 50 | return isEnd; 51 | } 52 | 53 | public void setEnd(boolean end) { 54 | isEnd = end; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/RegistryParam.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by xuxueli on 2017-05-10 20:22:42 7 | */ 8 | public class RegistryParam implements Serializable { 9 | private static final long serialVersionUID = 42L; 10 | 11 | private String registryGroup; 12 | private String registryKey; 13 | private String registryValue; 14 | 15 | public RegistryParam(){} 16 | public RegistryParam(String registryGroup, String registryKey, String registryValue) { 17 | this.registryGroup = registryGroup; 18 | this.registryKey = registryKey; 19 | this.registryValue = registryValue; 20 | } 21 | 22 | public String getRegistryGroup() { 23 | return registryGroup; 24 | } 25 | 26 | public void setRegistryGroup(String registryGroup) { 27 | this.registryGroup = registryGroup; 28 | } 29 | 30 | public String getRegistryKey() { 31 | return registryKey; 32 | } 33 | 34 | public void setRegistryKey(String registryKey) { 35 | this.registryKey = registryKey; 36 | } 37 | 38 | public String getRegistryValue() { 39 | return registryValue; 40 | } 41 | 42 | public void setRegistryValue(String registryValue) { 43 | this.registryValue = registryValue; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "RegistryParam{" + 49 | "registryGroup='" + registryGroup + '\'' + 50 | ", registryKey='" + registryKey + '\'' + 51 | ", registryValue='" + registryValue + '\'' + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/biz/model/ReturnT.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.biz.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * common return 7 | * @author xuxueli 2015-12-4 16:32:31 8 | * @param 9 | */ 10 | public class ReturnT implements Serializable { 11 | public static final long serialVersionUID = 42L; 12 | 13 | public static final int SUCCESS_CODE = 200; 14 | public static final int FAIL_CODE = 500; 15 | 16 | public static final ReturnT SUCCESS = new ReturnT(null); 17 | public static final ReturnT FAIL = new ReturnT(FAIL_CODE, null); 18 | 19 | private int code; 20 | private String msg; 21 | private T content; 22 | 23 | public ReturnT(){} 24 | public ReturnT(int code, String msg) { 25 | this.code = code; 26 | this.msg = msg; 27 | } 28 | public ReturnT(T content) { 29 | this.code = SUCCESS_CODE; 30 | this.content = content; 31 | } 32 | 33 | public int getCode() { 34 | return code; 35 | } 36 | public void setCode(int code) { 37 | this.code = code; 38 | } 39 | public String getMsg() { 40 | return msg; 41 | } 42 | public void setMsg(String msg) { 43 | this.msg = msg; 44 | } 45 | public T getContent() { 46 | return content; 47 | } 48 | public void setContent(T content) { 49 | this.content = content; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "ReturnT [code=" + code + ", msg=" + msg + ", content=" + content + "]"; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/config/Config.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.config; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * @author kdyzm 8 | * @date 2021/5/7 9 | */ 10 | @Configuration 11 | @ComponentScan(basePackages = {"com.xxl.job.core.controller"}) 12 | public class Config { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/context/XxlJobContext.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.context; 2 | 3 | /** 4 | * xxl-job context 5 | * 6 | * @author xuxueli 2020-05-21 7 | * [Dear hj] 8 | */ 9 | public class XxlJobContext { 10 | 11 | public static final int HANDLE_COCE_SUCCESS = 200; 12 | public static final int HANDLE_COCE_FAIL = 500; 13 | public static final int HANDLE_COCE_TIMEOUT = 502; 14 | 15 | // ---------------------- base info ---------------------- 16 | 17 | /** 18 | * job id 19 | */ 20 | private final long jobId; 21 | 22 | /** 23 | * job param 24 | */ 25 | private final String jobParam; 26 | 27 | // ---------------------- for log ---------------------- 28 | 29 | /** 30 | * job log filename 31 | */ 32 | private final String jobLogFileName; 33 | 34 | // ---------------------- for shard ---------------------- 35 | 36 | /** 37 | * shard index 38 | */ 39 | private final int shardIndex; 40 | 41 | /** 42 | * shard total 43 | */ 44 | private final int shardTotal; 45 | 46 | // ---------------------- for handle ---------------------- 47 | 48 | /** 49 | * handleCode:The result status of job execution 50 | * 51 | * 200 : success 52 | * 500 : fail 53 | * 502 : timeout 54 | * 55 | */ 56 | private int handleCode; 57 | 58 | /** 59 | * handleMsg:The simple log msg of job execution 60 | */ 61 | private String handleMsg; 62 | 63 | 64 | public XxlJobContext(long jobId, String jobParam, String jobLogFileName, int shardIndex, int shardTotal) { 65 | this.jobId = jobId; 66 | this.jobParam = jobParam; 67 | this.jobLogFileName = jobLogFileName; 68 | this.shardIndex = shardIndex; 69 | this.shardTotal = shardTotal; 70 | 71 | this.handleCode = HANDLE_COCE_SUCCESS; // default success 72 | } 73 | 74 | public long getJobId() { 75 | return jobId; 76 | } 77 | 78 | public String getJobParam() { 79 | return jobParam; 80 | } 81 | 82 | public String getJobLogFileName() { 83 | return jobLogFileName; 84 | } 85 | 86 | public int getShardIndex() { 87 | return shardIndex; 88 | } 89 | 90 | public int getShardTotal() { 91 | return shardTotal; 92 | } 93 | 94 | public void setHandleCode(int handleCode) { 95 | this.handleCode = handleCode; 96 | } 97 | 98 | public int getHandleCode() { 99 | return handleCode; 100 | } 101 | 102 | public void setHandleMsg(String handleMsg) { 103 | this.handleMsg = handleMsg; 104 | } 105 | 106 | public String getHandleMsg() { 107 | return handleMsg; 108 | } 109 | 110 | // ---------------------- tool ---------------------- 111 | 112 | private static InheritableThreadLocal contextHolder = new InheritableThreadLocal(); // support for child thread of job handler) 113 | 114 | public static void setXxlJobContext(XxlJobContext xxlJobContext){ 115 | contextHolder.set(xxlJobContext); 116 | } 117 | 118 | public static XxlJobContext getXxlJobContext(){ 119 | return contextHolder.get(); 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/controller/XxlJobController.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.controller; 2 | 3 | import com.google.gson.Gson; 4 | import com.xxl.job.core.biz.impl.ExecutorBizImpl; 5 | import com.xxl.job.core.biz.model.*; 6 | import groovy.util.logging.Slf4j; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | /** 15 | * @author kdyzm 16 | * @date 2021/5/7 17 | */ 18 | @RestController 19 | @RequestMapping("/xxl-job") 20 | public class XxlJobController { 21 | 22 | private static final Logger log = LoggerFactory.getLogger(XxlJobController.class); 23 | 24 | @PostMapping("/beat") 25 | public ReturnT beat() { 26 | log.debug("接收到beat请求"); 27 | return new ExecutorBizImpl().beat(); 28 | } 29 | 30 | @PostMapping("/idleBeat") 31 | public ReturnT idleBeat(@RequestBody IdleBeatParam param) { 32 | log.debug("接收到idleBeat请求,{}",new Gson().toJson(param)); 33 | return new ExecutorBizImpl().idleBeat(param); 34 | } 35 | 36 | @PostMapping("/run") 37 | public ReturnT run(@RequestBody TriggerParam param) { 38 | log.debug("接收到run请求,{}",new Gson().toJson(param)); 39 | return new ExecutorBizImpl().run(param); 40 | } 41 | 42 | @PostMapping("/kill") 43 | public ReturnT kill(@RequestBody KillParam param) { 44 | log.debug("接收到kill请求,{}",new Gson().toJson(param)); 45 | return new ExecutorBizImpl().kill(param); 46 | } 47 | 48 | @PostMapping("/log") 49 | public ReturnT log(@RequestBody LogParam param) { 50 | return new ExecutorBizImpl().log(param); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/enums/ExecutorBlockStrategyEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.enums; 2 | 3 | /** 4 | * Created by xuxueli on 17/5/9. 5 | */ 6 | public enum ExecutorBlockStrategyEnum { 7 | 8 | SERIAL_EXECUTION("Serial execution"), 9 | /*CONCURRENT_EXECUTION("并行"),*/ 10 | DISCARD_LATER("Discard Later"), 11 | COVER_EARLY("Cover Early"); 12 | 13 | private String title; 14 | private ExecutorBlockStrategyEnum (String title) { 15 | this.title = title; 16 | } 17 | 18 | public void setTitle(String title) { 19 | this.title = title; 20 | } 21 | public String getTitle() { 22 | return title; 23 | } 24 | 25 | public static ExecutorBlockStrategyEnum match(String name, ExecutorBlockStrategyEnum defaultItem) { 26 | if (name != null) { 27 | for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) { 28 | if (item.name().equals(name)) { 29 | return item; 30 | } 31 | } 32 | } 33 | return defaultItem; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/enums/RegistryConfig.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.enums; 2 | 3 | /** 4 | * Created by xuxueli on 17/5/10. 5 | */ 6 | public class RegistryConfig { 7 | 8 | public static final int BEAT_TIMEOUT = 30; 9 | public static final int DEAD_TIMEOUT = BEAT_TIMEOUT * 3; 10 | 11 | public enum RegistType{ EXECUTOR, ADMIN } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueFactory.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.glue; 2 | 3 | import com.xxl.job.core.glue.impl.SpringGlueFactory; 4 | import com.xxl.job.core.handler.IJobHandler; 5 | import groovy.lang.GroovyClassLoader; 6 | 7 | import java.math.BigInteger; 8 | import java.security.MessageDigest; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.ConcurrentMap; 11 | 12 | /** 13 | * glue factory, product class/object by name 14 | * 15 | * @author xuxueli 2016-1-2 20:02:27 16 | */ 17 | public class GlueFactory { 18 | 19 | 20 | private static GlueFactory glueFactory = new GlueFactory(); 21 | public static GlueFactory getInstance(){ 22 | return glueFactory; 23 | } 24 | public static void refreshInstance(int type){ 25 | if (type == 0) { 26 | glueFactory = new GlueFactory(); 27 | } else if (type == 1) { 28 | glueFactory = new SpringGlueFactory(); 29 | } 30 | } 31 | 32 | 33 | /** 34 | * groovy class loader 35 | */ 36 | private GroovyClassLoader groovyClassLoader = new GroovyClassLoader(); 37 | private ConcurrentMap> CLASS_CACHE = new ConcurrentHashMap<>(); 38 | 39 | /** 40 | * load new instance, prototype 41 | * 42 | * @param codeSource 43 | * @return 44 | * @throws Exception 45 | */ 46 | public IJobHandler loadNewInstance(String codeSource) throws Exception{ 47 | if (codeSource!=null && codeSource.trim().length()>0) { 48 | Class clazz = getCodeSourceClass(codeSource); 49 | if (clazz != null) { 50 | Object instance = clazz.newInstance(); 51 | if (instance!=null) { 52 | if (instance instanceof IJobHandler) { 53 | this.injectService(instance); 54 | return (IJobHandler) instance; 55 | } else { 56 | throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, " 57 | + "cannot convert from instance["+ instance.getClass() +"] to IJobHandler"); 58 | } 59 | } 60 | } 61 | } 62 | throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null"); 63 | } 64 | private Class getCodeSourceClass(String codeSource){ 65 | try { 66 | // md5 67 | byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes()); 68 | String md5Str = new BigInteger(1, md5).toString(16); 69 | 70 | Class clazz = CLASS_CACHE.get(md5Str); 71 | if(clazz == null){ 72 | clazz = groovyClassLoader.parseClass(codeSource); 73 | CLASS_CACHE.putIfAbsent(md5Str, clazz); 74 | } 75 | return clazz; 76 | } catch (Exception e) { 77 | return groovyClassLoader.parseClass(codeSource); 78 | } 79 | } 80 | 81 | /** 82 | * inject service of bean field 83 | * 84 | * @param instance 85 | */ 86 | public void injectService(Object instance) { 87 | // do something 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.glue; 2 | 3 | /** 4 | * Created by xuxueli on 17/4/26. 5 | */ 6 | public enum GlueTypeEnum { 7 | 8 | BEAN("BEAN", false, null, null), 9 | GLUE_GROOVY("GLUE(Java)", false, null, null), 10 | GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"), 11 | GLUE_PYTHON("GLUE(Python)", true, "python", ".py"), 12 | GLUE_PHP("GLUE(PHP)", true, "php", ".php"), 13 | GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js"), 14 | GLUE_POWERSHELL("GLUE(PowerShell)", true, "powershell", ".ps1"); 15 | 16 | private String desc; 17 | private boolean isScript; 18 | private String cmd; 19 | private String suffix; 20 | 21 | private GlueTypeEnum(String desc, boolean isScript, String cmd, String suffix) { 22 | this.desc = desc; 23 | this.isScript = isScript; 24 | this.cmd = cmd; 25 | this.suffix = suffix; 26 | } 27 | 28 | public String getDesc() { 29 | return desc; 30 | } 31 | 32 | public boolean isScript() { 33 | return isScript; 34 | } 35 | 36 | public String getCmd() { 37 | return cmd; 38 | } 39 | 40 | public String getSuffix() { 41 | return suffix; 42 | } 43 | 44 | public static GlueTypeEnum match(String name){ 45 | for (GlueTypeEnum item: GlueTypeEnum.values()) { 46 | if (item.name().equals(name)) { 47 | return item; 48 | } 49 | } 50 | return null; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/glue/impl/SpringGlueFactory.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.glue.impl; 2 | 3 | import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; 4 | import com.xxl.job.core.glue.GlueFactory; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.core.annotation.AnnotationUtils; 10 | 11 | import javax.annotation.Resource; 12 | import java.lang.reflect.Field; 13 | import java.lang.reflect.Modifier; 14 | 15 | /** 16 | * @author xuxueli 2018-11-01 17 | */ 18 | public class SpringGlueFactory extends GlueFactory { 19 | private static Logger logger = LoggerFactory.getLogger(SpringGlueFactory.class); 20 | 21 | 22 | /** 23 | * inject action of spring 24 | * @param instance 25 | */ 26 | @Override 27 | public void injectService(Object instance){ 28 | if (instance==null) { 29 | return; 30 | } 31 | 32 | if (XxlJobSpringExecutor.getApplicationContext() == null) { 33 | return; 34 | } 35 | 36 | Field[] fields = instance.getClass().getDeclaredFields(); 37 | for (Field field : fields) { 38 | if (Modifier.isStatic(field.getModifiers())) { 39 | continue; 40 | } 41 | 42 | Object fieldBean = null; 43 | // with bean-id, bean could be found by both @Resource and @Autowired, or bean could only be found by @Autowired 44 | 45 | if (AnnotationUtils.getAnnotation(field, Resource.class) != null) { 46 | try { 47 | Resource resource = AnnotationUtils.getAnnotation(field, Resource.class); 48 | if (resource.name()!=null && resource.name().length()>0){ 49 | fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(resource.name()); 50 | } else { 51 | fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getName()); 52 | } 53 | } catch (Exception e) { 54 | } 55 | if (fieldBean==null ) { 56 | fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType()); 57 | } 58 | } else if (AnnotationUtils.getAnnotation(field, Autowired.class) != null) { 59 | Qualifier qualifier = AnnotationUtils.getAnnotation(field, Qualifier.class); 60 | if (qualifier!=null && qualifier.value()!=null && qualifier.value().length()>0) { 61 | fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(qualifier.value()); 62 | } else { 63 | fieldBean = XxlJobSpringExecutor.getApplicationContext().getBean(field.getType()); 64 | } 65 | } 66 | 67 | if (fieldBean!=null) { 68 | field.setAccessible(true); 69 | try { 70 | field.set(instance, fieldBean); 71 | } catch (IllegalArgumentException e) { 72 | logger.error(e.getMessage(), e); 73 | } catch (IllegalAccessException e) { 74 | logger.error(e.getMessage(), e); 75 | } 76 | } 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.handler; 2 | 3 | /** 4 | * job handler 5 | * 6 | * @author xuxueli 2015-12-19 19:06:38 7 | */ 8 | public abstract class IJobHandler { 9 | 10 | 11 | /** 12 | * execute handler, invoked when executor receives a scheduling request 13 | * 14 | * @throws Exception 15 | */ 16 | public abstract void execute() throws Exception; 17 | 18 | 19 | /*@Deprecated 20 | public abstract ReturnT execute(String param) throws Exception;*/ 21 | 22 | /** 23 | * init handler, invoked when JobThread init 24 | */ 25 | public void init() throws Exception { 26 | // do something 27 | } 28 | 29 | 30 | /** 31 | * destroy handler, invoked when JobThread destroy 32 | */ 33 | public void destroy() throws Exception { 34 | // do something 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/JobHandler.java: -------------------------------------------------------------------------------- 1 | //package com.xxl.job.core.handler.annotation; 2 | // 3 | //import java.lang.annotation.ElementType; 4 | //import java.lang.annotation.Inherited; 5 | //import java.lang.annotation.Retention; 6 | //import java.lang.annotation.RetentionPolicy; 7 | //import java.lang.annotation.Target; 8 | // 9 | ///** 10 | // * annotation for job handler 11 | // * 12 | // * will be replaced by {@link com.xxl.job.core.handler.annotation.XxlJob} 13 | // * 14 | // * @author 2016-5-17 21:06:49 15 | // */ 16 | //@Target({ElementType.TYPE}) 17 | //@Retention(RetentionPolicy.RUNTIME) 18 | //@Inherited 19 | //@Deprecated 20 | //public @interface JobHandler { 21 | // 22 | // String value(); 23 | // 24 | //} 25 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/annotation/XxlJob.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.handler.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * annotation for method jobhandler 7 | * 8 | * @author xuxueli 2019-12-11 20:50:13 9 | */ 10 | @Target({ElementType.METHOD}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Inherited 13 | public @interface XxlJob { 14 | 15 | /** 16 | * jobhandler name 17 | */ 18 | String value(); 19 | 20 | /** 21 | * init handler, invoked when JobThread init 22 | */ 23 | String init() default ""; 24 | 25 | /** 26 | * destroy handler, invoked when JobThread destroy 27 | */ 28 | String destroy() default ""; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/GlueJobHandler.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.handler.impl; 2 | 3 | import com.xxl.job.core.context.XxlJobHelper; 4 | import com.xxl.job.core.handler.IJobHandler; 5 | 6 | /** 7 | * glue job handler 8 | * 9 | * @author xuxueli 2016-5-19 21:05:45 10 | */ 11 | public class GlueJobHandler extends IJobHandler { 12 | 13 | private long glueUpdatetime; 14 | private IJobHandler jobHandler; 15 | public GlueJobHandler(IJobHandler jobHandler, long glueUpdatetime) { 16 | this.jobHandler = jobHandler; 17 | this.glueUpdatetime = glueUpdatetime; 18 | } 19 | public long getGlueUpdatetime() { 20 | return glueUpdatetime; 21 | } 22 | 23 | @Override 24 | public void execute() throws Exception { 25 | XxlJobHelper.log("----------- glue.version:"+ glueUpdatetime +" -----------"); 26 | jobHandler.execute(); 27 | } 28 | 29 | @Override 30 | public void init() throws Exception { 31 | this.jobHandler.init(); 32 | } 33 | 34 | @Override 35 | public void destroy() throws Exception { 36 | this.jobHandler.destroy(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/MethodJobHandler.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.handler.impl; 2 | 3 | import com.xxl.job.core.context.XxlJobContext; 4 | import com.xxl.job.core.handler.IJobHandler; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * @author xuxueli 2019-12-11 21:12:18 10 | */ 11 | public class MethodJobHandler extends IJobHandler { 12 | 13 | private final Object target; 14 | private final Method method; 15 | private Method initMethod; 16 | private Method destroyMethod; 17 | 18 | public MethodJobHandler(Object target, Method method, Method initMethod, Method destroyMethod) { 19 | this.target = target; 20 | this.method = method; 21 | 22 | this.initMethod = initMethod; 23 | this.destroyMethod = destroyMethod; 24 | } 25 | 26 | @Override 27 | public void execute() throws Exception { 28 | Class[] paramTypes = method.getParameterTypes(); 29 | if (paramTypes.length > 0) { 30 | String jobParam = XxlJobContext.getXxlJobContext().getJobParam(); 31 | Object[] objs=new Object[paramTypes.length]; 32 | if (null != jobParam && !"".equalsIgnoreCase(jobParam.trim())) { 33 | objs[0] = jobParam; 34 | } 35 | // method-param can not be primitive-types 36 | method.invoke(target, objs); 37 | } else { 38 | method.invoke(target); 39 | } 40 | } 41 | 42 | @Override 43 | public void init() throws Exception { 44 | if(initMethod != null) { 45 | initMethod.invoke(target); 46 | } 47 | } 48 | 49 | @Override 50 | public void destroy() throws Exception { 51 | if(destroyMethod != null) { 52 | destroyMethod.invoke(target); 53 | } 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return super.toString()+"["+ target.getClass() + "#" + method.getName() +"]"; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.handler.impl; 2 | 3 | import com.xxl.job.core.context.XxlJobContext; 4 | import com.xxl.job.core.context.XxlJobHelper; 5 | import com.xxl.job.core.glue.GlueTypeEnum; 6 | import com.xxl.job.core.handler.IJobHandler; 7 | import com.xxl.job.core.log.XxlJobFileAppender; 8 | import com.xxl.job.core.util.ScriptUtil; 9 | 10 | import java.io.File; 11 | 12 | /** 13 | * Created by xuxueli on 17/4/27. 14 | */ 15 | public class ScriptJobHandler extends IJobHandler { 16 | 17 | private int jobId; 18 | private long glueUpdatetime; 19 | private String gluesource; 20 | private GlueTypeEnum glueType; 21 | 22 | public ScriptJobHandler(int jobId, long glueUpdatetime, String gluesource, GlueTypeEnum glueType){ 23 | this.jobId = jobId; 24 | this.glueUpdatetime = glueUpdatetime; 25 | this.gluesource = gluesource; 26 | this.glueType = glueType; 27 | 28 | // clean old script file 29 | File glueSrcPath = new File(XxlJobFileAppender.getGlueSrcPath()); 30 | if (glueSrcPath.exists()) { 31 | File[] glueSrcFileList = glueSrcPath.listFiles(); 32 | if (glueSrcFileList!=null && glueSrcFileList.length>0) { 33 | for (File glueSrcFileItem : glueSrcFileList) { 34 | if (glueSrcFileItem.getName().startsWith(String.valueOf(jobId)+"_")) { 35 | glueSrcFileItem.delete(); 36 | } 37 | } 38 | } 39 | } 40 | 41 | } 42 | 43 | public long getGlueUpdatetime() { 44 | return glueUpdatetime; 45 | } 46 | 47 | @Override 48 | public void execute() throws Exception { 49 | 50 | if (!glueType.isScript()) { 51 | XxlJobHelper.handleFail("glueType["+ glueType +"] invalid."); 52 | return; 53 | } 54 | 55 | // cmd 56 | String cmd = glueType.getCmd(); 57 | 58 | // make script file 59 | String scriptFileName = XxlJobFileAppender.getGlueSrcPath() 60 | .concat(File.separator) 61 | .concat(String.valueOf(jobId)) 62 | .concat("_") 63 | .concat(String.valueOf(glueUpdatetime)) 64 | .concat(glueType.getSuffix()); 65 | File scriptFile = new File(scriptFileName); 66 | if (!scriptFile.exists()) { 67 | ScriptUtil.markScriptFile(scriptFileName, gluesource); 68 | } 69 | 70 | // log file 71 | String logFileName = XxlJobContext.getXxlJobContext().getJobLogFileName(); 72 | 73 | // script params:0=param、1=分片序号、2=分片总数 74 | String[] scriptParams = new String[3]; 75 | scriptParams[0] = XxlJobHelper.getJobParam(); 76 | scriptParams[1] = String.valueOf(XxlJobContext.getXxlJobContext().getShardIndex()); 77 | scriptParams[2] = String.valueOf(XxlJobContext.getXxlJobContext().getShardTotal()); 78 | 79 | // invoke 80 | XxlJobHelper.log("----------- script file:"+ scriptFileName +" -----------"); 81 | int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, scriptParams); 82 | 83 | if (exitValue == 0) { 84 | XxlJobHelper.handleSuccess(); 85 | return; 86 | } else { 87 | XxlJobHelper.handleFail("script exit value("+exitValue+") is failed"); 88 | return ; 89 | } 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/server/EmbedServer.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.server; 2 | 3 | import com.xxl.job.core.thread.ExecutorRegistryThread; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * Copy from : https://github.com/xuxueli/xxl-rpc 9 | * 10 | * @author xuxueli 2020-04-11 21:25 11 | */ 12 | public class EmbedServer { 13 | private static final Logger logger = LoggerFactory.getLogger(EmbedServer.class); 14 | 15 | public void start(final String address, final int port, final String appname, final String accessToken) { 16 | // start registry 17 | startRegistry(appname, address); 18 | } 19 | 20 | public void stop() throws Exception { 21 | // stop registry 22 | stopRegistry(); 23 | logger.info(">>>>>>>>>>> xxl-job remoting server destroy success."); 24 | } 25 | 26 | // ---------------------- registry ---------------------- 27 | 28 | public void startRegistry(final String appname, final String address) { 29 | // start registry 30 | ExecutorRegistryThread.getInstance().start(appname, address); 31 | } 32 | 33 | public void stopRegistry() { 34 | // stop registry 35 | ExecutorRegistryThread.getInstance().toStop(); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/util/GsonTool.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.util; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.reflect.TypeToken; 6 | 7 | import java.lang.reflect.ParameterizedType; 8 | import java.lang.reflect.Type; 9 | import java.util.List; 10 | 11 | /** 12 | * @author xuxueli 2020-04-11 20:56:31 13 | */ 14 | public class GsonTool { 15 | 16 | private static Gson gson = null; 17 | static { 18 | gson= new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); 19 | } 20 | 21 | /** 22 | * Object 转成 json 23 | * 24 | * @param src 25 | * @return String 26 | */ 27 | public static String toJson(Object src) { 28 | return gson.toJson(src); 29 | } 30 | 31 | /** 32 | * json 转成 特定的cls的Object 33 | * 34 | * @param json 35 | * @param classOfT 36 | * @return 37 | */ 38 | public static T fromJson(String json, Class classOfT) { 39 | return gson.fromJson(json, classOfT); 40 | } 41 | 42 | /** 43 | * json 转成 特定的 rawClass 的Object 44 | * 45 | * @param json 46 | * @param classOfT 47 | * @param argClassOfT 48 | * @return 49 | */ 50 | public static T fromJson(String json, Class classOfT, Class argClassOfT) { 51 | Type type = new ParameterizedType4ReturnT(classOfT, new Class[]{argClassOfT}); 52 | return gson.fromJson(json, type); 53 | } 54 | public static class ParameterizedType4ReturnT implements ParameterizedType { 55 | private final Class raw; 56 | private final Type[] args; 57 | public ParameterizedType4ReturnT(Class raw, Type[] args) { 58 | this.raw = raw; 59 | this.args = args != null ? args : new Type[0]; 60 | } 61 | @Override 62 | public Type[] getActualTypeArguments() { 63 | return args; 64 | } 65 | @Override 66 | public Type getRawType() { 67 | return raw; 68 | } 69 | @Override 70 | public Type getOwnerType() {return null;} 71 | } 72 | 73 | /** 74 | * json 转成 特定的cls的list 75 | * 76 | * @param json 77 | * @param classOfT 78 | * @return 79 | */ 80 | public static List fromJsonList(String json, Class classOfT) { 81 | return gson.fromJson( 82 | json, 83 | new TypeToken>() { 84 | }.getType() 85 | ); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/util/JdkSerializeTool.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.*; 7 | 8 | /** 9 | * @author xuxueli 2020-04-12 0:14:00 10 | */ 11 | public class JdkSerializeTool { 12 | private static Logger logger = LoggerFactory.getLogger(JdkSerializeTool.class); 13 | 14 | 15 | // ------------------------ serialize and unserialize ------------------------ 16 | 17 | /** 18 | * 将对象-->byte[] (由于jedis中不支持直接存储object所以转换成byte[]存入) 19 | * 20 | * @param object 21 | * @return 22 | */ 23 | public static byte[] serialize(Object object) { 24 | ObjectOutputStream oos = null; 25 | ByteArrayOutputStream baos = null; 26 | try { 27 | // 序列化 28 | baos = new ByteArrayOutputStream(); 29 | oos = new ObjectOutputStream(baos); 30 | oos.writeObject(object); 31 | byte[] bytes = baos.toByteArray(); 32 | return bytes; 33 | } catch (Exception e) { 34 | logger.error(e.getMessage(), e); 35 | } finally { 36 | try { 37 | oos.close(); 38 | baos.close(); 39 | } catch (IOException e) { 40 | logger.error(e.getMessage(), e); 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | 47 | /** 48 | * 将byte[] -->Object 49 | * 50 | * @param bytes 51 | * @return 52 | */ 53 | public static Object deserialize(byte[] bytes, Class clazz) { 54 | ByteArrayInputStream bais = null; 55 | try { 56 | // 反序列化 57 | bais = new ByteArrayInputStream(bytes); 58 | ObjectInputStream ois = new ObjectInputStream(bais); 59 | return ois.readObject(); 60 | } catch (Exception e) { 61 | logger.error(e.getMessage(), e); 62 | } finally { 63 | try { 64 | bais.close(); 65 | } catch (IOException e) { 66 | logger.error(e.getMessage(), e); 67 | } 68 | } 69 | return null; 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/util/NetUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.IOException; 7 | import java.net.ServerSocket; 8 | 9 | /** 10 | * net util 11 | * 12 | * @author xuxueli 2017-11-29 17:00:25 13 | */ 14 | public class NetUtil { 15 | private static Logger logger = LoggerFactory.getLogger(NetUtil.class); 16 | 17 | /** 18 | * find avaliable port 19 | * 20 | * @param defaultPort 21 | * @return 22 | */ 23 | public static int findAvailablePort(int defaultPort) { 24 | int portTmp = defaultPort; 25 | while (portTmp < 65535) { 26 | if (!isPortUsed(portTmp)) { 27 | return portTmp; 28 | } else { 29 | portTmp++; 30 | } 31 | } 32 | portTmp = defaultPort--; 33 | while (portTmp > 0) { 34 | if (!isPortUsed(portTmp)) { 35 | return portTmp; 36 | } else { 37 | portTmp--; 38 | } 39 | } 40 | throw new RuntimeException("no available port."); 41 | } 42 | 43 | /** 44 | * check port used 45 | * 46 | * @param port 47 | * @return 48 | */ 49 | public static boolean isPortUsed(int port) { 50 | boolean used = false; 51 | ServerSocket serverSocket = null; 52 | try { 53 | serverSocket = new ServerSocket(port); 54 | used = false; 55 | } catch (IOException e) { 56 | logger.info(">>>>>>>>>>> xxl-rpc, port[{}] is in use.", port); 57 | used = true; 58 | } finally { 59 | if (serverSocket != null) { 60 | try { 61 | serverSocket.close(); 62 | } catch (IOException e) { 63 | logger.info(""); 64 | } 65 | } 66 | } 67 | return used; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/util/ShardingUtil.java: -------------------------------------------------------------------------------- 1 | //package com.xxl.job.core.util; 2 | // 3 | ///** 4 | // * sharding vo 5 | // * @author xuxueli 2017-07-25 21:26:38 6 | // */ 7 | //public class ShardingUtil { 8 | // 9 | // private static InheritableThreadLocal contextHolder = new InheritableThreadLocal(); 10 | // 11 | // public static class ShardingVO { 12 | // 13 | // private int index; // sharding index 14 | // private int total; // sharding total 15 | // 16 | // public ShardingVO(int index, int total) { 17 | // this.index = index; 18 | // this.total = total; 19 | // } 20 | // 21 | // public int getIndex() { 22 | // return index; 23 | // } 24 | // 25 | // public void setIndex(int index) { 26 | // this.index = index; 27 | // } 28 | // 29 | // public int getTotal() { 30 | // return total; 31 | // } 32 | // 33 | // public void setTotal(int total) { 34 | // this.total = total; 35 | // } 36 | // } 37 | // 38 | // public static void setShardingVo(ShardingVO shardingVo){ 39 | // contextHolder.set(shardingVo); 40 | // } 41 | // 42 | // public static ShardingVO getShardingVo(){ 43 | // return contextHolder.get(); 44 | // } 45 | // 46 | //} 47 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/java/com/xxl/job/core/util/ThrowableUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.core.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | 6 | /** 7 | * @author xuxueli 2018-10-20 20:07:26 8 | */ 9 | public class ThrowableUtil { 10 | 11 | /** 12 | * parse error to string 13 | * 14 | * @param e 15 | * @return 16 | */ 17 | public static String toString(Throwable e) { 18 | StringWriter stringWriter = new StringWriter(); 19 | e.printStackTrace(new PrintWriter(stringWriter)); 20 | String errorMsg = stringWriter.toString(); 21 | return errorMsg; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /xxl-job-core/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.xxl.job.core.config.Config -------------------------------------------------------------------------------- /xxl-job-executor-samples/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | com.xuxueli 7 | xxl-job 8 | 2.3.0 9 | 10 | xxl-job-executor-samples 11 | pom 12 | 13 | 14 | xxl-job-executor-sample-frameless 15 | xxl-job-executor-sample-springboot 16 | 17 | 18 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-frameless/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xuxueli 8 | xxl-job-executor-samples 9 | 2.3.0 10 | 11 | xxl-job-executor-sample-frameless 12 | jar 13 | 14 | ${project.artifactId} 15 | Example executor project for spring boot. 16 | https://www.xuxueli.com/ 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.slf4j 24 | slf4j-log4j12 25 | ${slf4j-api.version} 26 | 27 | 28 | 29 | org.junit.jupiter 30 | junit-jupiter-engine 31 | ${junit.version} 32 | test 33 | 34 | 35 | 36 | 37 | com.xuxueli 38 | xxl-job-core 39 | ${project.parent.version} 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/java/com/xxl/job/executor/sample/frameless/FramelessApplication.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.executor.sample.frameless; 2 | 3 | import com.xxl.job.executor.sample.frameless.config.FrameLessXxlJobConfig; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * @author xuxueli 2018-10-31 19:05:43 11 | */ 12 | public class FramelessApplication { 13 | private static Logger logger = LoggerFactory.getLogger(FramelessApplication.class); 14 | 15 | public static void main(String[] args) { 16 | 17 | try { 18 | // start 19 | FrameLessXxlJobConfig.getInstance().initXxlJobExecutor(); 20 | 21 | // Blocks until interrupted 22 | while (true) { 23 | try { 24 | TimeUnit.HOURS.sleep(1); 25 | } catch (InterruptedException e) { 26 | break; 27 | } 28 | } 29 | } catch (Exception e) { 30 | logger.error(e.getMessage(), e); 31 | } finally { 32 | // destory 33 | FrameLessXxlJobConfig.getInstance().destoryXxlJobExecutor(); 34 | } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/main/resources/xxl-job-executor.properties: -------------------------------------------------------------------------------- 1 | ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" 2 | xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin 3 | 4 | ### xxl-job, access token 5 | xxl.job.accessToken= 6 | 7 | ### xxl-job executor appname 8 | xxl.job.executor.appname=xxl-job-executor-sample 9 | ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null 10 | xxl.job.executor.address= 11 | ### xxl-job executor server-info 12 | xxl.job.executor.ip= 13 | xxl.job.executor.port=9998 14 | ### xxl-job executor log-path 15 | xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler 16 | ### xxl-job executor log-retention-days 17 | xxl.job.executor.logretentiondays=30 -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-frameless/src/test/java/com/xxl/job/executor/sample/frameless/test/FramelessApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.executor.sample.frameless.test; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | public class FramelessApplicationTest { 6 | 7 | @Test 8 | public void test(){ 9 | System.out.println("111"); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-slim 2 | MAINTAINER xuxueli 3 | 4 | ENV PARAMS="" 5 | 6 | ENV TZ=PRC 7 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 8 | 9 | ADD target/xxl-job-executor-sample-springboot-*.jar /app.jar 10 | 11 | ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /app.jar $PARAMS"] -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xuxueli 8 | xxl-job-executor-samples 9 | 2.3.0 10 | 11 | xxl-job-executor-sample-springboot 12 | jar 13 | 14 | ${project.artifactId} 15 | Example executor project for spring boot. 16 | https://www.xuxueli.com/ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-parent 27 | ${spring-boot.version} 28 | pom 29 | import 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | test 44 | 45 | 46 | 47 | 48 | com.xuxueli 49 | xxl-job-core 50 | ${project.parent.version} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-maven-plugin 61 | ${spring-boot.version} 62 | 63 | 64 | 65 | repackage 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.executor; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author xuxueli 2018-10-28 00:38:13 8 | */ 9 | @SpringBootApplication 10 | public class XxlJobExecutorApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(XxlJobExecutorApplication.class, args); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.executor.core.config; 2 | 3 | import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * xxl-job config 12 | * 13 | * @author xuxueli 2017-04-28 14 | */ 15 | @Configuration 16 | public class XxlJobConfig { 17 | private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class); 18 | 19 | @Value("${xxl.job.admin.addresses}") 20 | private String adminAddresses; 21 | 22 | @Value("${xxl.job.accessToken}") 23 | private String accessToken; 24 | 25 | @Value("${xxl.job.executor.appname}") 26 | private String appname; 27 | 28 | @Value("${xxl.job.executor.address}") 29 | private String address; 30 | 31 | @Value("${xxl.job.executor.ip}") 32 | private String ip; 33 | 34 | @Value("${xxl.job.executor.port}") 35 | private int port; 36 | 37 | @Value("${xxl.job.executor.logpath}") 38 | private String logPath; 39 | 40 | @Value("${xxl.job.executor.logretentiondays}") 41 | private int logRetentionDays; 42 | 43 | 44 | @Bean 45 | public XxlJobSpringExecutor xxlJobExecutor() { 46 | logger.info(">>>>>>>>>>> xxl-job config init."); 47 | XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); 48 | xxlJobSpringExecutor.setAdminAddresses(adminAddresses); 49 | xxlJobSpringExecutor.setAppname(appname); 50 | xxlJobSpringExecutor.setAddress(address); 51 | xxlJobSpringExecutor.setIp(ip); 52 | xxlJobSpringExecutor.setPort(port); 53 | xxlJobSpringExecutor.setAccessToken(accessToken); 54 | xxlJobSpringExecutor.setLogPath(logPath); 55 | xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); 56 | 57 | return xxlJobSpringExecutor; 58 | } 59 | 60 | /** 61 | * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP; 62 | * 63 | * 1、引入依赖: 64 | * 65 | * org.springframework.cloud 66 | * spring-cloud-commons 67 | * ${version} 68 | * 69 | * 70 | * 2、配置文件,或者容器启动变量 71 | * spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.' 72 | * 73 | * 3、获取IP 74 | * String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); 75 | */ 76 | 77 | 78 | } -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/mvc/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | //package com.xxl.job.executor.mvc.controller; 2 | // 3 | //import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 4 | //import org.springframework.stereotype.Controller; 5 | //import org.springframework.web.bind.annotation.RequestMapping; 6 | //import org.springframework.web.bind.annotation.ResponseBody; 7 | // 8 | //@Controller 9 | //@EnableAutoConfiguration 10 | //public class IndexController { 11 | // 12 | // @RequestMapping("/") 13 | // @ResponseBody 14 | // String index() { 15 | // return "xxl job executor running."; 16 | // } 17 | // 18 | //} -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # web port 2 | server.port=8081 3 | # no web 4 | #spring.main.web-environment=false 5 | 6 | # log config 7 | logging.config=classpath:logback.xml 8 | 9 | 10 | ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" 11 | xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin 12 | 13 | ### xxl-job, access token 14 | xxl.job.accessToken= 15 | 16 | ### xxl-job executor appname 17 | xxl.job.executor.appname=xxl-job-executor-sample 18 | ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null 19 | xxl.job.executor.address= 20 | ### xxl-job executor server-info 21 | xxl.job.executor.ip= 22 | xxl.job.executor.port=${server.port} 23 | ### xxl-job executor log-path 24 | xxl.job.executor.logpath=./logs 25 | ### xxl-job executor log-retention-days 26 | xxl.job.executor.logretentiondays=30 27 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logback 5 | 6 | 7 | 8 | 9 | %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | ${log.path} 15 | 16 | ${log.path}.%d{yyyy-MM-dd}.zip 17 | 18 | 19 | %date %level [%thread] %logger{36} [%file : %line] %msg%n 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/test/java/com/xxl/job/executor/test/XxlJobExecutorExampleBootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.executor.test; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class XxlJobExecutorExampleBootApplicationTests { 8 | 9 | @Test 10 | public void test() { 11 | System.out.println(11); 12 | } 13 | 14 | } --------------------------------------------------------------------------------