Unverified 提交 e4c93174 authored 作者: 许雪里's avatar 许雪里 提交者: GitHub

Merge branch 'master' into master

# for eclipse .idea
/.settings/ .classpath
/.project .project
# for idea
*.iml *.iml
/.idea target/
*/target
.DS_Store .DS_Store
.gitattributes .gitattributes
language: java language: java
jdk: jdk:
- oraclejdk7 - oraclejdk8
install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true
#script: mvn test #script: mvn test
script: mvn -DskipTests=true clean package script: mvn -DskipTests=true clean package
\ No newline at end of file
差异被折叠。
差异被折叠。
CREATE database if NOT EXISTS `xxl-job` default character set utf8 collate utf8_general_ci;
use `xxl-job`;
CREATE TABLE XXL_JOB_QRTZ_JOB_DETAILS CREATE TABLE XXL_JOB_QRTZ_JOB_DETAILS
( (
...@@ -156,7 +160,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` ( ...@@ -156,7 +160,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件', `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略', `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(255) DEFAULT NULL COMMENT '执行器任务参数', `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略', `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略', `executor_fail_strategy` varchar(50) DEFAULT NULL COMMENT '失败处理策略',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型', `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
...@@ -174,7 +178,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` ( ...@@ -174,7 +178,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型', `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址', `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler', `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(255) DEFAULT NULL COMMENT 'executor_param', `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间', `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '调度-结果', `trigger_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '调度-结果',
`trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志', `trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',
...@@ -210,7 +214,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` ( ...@@ -210,7 +214,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` (
`title` varchar(12) NOT NULL COMMENT '执行器名称', `title` varchar(12) NOT NULL COMMENT '执行器名称',
`order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序', `order` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入', `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` varchar(200) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔', `address_list` varchar(512) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId> <artifactId>xxl-job</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
...@@ -20,31 +20,32 @@ ...@@ -20,31 +20,32 @@
<javax.servlet-api.version>3.0.1</javax.servlet-api.version> <javax.servlet-api.version>3.0.1</javax.servlet-api.version>
<jsp-api.version>2.2</jsp-api.version> <jsp-api.version>2.2</jsp-api.version>
<spring.version>3.2.18.RELEASE</spring.version> <spring.version>4.3.13.RELEASE</spring.version>
<jackson-mapper-asl.version>1.9.13</jackson-mapper-asl.version> <jackson.version>2.9.3</jackson.version>
<aspectjweaver.version>1.8.7</aspectjweaver.version> <aspectjweaver.version>1.8.13</aspectjweaver.version>
<slf4j-api.version>1.7.25</slf4j-api.version> <slf4j-api.version>1.7.25</slf4j-api.version>
<freemarker.version>2.3.20</freemarker.version> <freemarker.version>2.3.23</freemarker.version>
<junit.version>4.11</junit.version> <junit.version>4.12</junit.version>
<jetty-server.version>9.2.22.v20170606</jetty-server.version>
<hessian.version>4.0.51</hessian.version>
<httpclient.version>4.5.4</httpclient.version>
<jetty-server.version>9.4.6.v20170531</jetty-server.version>
<hessian.version>4.0.38</hessian.version>
<httpclient.version>4.3.6</httpclient.version>
<commons-exec.version>1.3</commons-exec.version> <commons-exec.version>1.3</commons-exec.version>
<commons-beanutils.version>1.9.2</commons-beanutils.version> <commons-collections4.version>4.1</commons-collections4.version>
<commons-lang.version>2.6</commons-lang.version> <commons-lang3.version>3.7</commons-lang3.version>
<commons-email.version>1.5</commons-email.version>
<c3p0.version>0.9.5.2</c3p0.version> <c3p0.version>0.9.5.2</c3p0.version>
<mysql-connector-java.version>5.1.29</mysql-connector-java.version> <mysql-connector-java.version>5.1.45</mysql-connector-java.version>
<mybatis-spring.version>1.2.2</mybatis-spring.version> <mybatis-spring.version>1.3.1</mybatis-spring.version>
<mybatis.version>3.2.8</mybatis.version> <mybatis.version>3.4.5</mybatis.version>
<groovy-all.version>2.4.5</groovy-all.version> <groovy-all.version>2.4.13</groovy-all.version>
<mail.version>1.4.6</mail.version>
<quartz.version>2.3.0</quartz.version> <quartz.version>2.3.0</quartz.version>
<spring-boot.version>1.5.6.RELEASE</spring-boot.version> <spring-boot.version>1.5.9.RELEASE</spring-boot.version>
</properties> </properties>
<build> <build>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId> <artifactId>xxl-job</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>xxl-job-admin</artifactId> <artifactId>xxl-job-admin</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
...@@ -40,18 +40,22 @@ ...@@ -40,18 +40,22 @@
</dependency> </dependency>
<!-- jackson (support spring json) --> <!-- jackson (support spring json) -->
<dependency> <dependency>
<groupId>org.codehaus.jackson</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-mapper-asl</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson-mapper-asl.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<!-- slf4j --> <!-- servlet -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>javax.servlet</groupId>
<artifactId>slf4j-log4j12</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>${slf4j-api.version}</version> <version>${javax.servlet-api.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
</dependency> </dependency>
<!-- freemarker --> <!-- freemarker -->
<dependency> <dependency>
<groupId>org.freemarker</groupId> <groupId>org.freemarker</groupId>
...@@ -59,37 +63,37 @@ ...@@ -59,37 +63,37 @@
<version>${freemarker.version}</version> <version>${freemarker.version}</version>
</dependency> </dependency>
<!-- commons-beanutils --> <!-- slf4j -->
<dependency> <dependency>
<groupId>commons-beanutils</groupId> <groupId>org.slf4j</groupId>
<artifactId>commons-beanutils</artifactId> <artifactId>slf4j-log4j12</artifactId>
<version>${commons-beanutils.version}</version> <version>${slf4j-api.version}</version>
</dependency> </dependency>
<!-- commons-lang --> <!-- junit -->
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>junit</groupId>
<artifactId>commons-lang</artifactId> <artifactId>junit</artifactId>
<version>${commons-lang.version}</version> <version>${junit.version}</version>
<scope>test</scope>
</dependency> </dependency>
<!-- servlet --> <!-- commons-collections4 -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>org.apache.commons</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>commons-collections4</artifactId>
<version>${javax.servlet-api.version}</version> <version>${commons-collections4.version}</version>
</dependency> </dependency>
<!-- commons-lang3 -->
<dependency> <dependency>
<groupId>javax.servlet.jsp</groupId> <groupId>org.apache.commons</groupId>
<artifactId>jsp-api</artifactId> <artifactId>commons-lang3</artifactId>
<version>${jsp-api.version}</version> <version>${commons-lang3.version}</version>
</dependency> </dependency>
<!-- commons-email -->
<!-- junit -->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>org.apache.commons</groupId>
<artifactId>junit</artifactId> <artifactId>commons-email</artifactId>
<version>${junit.version}</version> <version>${commons-email.version}</version>
<scope>test</scope>
</dependency> </dependency>
<!-- c3p0 --> <!-- c3p0 -->
...@@ -116,7 +120,6 @@ ...@@ -116,7 +120,6 @@
<version>${mybatis.version}</version> <version>${mybatis.version}</version>
</dependency> </dependency>
<!-- httpclient --> <!-- httpclient -->
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
...@@ -124,13 +127,6 @@ ...@@ -124,13 +127,6 @@
<version>${httpclient.version}</version> <version>${httpclient.version}</version>
</dependency> </dependency>
<!-- javax.mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${mail.version}</version>
</dependency>
<!-- quartz :quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 --> <!-- quartz :quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 -->
<dependency> <dependency>
<groupId>org.quartz-scheduler</groupId> <groupId>org.quartz-scheduler</groupId>
......
...@@ -5,9 +5,12 @@ import com.xxl.job.admin.controller.interceptor.PermissionInterceptor; ...@@ -5,9 +5,12 @@ import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.util.PropertiesUtil; import com.xxl.job.admin.core.util.PropertiesUtil;
import com.xxl.job.admin.service.XxlJobService; import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
...@@ -15,6 +18,8 @@ import org.springframework.web.bind.annotation.ResponseBody; ...@@ -15,6 +18,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map; import java.util.Map;
/** /**
...@@ -38,8 +43,8 @@ public class IndexController { ...@@ -38,8 +43,8 @@ public class IndexController {
@RequestMapping("/triggerChartDate") @RequestMapping("/triggerChartDate")
@ResponseBody @ResponseBody
public ReturnT<Map<String, Object>> triggerChartDate() { public ReturnT<Map<String, Object>> triggerChartDate(Date startDate, Date endDate) {
ReturnT<Map<String, Object>> triggerChartDate = xxlJobService.triggerChartDate(); ReturnT<Map<String, Object>> triggerChartDate = xxlJobService.triggerChartDate(startDate, endDate);
return triggerChartDate; return triggerChartDate;
} }
...@@ -91,5 +96,12 @@ public class IndexController { ...@@ -91,5 +96,12 @@ public class IndexController {
return "help"; return "help";
} }
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
} }
...@@ -4,7 +4,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup; ...@@ -4,7 +4,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.dao.XxlJobGroupDao; import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao; import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
......
...@@ -11,8 +11,8 @@ import com.xxl.job.core.biz.ExecutorBiz; ...@@ -11,8 +11,8 @@ import com.xxl.job.core.biz.ExecutorBiz;
import com.xxl.job.core.biz.model.LogResult; import com.xxl.job.core.biz.model.LogResult;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.rpc.netcom.NetComClientProxy; import com.xxl.job.core.rpc.netcom.NetComClientProxy;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
......
package com.xxl.job.admin.controller.interceptor; package com.xxl.job.admin.controller.interceptor;
import java.util.HashMap; import org.apache.commons.lang3.ArrayUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/** /**
* push cookies to model as cookieMap * push cookies to model as cookieMap
*
* @author xuxueli 2015-12-12 18:09:04 * @author xuxueli 2015-12-12 18:09:04
*/ */
public class CookieInterceptor extends HandlerInterceptorAdapter { public class CookieInterceptor extends HandlerInterceptorAdapter {
......
...@@ -12,11 +12,12 @@ import java.math.BigInteger; ...@@ -12,11 +12,12 @@ import java.math.BigInteger;
/** /**
* 权限拦截, 简易版 * 权限拦截, 简易版
*
* @author xuxueli 2015-12-12 18:09:04 * @author xuxueli 2015-12-12 18:09:04
*/ */
public class PermissionInterceptor extends HandlerInterceptorAdapter { public class PermissionInterceptor extends HandlerInterceptorAdapter {
public static final String LOGIN_IDENTITY_KEY = "LOGIN_IDENTITY"; public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
public static final String LOGIN_IDENTITY_TOKEN; public static final String LOGIN_IDENTITY_TOKEN;
static { static {
String username = PropertiesUtil.getString("xxl.job.login.username"); String username = PropertiesUtil.getString("xxl.job.login.username");
......
package com.xxl.job.admin.core.jobbean;
//package com.xxl.job.action.job;
//
//import java.io.PrintWriter;
//import java.io.StringWriter;
//import java.util.Date;
//import java.util.HashMap;
//import java.util.Map;
//
//import org.apache.commons.lang.StringUtils;
//import org.quartz.JobExecutionContext;
//import org.quartz.JobExecutionException;
//import org.quartz.JobKey;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.scheduling.quartz.QuartzJobBean;
//
//import com.xxl.job.client.handler.HandlerRouter;
//import com.xxl.job.client.util.XxlJobNetCommUtil.RemoteCallBack;
//import com.xxl.job.client.util.JacksonUtil;
//import com.xxl.job.core.model.XxlJobInfo;
//import com.xxl.job.core.model.XxlJobLog;
//import com.xxl.job.core.thread.JobFailMonitorHelper;
//import com.xxl.job.core.util.DynamicSchedulerUtil;
//
///**
// * http job bean
// * @author xuxueli 2015-12-17 18:20:34
// */
//@Deprecated
//public abstract class LocalNomalJobBean extends QuartzJobBean {
// private static Logger logger = LoggerFactory.getLogger(LocalNomalJobBean.class);
//
// @Override
// protected void executeInternal(JobExecutionContext context)
// throws JobExecutionException {
// JobKey jobKey = context.getTrigger().getJobKey();
//
// XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName());
// @SuppressWarnings("unchecked")
// HashMap<String, String> jobDataMap = (HashMap<String, String>) JacksonUtil.readValueRefer(jobInfo.getJobData(), Map.class);
//
// // save log
// XxlJobLog jobLog = new XxlJobLog();
// jobLog.setJobGroup(jobInfo.getJobGroup());
// jobLog.setJobName(jobInfo.getJobName());
// jobLog.setJobCron(jobInfo.getJobCron());
// jobLog.setJobDesc(jobInfo.getJobDesc());
// jobLog.setJobClass(jobInfo.getJobClass());
// jobLog.setJobData(jobInfo.getJobData());
//
// jobLog.setJobClass(RemoteHttpJobBean.class.getName());
// jobLog.setJobData(jobInfo.getJobData());
// DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
// logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
//
// // trigger request
// String handler_params = jobDataMap.get(HandlerRouter.HANDLER_PARAMS);
// String[] handlerParams = null;
// if (StringUtils.isNotBlank(handler_params)) {
// handlerParams = handler_params.split(",");
// }
//
// jobLog.setTriggerTime(new Date());
// jobLog.setTriggerStatus(RemoteCallBack.SUCCESS);
// jobLog.setTriggerMsg(null);
//
// try {
// Object responseMsg = this.handle(handlerParams);
//
// jobLog.setHandleTime(new Date());
// jobLog.setHandleStatus(RemoteCallBack.SUCCESS);
// jobLog.setHandleMsg(JacksonUtil.writeValueAsString(responseMsg));
// } catch (Exception e) {
// logger.info("JobThread Exception:", e);
// StringWriter out = new StringWriter();
// e.printStackTrace(new PrintWriter(out));
//
// jobLog.setHandleTime(new Date());
// jobLog.setHandleStatus(RemoteCallBack.FAIL);
// jobLog.setHandleMsg(out.toString());
// }
//
// // update trigger info
// DynamicSchedulerUtil.xxlJobLogDao.updateTriggerInfo(jobLog);
// DynamicSchedulerUtil.xxlJobLogDao.updateHandleInfo(jobLog);
// JobFailMonitorHelper.monitor(jobLog.getId());
// logger.info(">>>>>>>>>>> xxl-job trigger end, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
//
// }
//
// public abstract Object handle(String... param);
//
//}
\ No newline at end of file
package com.xxl.job.admin.core.jobbean.impl;
//package com.xxl.job.action.job.impl;
//
//import java.util.concurrent.TimeUnit;
//
//import org.quartz.DisallowConcurrentExecution;
//
//import com.xxl.job.action.job.LocalNomalJobBean;
//
///**
// * demo job bean for no-concurrent
// * @author xuxueli 2016-3-12 14:25:14
// */
//@Deprecated
//@DisallowConcurrentExecution // 串行;线程数要多配置几个,否则不生效;
//public class DemoConcurrentJobBean extends LocalNomalJobBean {
//
// @Override
// public Object handle(String... param) {
//
// try {
// TimeUnit.SECONDS.sleep(10);
// } catch (InterruptedException e) {
// logger.error(e.getMessage(), e);
// }
//
// return false;
// }
//
//}
package com.xxl.job.admin.core.jobbean.impl;
//package com.xxl.job.action.job.impl;
//
//import java.util.concurrent.TimeUnit;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//import com.xxl.job.action.job.LocalNomalJobBean;
//
///**
// * demo job bean for concurrent
// * @author xuxueli 2016-3-12 14:25:57
// */
//@Deprecated
//public class DemoNomalJobBean extends LocalNomalJobBean {
// private static Logger Logger = LoggerFactory.getLogger(DemoNomalJobBean.class);
//
// @Override
// public Object handle(String... param) {
// Logger.info("DemoNomalJobBean run :" + param);
//
// try {
// TimeUnit.SECONDS.sleep(10);
// } catch (InterruptedException e) {
// logger.error(e.getMessage(), e);
// }
//
// return false;
// }
//
//}
package com.xxl.job.admin.core.model; package com.xxl.job.admin.core.model;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
......
...@@ -4,8 +4,11 @@ import com.xxl.job.admin.core.model.XxlJobGroup; ...@@ -4,8 +4,11 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog; import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.xxl.job.admin.core.util.JobKeyUtil;
import com.xxl.job.admin.core.util.MailUtil; import com.xxl.job.admin.core.util.MailUtil;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -26,6 +29,8 @@ public class JobFailMonitorHelper { ...@@ -26,6 +29,8 @@ public class JobFailMonitorHelper {
return instance; return instance;
} }
// ---------------------- monitor ----------------------
private LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(0xfff8); private LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(0xfff8);
private Thread monitorThread; private Thread monitorThread;
...@@ -35,33 +40,41 @@ public class JobFailMonitorHelper { ...@@ -35,33 +40,41 @@ public class JobFailMonitorHelper {
@Override @Override
public void run() { public void run() {
// monitor // monitor
while (!toStop) { while (!toStop) {
try { try {
Integer jobLogId = JobFailMonitorHelper.instance.queue.take(); List<Integer> jobLogIdList = new ArrayList<Integer>();
if (jobLogId != null && jobLogId > 0) { int drainToNum = JobFailMonitorHelper.instance.queue.drainTo(jobLogIdList);
XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);
if (log!=null) {
if (ReturnT.SUCCESS_CODE==log.getTriggerCode() && log.getHandleCode()==0) {
// job running, wait + again monitor
TimeUnit.SECONDS.sleep(10);
if (CollectionUtils.isNotEmpty(jobLogIdList)) {
for (Integer jobLogId : jobLogIdList) {
if (jobLogId==null || jobLogId==0) {
continue;
}
XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);
if (log == null) {
continue;
}
if (IJobHandler.SUCCESS.getCode() == log.getTriggerCode() && log.getHandleCode() == 0) {
JobFailMonitorHelper.monitor(jobLogId); JobFailMonitorHelper.monitor(jobLogId);
logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId); logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId);
} } else if (IJobHandler.SUCCESS.getCode() == log.getHandleCode()) {
if (ReturnT.SUCCESS_CODE==log.getTriggerCode() && ReturnT.SUCCESS_CODE==log.getHandleCode()) {
// job success, pass // job success, pass
logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId); logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId);
} } else if (IJobHandler.FAIL.getCode() == log.getTriggerCode()
|| IJobHandler.FAIL.getCode() == log.getHandleCode()
if (ReturnT.FAIL_CODE == log.getTriggerCode()|| ReturnT.FAIL_CODE==log.getHandleCode()) { || IJobHandler.FAIL_RETRY.getCode() == log.getHandleCode() ) {
// job fail, // job fail,
sendMonitorEmail(log); failAlarm(log);
logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId); logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId);
} else {
JobFailMonitorHelper.monitor(jobLogId);
logger.info(">>>>>>>>>>> job monitor, job status unknown, JobLogId:{}", jobLogId);
} }
} }
} }
TimeUnit.SECONDS.sleep(10);
} catch (Exception e) { } catch (Exception e) {
logger.error("job monitor error:{}", e); logger.error("job monitor error:{}", e);
} }
...@@ -75,7 +88,7 @@ public class JobFailMonitorHelper { ...@@ -75,7 +88,7 @@ public class JobFailMonitorHelper {
XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId); XxlJobLog log = XxlJobDynamicScheduler.xxlJobLogDao.load(jobLogId);
if (ReturnT.FAIL_CODE == log.getTriggerCode()|| ReturnT.FAIL_CODE==log.getHandleCode()) { if (ReturnT.FAIL_CODE == log.getTriggerCode()|| ReturnT.FAIL_CODE==log.getHandleCode()) {
// job fail, // job fail,
sendMonitorEmail(log); failAlarm(log);
logger.info(">>>>>>>>>>> job monitor last, job fail, JobLogId:{}", jobLogId); logger.info(">>>>>>>>>>> job monitor last, job fail, JobLogId:{}", jobLogId);
} }
} }
...@@ -87,24 +100,6 @@ public class JobFailMonitorHelper { ...@@ -87,24 +100,6 @@ public class JobFailMonitorHelper {
monitorThread.start(); monitorThread.start();
} }
/**
* send monitor email
* @param jobLog
*/
private void sendMonitorEmail(XxlJobLog jobLog){
XxlJobInfo info = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobLog.getJobId());
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
for (String email: emailSet) {
String title = "《调度监控报警》(任务调度中心XXL-JOB)";
XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(Integer.valueOf(info.getJobGroup()));
String content = MessageFormat.format("任务调度失败, 执行器名称:{0}, 任务描述:{1}.", group!=null?group.getTitle():"null", info.getJobDesc());
MailUtil.sendMail(email, title, content, false, null);
}
}
}
public void toStop(){ public void toStop(){
toStop = true; toStop = true;
// interrupt and wait // interrupt and wait
...@@ -120,5 +115,55 @@ public class JobFailMonitorHelper { ...@@ -120,5 +115,55 @@ public class JobFailMonitorHelper {
public static void monitor(int jobLogId){ public static void monitor(int jobLogId){
getInstance().queue.offer(jobLogId); getInstance().queue.offer(jobLogId);
} }
// ---------------------- alarm ----------------------
// email alarm template
private static final String mailBodyTemplate = "<h5>监控告警明细:</span>" +
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >" +
" <tr>\n" +
" <td>执行器</td>\n" +
" <td>JobKey</td>\n" +
" <td>任务描述</td>\n" +
" <td>告警类型</td>\n" +
" </tr>\n" +
" <thead/>\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>{0}</td>\n" +
" <td>{1}</td>\n" +
" <td>{2}</td>\n" +
" <td>调度失败</td>\n" +
" </tr>\n" +
" <tbody>\n" +
"</table>";
/**
* fail alarm
*
* @param jobLog
*/
private void failAlarm(XxlJobLog jobLog){
// send monitor email
XxlJobInfo info = XxlJobDynamicScheduler.xxlJobInfoDao.loadById(jobLog.getJobId());
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
for (String email: emailSet) {
XxlJobGroup group = XxlJobDynamicScheduler.xxlJobGroupDao.load(Integer.valueOf(info.getJobGroup()));
String title = "调度中心监控报警";
String content = MessageFormat.format(mailBodyTemplate, group!=null?group.getTitle():"null", JobKeyUtil.formatJobKey(info), info.getJobDesc());
MailUtil.sendMail(email, title, content);
}
}
// TODO, custom alarm strategy, such as sms
}
} }
...@@ -4,8 +4,8 @@ import com.xxl.job.admin.core.model.XxlJobGroup; ...@@ -4,8 +4,8 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry; import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.xxl.job.core.enums.RegistryConfig; import com.xxl.job.core.enums.RegistryConfig;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
......
package com.xxl.job.admin.core.util;
import com.xxl.job.admin.core.model.XxlJobInfo;
import org.apache.commons.lang3.StringUtils;
/**
* job key util
*
* @author xuxueli 2017-12-22 18:48:45
*/
public class JobKeyUtil {
/**
* format job key
*
* @param xxlJobInfo
* @return
*/
public static String formatJobKey(XxlJobInfo xxlJobInfo){
return String.valueOf(xxlJobInfo.getJobGroup())
.concat("_").concat(String.valueOf(xxlJobInfo.getId()));
}
/**
* parse jobId from JobKey
*
* @param jobKey
* @return
*/
public static int parseJobId(String jobKey){
if (jobKey!=null && jobKey.trim().length()>0) {
String[] jobKeyArr = jobKey.split("_");
if (jobKeyArr.length == 2) {
String jobIdStr = jobKeyArr[1];
if (StringUtils.isNotBlank(jobIdStr) && StringUtils.isNumeric(jobIdStr)) {
int jobId = Integer.valueOf(jobIdStr);
return jobId;
}
}
}
return -1;
}
}
package com.xxl.job.admin.core.util; package com.xxl.job.admin.core.util;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.internet.MimeMessage; import java.nio.charset.Charset;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** /**
* 邮件发送.Util * 邮件发送.Util
*
* @author xuxueli 2016-3-12 15:06:20 * @author xuxueli 2016-3-12 15:06:20
*/ */
public class MailUtil { public class MailUtil {
...@@ -25,156 +20,52 @@ public class MailUtil { ...@@ -25,156 +20,52 @@ public class MailUtil {
private static String port; private static String port;
private static String username; private static String username;
private static String password; private static String password;
private static String sendFrom;
private static String sendNick; private static String sendNick;
static{ static{
host = PropertiesUtil.getString("xxl.job.mail.host"); host = PropertiesUtil.getString("xxl.job.mail.host");
port = PropertiesUtil.getString("xxl.job.mail.port"); port = PropertiesUtil.getString("xxl.job.mail.port");
username = PropertiesUtil.getString("xxl.job.mail.username"); username = PropertiesUtil.getString("xxl.job.mail.username");
password = PropertiesUtil.getString("xxl.job.mail.password"); password = PropertiesUtil.getString("xxl.job.mail.password");
sendFrom = PropertiesUtil.getString("xxl.job.mail.sendFrom");
sendNick = PropertiesUtil.getString("xxl.job.mail.sendNick"); sendNick = PropertiesUtil.getString("xxl.job.mail.sendNick");
} }
/**
<!-- spring mail sender -->
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" scope="singleton" >
<property name="host" value="${mail.host}" /> <!-- SMTP发送邮件的服务器的IP和端口 -->
<property name="port" value="${mail.port}" />
<property name="username" value="${mail.username}" /> <!-- 登录SMTP邮件发送服务器的用户名和密码 -->
<property name="password" value="${mail.password}" />
<property name="javaMailProperties"> <!-- 获得邮件会话属性,验证登录邮件服务器是否成功 -->
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="prop">true</prop>
<!-- <prop key="mail.smtp.timeout">25000</prop> -->
</props>
</property>
</bean>
*/
/** /**
* 发送邮件 (完整版)(结合Spring) *
* * @param toAddress 收件人邮箱
* //@param javaMailSender: 发送Bean * @param mailSubject 邮件主题
* //@param sendFrom : 发送人邮箱 * @param mailBody 邮件正文
* //@param sendNick : 发送人昵称 * @return
* @param toAddress : 收件人邮箱
* @param mailSubject : 邮件主题
* @param mailBody : 邮件正文
* @param mailBodyIsHtml: 邮件正文格式,true:HTML格式;false:文本格式
* @param attachments : 附件
*/ */
@SuppressWarnings("null") public static boolean sendMail(String toAddress, String mailSubject, String mailBody){
public static boolean sendMailSpring(String toAddress, String mailSubject, String mailBody, boolean mailBodyIsHtml,File[] attachments) {
JavaMailSender javaMailSender = null;//ResourceBundle.getInstance().getJavaMailSender();
try { try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage(); // Create the email message
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, ArrayUtils.isNotEmpty(attachments), "UTF-8"); // 设置utf-8或GBK编码,否则邮件会有乱码;multipart,true表示文件上传 HtmlEmail email = new HtmlEmail();
helper.setFrom(sendFrom, sendNick);
helper.setTo(toAddress);
// 设置收件人抄送的名片和地址(相当于群发了) //email.setDebug(true); // 将会打印一些log
//helper.setCc(InternetAddress.parse(MimeUtility.encodeText("邮箱001") + " <@163.com>," + MimeUtility.encodeText("邮箱002") + " <@foxmail.com>")); //email.setTLS(true); // 是否TLS校验,,某些邮箱需要TLS安全校验,同理有SSL校验
//email.setSSL(true);
helper.setSubject(mailSubject); email.setHostName(host);
helper.setText(mailBody, mailBodyIsHtml); email.setSmtpPort(Integer.valueOf(port));
//email.setSslSmtpPort(port);
// 添加附件 email.setAuthenticator(new DefaultAuthenticator(username, password));
if (ArrayUtils.isNotEmpty(attachments)) { email.setCharset(Charset.defaultCharset().name());
for (File file : attachments) {
helper.addAttachment(MimeUtility.encodeText(file.getName()), file); email.setFrom(username, sendNick);
} email.addTo(toAddress);
} email.setSubject(mailSubject);
email.setMsg(mailBody);
// 群发
//MimeMessage[] mailMessages = { mimeMessage };
javaMailSender.send(mimeMessage);
return true;
} catch (Exception e) {
logger.info("{}", e);
}
return false;
}
/**
* 发送邮件 (完整版) (纯JavaMail)
*
* @param toAddress : 收件人邮箱
* @param mailSubject : 邮件主题
* @param mailBody : 邮件正文
* @param mailBodyIsHtml: 邮件正文格式,true:HTML格式;false:文本格式
* //@param inLineFile : 内嵌文件
* @param attachments : 附件
*/
public static boolean sendMail (String toAddress, String mailSubject, String mailBody,
boolean mailBodyIsHtml, File[] attachments){
try {
// 创建邮件发送类 JavaMailSender (用于发送多元化邮件,包括附件,图片,html 等 )
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host); // 设置邮件服务主机
mailSender.setUsername(username); // 发送者邮箱的用户名
mailSender.setPassword(password); // 发送者邮箱的密码
//配置文件,用于实例化java.mail.session
Properties pro = new Properties();
pro.put("mail.smtp.auth", "true"); // 登录SMTP服务器,需要获得授权 (网易163邮箱新近注册的邮箱均不能授权,测试 sohu 的邮箱可以获得授权)
pro.put("mail.smtp.socketFactory.port", port);
pro.put("mail.smtp.socketFactory.fallback", "false");
mailSender.setJavaMailProperties(pro);
//创建多元化邮件 (创建 mimeMessage 帮助类,用于封装信息至 mimeMessage)
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, ArrayUtils.isNotEmpty(attachments), "UTF-8");
helper.setFrom(sendFrom, sendNick);
helper.setTo(toAddress);
helper.setSubject(mailSubject); //email.attach(attachment); // add the attachment
helper.setText(mailBody, mailBodyIsHtml);
email.send(); // send the email
// 添加内嵌文件,第1个参数为cid标识这个文件,第2个参数为资源
//helper.addInline(MimeUtility.encodeText(inLineFile.getName()), inLineFile);
// 添加附件
if (ArrayUtils.isNotEmpty(attachments)) {
for (File file : attachments) {
helper.addAttachment(MimeUtility.encodeText(file.getName()), file);
}
}
mailSender.send(mimeMessage);
return true; return true;
} catch (Exception e) { } catch (EmailException e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
return false; return false;
} }
static int total = 0;
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
exec.execute(new Thread(new Runnable() {
@Override
public void run() {
while(total < 10){
String mailBody = "<html><head><meta http-equiv="
+ "Content-Type"
+ " content="
+ "text/html; charset=gb2312"
+ "></head><body><h1>新书快递通知</h1>你的新书快递申请已推送新书,请到<a href=''>空间"
+ "</a>中查看</body></html>";
sendMail("ovono802302@163.com", "测试邮件", mailBody, false, null);
System.out.println(total);
total++;
}
}
}));
}
}
} }
...@@ -12,6 +12,7 @@ import java.util.Properties; ...@@ -12,6 +12,7 @@ import java.util.Properties;
/** /**
* properties util * properties util
*
* @author xuxueli 2015-8-28 10:35:53 * @author xuxueli 2015-8-28 10:35:53
*/ */
public class PropertiesUtil { public class PropertiesUtil {
...@@ -33,9 +34,5 @@ public class PropertiesUtil { ...@@ -33,9 +34,5 @@ public class PropertiesUtil {
} }
return null; return null;
} }
public static void main(String[] args) {
System.out.println(getString("xxl.job.login.username"));
}
} }
...@@ -4,6 +4,7 @@ package com.xxl.job.admin.service; ...@@ -4,6 +4,7 @@ package com.xxl.job.admin.service;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import java.util.Date;
import java.util.Map; import java.util.Map;
/** /**
...@@ -29,6 +30,6 @@ public interface XxlJobService { ...@@ -29,6 +30,6 @@ public interface XxlJobService {
public Map<String,Object> dashboardInfo(); public Map<String,Object> dashboardInfo();
public ReturnT<Map<String,Object>> triggerChartDate(); public ReturnT<Map<String,Object>> triggerChartDate(Date startDate, Date endDate);
} }
...@@ -5,6 +5,7 @@ import com.xxl.job.admin.core.model.XxlJobInfo; ...@@ -5,6 +5,7 @@ import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog; import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.xxl.job.admin.core.trigger.XxlJobTrigger; import com.xxl.job.admin.core.trigger.XxlJobTrigger;
import com.xxl.job.admin.core.util.JobKeyUtil;
import com.xxl.job.admin.dao.XxlJobInfoDao; import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobLogDao; import com.xxl.job.admin.dao.XxlJobLogDao;
import com.xxl.job.admin.dao.XxlJobRegistryDao; import com.xxl.job.admin.dao.XxlJobRegistryDao;
...@@ -13,7 +14,8 @@ import com.xxl.job.core.biz.AdminBiz; ...@@ -13,7 +14,8 @@ import com.xxl.job.core.biz.AdminBiz;
import com.xxl.job.core.biz.model.HandleCallbackParam; import com.xxl.job.core.biz.model.HandleCallbackParam;
import com.xxl.job.core.biz.model.RegistryParam; import com.xxl.job.core.biz.model.RegistryParam;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import org.apache.commons.lang.StringUtils; import com.xxl.job.core.handler.IJobHandler;
import org.apache.commons.lang3.StringUtils;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -45,8 +47,8 @@ public class AdminBizImpl implements AdminBiz { ...@@ -45,8 +47,8 @@ public class AdminBizImpl implements AdminBiz {
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) { public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
for (HandleCallbackParam handleCallbackParam: callbackParamList) { for (HandleCallbackParam handleCallbackParam: callbackParamList) {
ReturnT<String> callbackResult = callback(handleCallbackParam); ReturnT<String> callbackResult = callback(handleCallbackParam);
logger.info("JobApiController.callback {}, handleCallbackParam={}, callbackResult={}", logger.info(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
(callbackResult.getCode()==ReturnT.SUCCESS_CODE?"success":"fail"), handleCallbackParam, callbackResult); (callbackResult.getCode()==IJobHandler.SUCCESS.getCode()?"success":"fail"), handleCallbackParam, callbackResult);
} }
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
...@@ -58,28 +60,39 @@ public class AdminBizImpl implements AdminBiz { ...@@ -58,28 +60,39 @@ public class AdminBizImpl implements AdminBiz {
if (log == null) { if (log == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found."); return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
} }
if (log.getHandleCode() > 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid repeat callback, trigger child job etc
}
// trigger success, to trigger child job, and avoid repeat trigger child job // trigger success, to trigger child job
String childTriggerMsg = null; String callbackMsg = null;
if (ReturnT.SUCCESS_CODE==handleCallbackParam.getExecuteResult().getCode() && ReturnT.SUCCESS_CODE!=log.getHandleCode()) { if (IJobHandler.SUCCESS.getCode() == handleCallbackParam.getExecuteResult().getCode()) {
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId()); XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId());
if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) { if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
childTriggerMsg = "<hr>"; callbackMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发子任务<<<<<<<<<<< </span><br>";
String[] childJobKeys = xxlJobInfo.getChildJobKey().split(","); String[] childJobKeys = xxlJobInfo.getChildJobKey().split(",");
for (int i = 0; i < childJobKeys.length; i++) { for (int i = 0; i < childJobKeys.length; i++) {
String[] jobKeyArr = childJobKeys[i].split("_"); int childJobId = JobKeyUtil.parseJobId(childJobKeys[i]);
if (jobKeyArr!=null && jobKeyArr.length==2) { if (childJobId > 0) {
ReturnT<String> triggerChildResult = xxlJobService.triggerJob(Integer.valueOf(jobKeyArr[1])); ReturnT<String> triggerChildResult = xxlJobService.triggerJob(childJobId);
// add msg // add msg
childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务{2}, 子任务Key: {3}, 子任务触发备注: {4}", callbackMsg += MessageFormat.format("{0}/{1} [JobKey={2}], 触发{3}, 触发备注: {4} <br>",
(i+1), childJobKeys.length, (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), childJobKeys[i], triggerChildResult.getMsg()); (i+1), childJobKeys.length, childJobKeys[i], (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), triggerChildResult.getMsg());
} else { } else {
childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务失败, 子任务Key格式错误, 子任务Key: {2}", callbackMsg += MessageFormat.format(" {0}/{1} [JobKey={2}], 触发失败, 触发备注: JobKey格式错误 <br>",
(i+1), childJobKeys.length, childJobKeys[i]); (i+1), childJobKeys.length, childJobKeys[i]);
} }
} }
} }
} else if (IJobHandler.FAIL_RETRY.getCode() == handleCallbackParam.getExecuteResult().getCode()){
ReturnT<String> retryTriggerResult = xxlJobService.triggerJob(log.getJobId());
callbackMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>执行失败重试<<<<<<<<<<< </span><br>";
callbackMsg += MessageFormat.format("触发{0}, 触发备注: {1}",
(retryTriggerResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), retryTriggerResult.getMsg());
} }
// handle msg // handle msg
...@@ -90,8 +103,8 @@ public class AdminBizImpl implements AdminBiz { ...@@ -90,8 +103,8 @@ public class AdminBizImpl implements AdminBiz {
if (handleCallbackParam.getExecuteResult().getMsg() != null) { if (handleCallbackParam.getExecuteResult().getMsg() != null) {
handleMsg.append(handleCallbackParam.getExecuteResult().getMsg()); handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());
} }
if (childTriggerMsg !=null) { if (callbackMsg != null) {
handleMsg.append("<br>子任务触发备注:").append(childTriggerMsg); handleMsg.append(callbackMsg);
} }
// success, save log // success, save log
......
...@@ -5,6 +5,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup; ...@@ -5,6 +5,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum; import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.xxl.job.admin.core.util.JobKeyUtil;
import com.xxl.job.admin.dao.XxlJobGroupDao; import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao; import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobLogDao; import com.xxl.job.admin.dao.XxlJobLogDao;
...@@ -13,10 +14,10 @@ import com.xxl.job.admin.service.XxlJobService; ...@@ -13,10 +14,10 @@ import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum; import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
import com.xxl.job.core.glue.GlueTypeEnum; import com.xxl.job.core.glue.GlueTypeEnum;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat; import org.apache.commons.lang3.time.FastDateFormat;
import org.quartz.CronExpression; import org.quartz.CronExpression;
import org.quartz.SchedulerException; import org.quartz.SchedulerException;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -107,11 +108,11 @@ public class XxlJobServiceImpl implements XxlJobService { ...@@ -107,11 +108,11 @@ public class XxlJobServiceImpl implements XxlJobService {
if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) { if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) {
String[] childJobKeys = jobInfo.getChildJobKey().split(","); String[] childJobKeys = jobInfo.getChildJobKey().split(",");
for (String childJobKeyItem: childJobKeys) { for (String childJobKeyItem: childJobKeys) {
String[] childJobKeyArr = childJobKeyItem.split("_"); int childJobId = JobKeyUtil.parseJobId(childJobKeyItem);
if (childJobKeyArr.length!=2) { if (childJobId <= 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem)); return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem));
} }
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobKeyArr[1])); XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(childJobId);
if (childJobInfo==null) { if (childJobInfo==null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})无效", childJobKeyItem)); return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})无效", childJobKeyItem));
} }
...@@ -170,11 +171,11 @@ public class XxlJobServiceImpl implements XxlJobService { ...@@ -170,11 +171,11 @@ public class XxlJobServiceImpl implements XxlJobService {
if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) { if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) {
String[] childJobKeys = jobInfo.getChildJobKey().split(","); String[] childJobKeys = jobInfo.getChildJobKey().split(",");
for (String childJobKeyItem: childJobKeys) { for (String childJobKeyItem: childJobKeys) {
String[] childJobKeyArr = childJobKeyItem.split("_"); int childJobId = JobKeyUtil.parseJobId(childJobKeyItem);
if (childJobKeyArr.length!=2) { if (childJobId <= 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem)); return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem));
} }
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.valueOf(childJobKeyArr[1])); XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(childJobId);
if (childJobInfo==null) { if (childJobInfo==null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})无效", childJobKeyItem)); return new ReturnT<String>(ReturnT.FAIL_CODE, MessageFormat.format("子任务Key({0})无效", childJobKeyItem));
} }
...@@ -310,18 +311,15 @@ public class XxlJobServiceImpl implements XxlJobService { ...@@ -310,18 +311,15 @@ public class XxlJobServiceImpl implements XxlJobService {
} }
@Override @Override
public ReturnT<Map<String, Object>> triggerChartDate() { public ReturnT<Map<String, Object>> triggerChartDate(Date startDate, Date endDate) {
Date from = DateUtils.addDays(new Date(), -30);
Date to = new Date();
List<String> triggerDayList = new ArrayList<String>(); List<String> triggerDayList = new ArrayList<String>();
List<Integer> triggerDayCountSucList = new ArrayList<Integer>(); List<Integer> triggerDayCountSucList = new ArrayList<Integer>();
List<Integer> triggerDayCountFailList = new ArrayList<Integer>(); List<Integer> triggerDayCountFailList = new ArrayList<Integer>();
int triggerCountSucTotal = 0; int triggerCountSucTotal = 0;
int triggerCountFailTotal = 0; int triggerCountFailTotal = 0;
List<Map<String, Object>> triggerCountMapAll = xxlJobLogDao.triggerCountByDay(from, to, -1); List<Map<String, Object>> triggerCountMapAll = xxlJobLogDao.triggerCountByDay(startDate, endDate, -1);
List<Map<String, Object>> triggerCountMapSuc = xxlJobLogDao.triggerCountByDay(from, to, ReturnT.SUCCESS_CODE); List<Map<String, Object>> triggerCountMapSuc = xxlJobLogDao.triggerCountByDay(startDate, endDate, ReturnT.SUCCESS_CODE);
if (CollectionUtils.isNotEmpty(triggerCountMapAll)) { if (CollectionUtils.isNotEmpty(triggerCountMapAll)) {
for (Map<String, Object> item: triggerCountMapAll) { for (Map<String, Object> item: triggerCountMapAll) {
String day = String.valueOf(item.get("triggerDay")); String day = String.valueOf(item.get("triggerDay"));
......
log4j.rootLogger=info,console,logFile
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n
log4j.appender.logFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logFile.File=/data/applogs/xxl-job/xxl-job-admin.log
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" debug="null">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="/data/applogs/xxl-job/xxl-job-admin.log"/>
<param name="append" value="true"/>
<param name="encoding" value="UTF-8"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} xxl-job-admin [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/>
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</log4j:configuration>
\ No newline at end of file
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.xxl.job.admin.service, com.xxl.job.admin.dao" /> <context:component-scan base-package="com.xxl.job.admin.service, com.xxl.job.admin.dao" />
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven /> <mvc:annotation-driven />
<context:component-scan base-package="com.xxl.job.admin.controller" /> <context:component-scan base-package="com.xxl.job.admin.controller" />
......
...@@ -9,7 +9,6 @@ xxl.job.mail.host=smtp.163.com ...@@ -9,7 +9,6 @@ xxl.job.mail.host=smtp.163.com
xxl.job.mail.port=25 xxl.job.mail.port=25
xxl.job.mail.username=ovono802302@163.com xxl.job.mail.username=ovono802302@163.com
xxl.job.mail.password=asdfzxcv xxl.job.mail.password=asdfzxcv
xxl.job.mail.sendFrom=ovono802302@163.com
xxl.job.mail.sendNick=《任务调度平台XXL-JOB》 xxl.job.mail.sendNick=《任务调度平台XXL-JOB》
### xxl-job login ### xxl-job login
......
...@@ -175,7 +175,7 @@ ...@@ -175,7 +175,7 @@
<#macro commonFooter > <#macro commonFooter >
<footer class="main-footer"> <footer class="main-footer">
Powered by <b>XXL-JOB</b> 1.8.2(快照版本) Powered by <b>XXL-JOB</b> 1.9.0(快照版本)
<div class="pull-right hidden-xs"> <div class="pull-right hidden-xs">
<strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp; <strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;
<a href="http://www.xuxueli.com/" target="_blank" >xuxueli</a> <a href="http://www.xuxueli.com/" target="_blank" >xuxueli</a>
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
<title>任务调度中心</title> <title>任务调度中心</title>
<#import "/common/common.macro.ftl" as netCommon> <#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle /> <@netCommon.commonStyle />
<!-- daterangepicker -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.css">
</head> </head>
<body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> "> <body class="hold-transition skin-blue sidebar-mini <#if cookieMap?exists && "off" == cookieMap["xxljob_adminlte_settings"].value >sidebar-collapse</#if> ">
<div class="wrapper"> <div class="wrapper">
...@@ -43,7 +45,7 @@ ...@@ -43,7 +45,7 @@
<div class="progress"> <div class="progress">
<div class="progress-bar" style="width: 100%"></div> <div class="progress-bar" style="width: 100%"></div>
</div> </div>
<span class="progress-description">系统中配置的任务数量</span> <span class="progress-description">调度中心运行的任务数量</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -82,7 +84,7 @@ ...@@ -82,7 +84,7 @@
<div class="progress"> <div class="progress">
<div class="progress-bar" style="width: 100%"></div> <div class="progress-bar" style="width: 100%"></div>
</div> </div>
<span class="progress-description">心跳检测成功的执行器机器数量</span> <span class="progress-description">调度中心在线的执行器机器数量</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -94,8 +96,20 @@ ...@@ -94,8 +96,20 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="box"> <div class="box">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">调度报表(一月之内)</h3> <h3 class="box-title">调度报表</h3>
<#--<input type="text" class="form-control" id="filterTime" readonly >--> <#--<input type="text" class="form-control" id="filterTime" readonly >-->
<!-- tools box -->
<div class="pull-right box-tools">
<button type="button" class="btn btn-primary btn-sm daterange pull-right" data-toggle="tooltip" id="filterTime" >
<i class="fa fa-calendar"></i>
</button>
<#--<button type="button" class="btn btn-primary btn-sm pull-right" data-widget="collapse" data-toggle="tooltip" title="" style="margin-right: 5px;" data-original-title="Collapse">
<i class="fa fa-minus"></i>
</button>-->
</div>
<!-- /. tools -->
</div> </div>
<div class="box-body"> <div class="box-body">
<div class="row"> <div class="row">
...@@ -113,7 +127,6 @@ ...@@ -113,7 +127,6 @@
</div> </div>
</div> </div>
</section> </section>
<!-- /.content --> <!-- /.content -->
</div> </div>
...@@ -123,10 +136,11 @@ ...@@ -123,10 +136,11 @@
<@netCommon.commonFooter /> <@netCommon.commonFooter />
</div> </div>
<@netCommon.commonScript /> <@netCommon.commonScript />
<#--<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script> <!-- daterangepicker -->
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>--> <script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>
<#-- echarts -->
<script src="${request.contextPath}/static/plugins/echarts/echarts.common.min.js"></script> <script src="${request.contextPath}/static/plugins/echarts/echarts.common.min.js"></script>
<script src="${request.contextPath}/static/js/index.js"></script> <script src="${request.contextPath}/static/js/index.js"></script>
</body> </body>
</html> </html>
...@@ -109,15 +109,34 @@ ...@@ -109,15 +109,34 @@
</div> </div>
<@netCommon.commonScript /> <@netCommon.commonScript />
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#if jobInfo.glueType == "GLUE_GROOVY" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js" />
<#assign glueTypeIdeMode = "text/x-java" />
<#elseif jobInfo.glueType == "GLUE_SHELL" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/shell/shell.js" />
<#assign glueTypeIdeMode = "text/x-sh" />
<#elseif jobInfo.glueType == "GLUE_PYTHON" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/python/python.js" />
<#assign glueTypeIdeMode = "text/x-python" />
<#elseif jobInfo.glueType == "GLUE_NODEJS" >
<#assign glueTypeModeSrc = "${request.contextPath}/static/plugins/codemirror/mode/javascript/javascript.js" />
<#assign glueTypeIdeMode = "text/javascript" />
</#if>
<script src="${request.contextPath}/static/plugins/codemirror/lib/codemirror.js"></script> <script src="${request.contextPath}/static/plugins/codemirror/lib/codemirror.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/mode/clike/clike.js"></script> <script src="${glueTypeModeSrc}"></script>
<script src="${request.contextPath}/static/plugins/codemirror/mode/shell/shell.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/mode/python/python.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.js"></script> <script src="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/anyword-hint.js"></script> <script src="${request.contextPath}/static/plugins/codemirror/addon/hint/anyword-hint.js"></script>
<script> <script>
var id = '${jobInfo.id}'; var id = '${jobInfo.id}';
var glueType = '${jobInfo.glueType}'; var ideMode = '${glueTypeIdeMode}';
</script> </script>
<script src="${request.contextPath}/static/js/jobcode.index.1.js"></script> <script src="${request.contextPath}/static/js/jobcode.index.1.js"></script>
......
...@@ -53,7 +53,20 @@ ...@@ -53,7 +53,20 @@
<td>${group.appName}</td> <td>${group.appName}</td>
<td>${group.title}</td> <td>${group.title}</td>
<td><#if group.addressType==0>自动注册<#else>手动录入</#if></td> <td><#if group.addressType==0>自动注册<#else>手动录入</#if></td>
<td><#if group.registryList?exists><#list group.registryList as item><span class="badge bg-green">${item}</span><br></#list></#if></td> <td>
<#if group.registryList?exists>
<#list group.registryList as item>
<span class="badge bg-green" title="${item}" >
<#if item?length gt 35>
${item?substring(0, 35)}...
<#else>
${item}
</#if>
</span>
<br>
</#list>
</#if>
</td>
<td> <td>
<button class="btn btn-warning btn-xs update" <button class="btn btn-warning btn-xs update"
id="${group.id}" id="${group.id}"
...@@ -107,7 +120,9 @@ ...@@ -107,7 +120,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="addressList" placeholder="请输入执行器地址列表,多地址逗号分隔" maxlength="200" readonly="readonly" ></div> <div class="col-sm-10">
<textarea class="textarea" name="addressList" maxlength="512" placeholder="请输入执行器地址列表,多地址逗号分隔" readonly="readonly" style="background-color:#eee; width: 100%; height: 100px; font-size: 14px; line-height: 10px; border: 1px solid #dddddd; padding: 10px;"></textarea>
</div>
</div> </div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
...@@ -153,7 +168,9 @@ ...@@ -153,7 +168,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">机器地址<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="addressList" placeholder="请输入执行器地址列表,多地址逗号分隔" maxlength="200" readonly="readonly" ></div> <div class="col-sm-10">
<textarea class="textarea" name="addressList" maxlength="512" placeholder="请输入执行器地址列表,多地址逗号分隔" readonly="readonly" style="background-color:#eee; width: 100%; height: 100px; font-size: 14px; line-height: 10px; border: 1px solid #dddddd; padding: 10px;"></textarea>
</div>
</div> </div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<h3 class="box-title">调度列表</h3> <h3 class="box-title">调度列表</h3>
</div> </div>
<div class="box-body" > <div class="box-body" >
<table id="job_list" class="table table-bordered table-striped"> <table id="job_list" class="table table-bordered table-striped" width="100%" >
<thead> <thead>
<tr> <tr>
<th name="id" >id</th> <th name="id" >id</th>
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
</select> </select>
</div> </div>
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="128" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">运行模式<font color="red">*</font></label> <label for="firstname" class="col-sm-2 control-label">运行模式<font color="red">*</font></label>
...@@ -143,7 +143,7 @@ ...@@ -143,7 +143,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label> <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="512" ></div>
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label> <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
</div> </div>
...@@ -192,7 +192,7 @@ import com.xxl.job.core.handler.IJobHandler; ...@@ -192,7 +192,7 @@ import com.xxl.job.core.handler.IJobHandler;
public class DemoGlueJobHandler extends IJobHandler { public class DemoGlueJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World."); XxlJobLogger.log("XXL-JOB, Hello World.");
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} }
...@@ -204,12 +204,15 @@ public class DemoGlueJobHandler extends IJobHandler { ...@@ -204,12 +204,15 @@ public class DemoGlueJobHandler extends IJobHandler {
echo "xxl-job: hello shell" echo "xxl-job: hello shell"
echo "脚本位置:$0" echo "脚本位置:$0"
echo "参数数量:$#" echo "任务参数:$1"
echo "分片序号 = $2"
echo "分片总数 = $3"
<#--echo "参数数量:$#"
for param in $* for param in $*
do do
echo "参数 : $param" echo "参数 : $param"
sleep 1s sleep 1s
done done-->
echo "Good bye!" echo "Good bye!"
exit 0 exit 0
...@@ -221,19 +224,40 @@ import time ...@@ -221,19 +224,40 @@ import time
import sys import sys
print "xxl-job: hello python" print "xxl-job: hello python"
print "脚本文件:", sys.argv[0] print "脚本文件:", sys.argv[0]
for i in range(1, len(sys.argv)): print "任务参数:", sys.argv[1]
print "分片序号:", sys.argv[2]
print "分片总数:", sys.argv[3]
<#--for i in range(1, len(sys.argv)):
time.sleep(1) time.sleep(1)
print "参数", i, sys.argv[i] print "参数", i, sys.argv[i]-->
print "Good bye!" print "Good bye!"
exit(0)<#-- exit(0)
<#--
import logging import logging
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logging.info("脚本文件:" + sys.argv[0]) logging.info("脚本文件:" + sys.argv[0])
--> -->
</textarea> </textarea>
<textarea class="glueSource_nodejs" style="display:none;" >
#!/usr/bin/env node
console.log("xxl-job: hello nodejs")
var arguments = process.argv
console.log("脚本文件: " + arguments[1])
console.log("任务参数: " + arguments[2])
console.log("分片序号: " + arguments[3])
console.log("分片总数: " + arguments[4])
<#--for (var i = 2; i < arguments.length; i++){
console.log("参数 %s = %s", (i-1), arguments[i]);
}-->
console.log("Good bye!")
process.exit(0)
</textarea>
</form> </form>
</div> </div>
</div> </div>
...@@ -271,7 +295,7 @@ logging.info("脚本文件:" + sys.argv[0]) ...@@ -271,7 +295,7 @@ logging.info("脚本文件:" + sys.argv[0])
</select> </select>
</div> </div>
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="128" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">运行模式<font color="red">*</font></label> <label for="firstname" class="col-sm-2 control-label">运行模式<font color="red">*</font></label>
...@@ -287,7 +311,7 @@ logging.info("脚本文件:" + sys.argv[0]) ...@@ -287,7 +311,7 @@ logging.info("脚本文件:" + sys.argv[0])
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label> <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="512" ></div>
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label> <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
</div> </div>
......
...@@ -7,14 +7,18 @@ $(function(){ ...@@ -7,14 +7,18 @@ $(function(){
$.post(base_url + "/logout", function(data, status) { $.post(base_url + "/logout", function(data, status) {
if (data.code == "200") { if (data.code == "200") {
layer.open({ layer.msg('注销成功');
setTimeout(function(){
window.location.href = base_url + "/";
}, 500);
/*layer.open({
title: '系统提示', title: '系统提示',
content: '注销成功', content: '注销成功',
icon: '1', icon: '1',
end: function(layero, index){ end: function(layero, index){
window.location.href = base_url + "/"; window.location.href = base_url + "/";
} }
}); });*/
} else { } else {
layer.open({ layer.open({
title: '系统提示', title: '系统提示',
......
...@@ -5,29 +5,74 @@ ...@@ -5,29 +5,74 @@
$(function () { $(function () {
// 过滤时间
var _startDate = moment().subtract(1, 'months'); // 默认,最近一月
var _endDate = moment();
$('#filterTime').daterangepicker({
autoApply:false,
singleDatePicker:false,
showDropdowns:false, // 是否显示年月选择条件
timePicker: true, // 是否显示小时和分钟选择条件
timePickerIncrement: 10, // 时间的增量,单位为分钟
timePicker24Hour : true,
opens : 'left', //日期选择框的弹出位置
ranges: {
//'最近1小时': [moment().subtract(1, 'hours'), moment()],
'今日': [moment().startOf('day'), moment().endOf('day')],
'昨日': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')],
'本月': [moment().startOf('month'), moment().endOf('month')],
'上个月': [moment().subtract(1, 'months').startOf('month'), moment().subtract(1, 'months').endOf('month')],
'最近1周': [moment().subtract(1, 'weeks'), moment()],
'最近1月': [_startDate, _endDate]
},
locale : {
format: 'YYYY-MM-DD HH:mm:ss',
separator : ' - ',
customRangeLabel : '自定义',
applyLabel : '确定',
cancelLabel : '取消',
fromLabel : '起始时间',
toLabel : '结束时间',
daysOfWeek : [ '日', '一', '二', '三', '四', '五', '六' ],
monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
firstDay : 1
},
startDate:_startDate,
endDate: _endDate
}, function (start, end, label) {
freshChartDate(start, end);
});
freshChartDate(_startDate, _endDate);
/** /**
* 刷新报表
* *
* @param startDate
* @param endDate
*/ */
$.ajax({ function freshChartDate(startDate, endDate) {
type : 'POST', $.ajax({
url : base_url + '/triggerChartDate', type : 'POST',
data : { }, url : base_url + '/triggerChartDate',
dataType : "json", data : {
success : function(data){ 'startDate':startDate.format('YYYY-MM-DD HH:mm:ss'),
if (data.code == 200) { 'endDate':endDate.format('YYYY-MM-DD HH:mm:ss')
lineChartInit(data) },
pieChartInit(data); dataType : "json",
} else { success : function(data){
layer.open({ if (data.code == 200) {
title: '系统提示', lineChartInit(data)
content: (data.msg || '调度报表数据加载异常'), pieChartInit(data);
icon: '2' } else {
}); layer.open({
title: '系统提示',
content: (data.msg || '调度报表数据加载异常'),
icon: '2'
});
}
} }
} });
}); }
/** /**
* 折线图 * 折线图
...@@ -151,38 +196,4 @@ $(function () { ...@@ -151,38 +196,4 @@ $(function () {
pieChart.setOption(option); pieChart.setOption(option);
} }
// 过滤时间
/*$('#filterTime').daterangepicker({
autoApply:false,
singleDatePicker:false,
showDropdowns:false, // 是否显示年月选择条件
timePicker: true, // 是否显示小时和分钟选择条件
timePickerIncrement: 10, // 时间的增量,单位为分钟
timePicker24Hour : true,
opens : 'left', //日期选择框的弹出位置
ranges: {
'最近1小时': [moment().subtract(1, 'hours'), moment()],
'今日': [moment().startOf('day'), moment().endOf('day')],
'昨日': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')],
'最近7日': [moment().subtract(6, 'days'), moment()],
'最近30日': [moment().subtract(29, 'days'), moment()],
'本月': [moment().startOf('month'), moment().endOf('month')],
'上个月': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
},
locale : {
format: 'YYYY-MM-DD HH:mm:ss',
separator : ' - ',
customRangeLabel : '自定义',
applyLabel : '确定',
cancelLabel : '取消',
fromLabel : '起始时间',
toLabel : '结束时间',
daysOfWeek : [ '日', '一', '二', '三', '四', '五', '六' ],
monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
firstDay : 1,
startDate: moment().startOf('day'),
endDate: moment().endOf('day')
}
});*/
}); });
...@@ -8,34 +8,28 @@ $(function() { ...@@ -8,34 +8,28 @@ $(function() {
});*/ });*/
var codeEditor; var codeEditor;
function initIde(glueType, glueSource) { function initIde(glueSource) {
var ideMode = "text/x-java"; if (codeEditor == null) {
if ('GLUE_GROOVY'==glueType){ codeEditor = CodeMirror(document.getElementById("ideWindow"), {
ideMode = "text/x-java"; mode : ideMode,
} else if ('GLUE_SHELL'==glueType){ lineNumbers : true,
ideMode = "text/x-sh"; matchBrackets : true,
} else if ('GLUE_PYTHON'==glueType){ value: glueSource
ideMode = "text/x-python"; });
} else {
codeEditor.setValue(glueSource);
} }
codeEditor = CodeMirror(document.getElementById("ideWindow"), {
mode : ideMode,
lineNumbers : true,
matchBrackets : true,
value: glueSource
});
} }
initIde(glueType, $("#version_now").val()); initIde($("#version_now").val());
// code change // code change
$(".source_version").click(function(){ $(".source_version").click(function(){
var glueType = $(this).attr('glueType');
var sourceId = $(this).attr('version'); var sourceId = $(this).attr('version');
var temp = $( "#" + sourceId ).val(); var temp = $( "#" + sourceId ).val();
codeEditor.setValue(''); //codeEditor.setValue('');
initIde(glueType, temp); initIde(temp);
}); });
// code source save // code source save
......
...@@ -122,11 +122,13 @@ $(function() { ...@@ -122,11 +122,13 @@ $(function() {
// 注册方式,切换 // 注册方式,切换
$("#addModal input[name=addressType], #updateModal input[name=addressType]").click(function(){ $("#addModal input[name=addressType], #updateModal input[name=addressType]").click(function(){
var addressType = $(this).val(); var addressType = $(this).val();
var $addressList = $(this).parents("form").find("input[name=addressList]"); var $addressList = $(this).parents("form").find("textarea[name=addressList]");
if (addressType == 0) { if (addressType == 0) {
$addressList.css("background-color", "#eee"); // 自动注册
$addressList.attr("readonly","readonly");
$addressList.val(""); $addressList.val("");
$addressList.attr("readonly","readonly");
} else { } else {
$addressList.css("background-color", "white");
$addressList.removeAttr("readonly"); $addressList.removeAttr("readonly");
} }
}); });
...@@ -144,7 +146,7 @@ $(function() { ...@@ -144,7 +146,7 @@ $(function() {
//$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").attr('checked', 'true'); //$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").attr('checked', 'true');
$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").click(); $("#updateModal .form input[name='addressType'][value='"+ addressType +"']").click();
// 机器地址 // 机器地址
$("#updateModal .form input[name='addressList']").val($(this).attr("addressList")); $("#updateModal .form textarea[name='addressList']").val($(this).attr("addressList"));
$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show'); $('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
}); });
......
...@@ -55,6 +55,8 @@ $(function() { ...@@ -55,6 +55,8 @@ $(function() {
return "GLUE模式(Shell)"; return "GLUE模式(Shell)";
} else if ('GLUE_PYTHON'==row.glueType) { } else if ('GLUE_PYTHON'==row.glueType) {
return "GLUE模式(Python)"; return "GLUE模式(Python)";
}else if ('GLUE_NODEJS'==row.glueType){
return "GLUE模式(Nodejs)";
} else if ('BEAN'==row.glueType) { } else if ('BEAN'==row.glueType) {
return "BEAN模式:" + row.executorHandler; return "BEAN模式:" + row.executorHandler;
} }
...@@ -341,6 +343,8 @@ $(function() { ...@@ -341,6 +343,8 @@ $(function() {
$("#addModal .form textarea[name='glueSource']").val( $("#addModal .form .glueSource_shell").val() ); $("#addModal .form textarea[name='glueSource']").val( $("#addModal .form .glueSource_shell").val() );
} else if ('GLUE_PYTHON'==glueType){ } else if ('GLUE_PYTHON'==glueType){
$("#addModal .form textarea[name='glueSource']").val( $("#addModal .form .glueSource_python").val() ); $("#addModal .form textarea[name='glueSource']").val( $("#addModal .form .glueSource_python").val() );
} else if ('GLUE_NODEJS'==glueType){
$("#addModal .form textarea[name='glueSource']").val( $("#addModal .form .glueSource_nodejs").val() );
} }
}); });
......
...@@ -105,6 +105,8 @@ $(function() { ...@@ -105,6 +105,8 @@ $(function() {
glueTypeTitle = "GLUE模式(Shell)"; glueTypeTitle = "GLUE模式(Shell)";
} else if ('GLUE_PYTHON'==row.glueType) { } else if ('GLUE_PYTHON'==row.glueType) {
glueTypeTitle = "GLUE模式(Python)"; glueTypeTitle = "GLUE模式(Python)";
}else if ('GLUE_NODEJS'==row.glueType) {
glueTypeTitle = "GLUE模式(Nodejs)";
} else if ('BEAN'==row.glueType) { } else if ('BEAN'==row.glueType) {
glueTypeTitle = "BEAN模式:" + row.executorHandler; glueTypeTitle = "BEAN模式:" + row.executorHandler;
} }
...@@ -144,9 +146,16 @@ $(function() { ...@@ -144,9 +146,16 @@ $(function() {
{ {
"data": 'triggerCode', "data": 'triggerCode',
"render": function ( data, type, row ) { "render": function ( data, type, row ) {
return (data==200)?'<span style="color: green">成功</span>':(data==500)?'<span style="color: red">失败</span>':(data==0)?'':data; var html = data;
if (data == 200) {
html = '<span style="color: green">成功</span>';
} else if (data == 500) {
html = '<span style="color: red">失败</span>';
} else if (data == 0) {
html = '';
}
return html;
} }
}, },
{ {
"data": 'triggerMsg', "data": 'triggerMsg',
...@@ -163,7 +172,17 @@ $(function() { ...@@ -163,7 +172,17 @@ $(function() {
{ {
"data": 'handleCode', "data": 'handleCode',
"render": function ( data, type, row ) { "render": function ( data, type, row ) {
return (data==200)?'<span style="color: green">成功</span>':(data==500)?'<span style="color: red">失败</span>':(data==0)?'':data; var html = data;
if (data == 200) {
html = '<span style="color: green">成功</span>';
} else if (data == 500) {
html = '<span style="color: red">失败</span>';
} else if (data == 501) {
html = '<span style="color: red">失败重试</span>';
} else if (data == 0) {
html = '';
}
return html;
} }
}, },
{ {
......
...@@ -48,14 +48,18 @@ $(function(){ ...@@ -48,14 +48,18 @@ $(function(){
submitHandler : function(form) { submitHandler : function(form) {
$.post(base_url + "/login", $("#loginForm").serialize(), function(data, status) { $.post(base_url + "/login", $("#loginForm").serialize(), function(data, status) {
if (data.code == "200") { if (data.code == "200") {
layer.open({ layer.msg('登录成功');
setTimeout(function(){
window.location.href = base_url;
}, 500);
/*layer.open({
title: '系统提示', title: '系统提示',
content: '登录成功', content: '登录成功',
icon: '1', icon: '1',
end: function(layero, index){ end: function(layero, index){
window.location.href = base_url; window.location.href = base_url;
} }
}); });*/
} else { } else {
layer.open({ layer.open({
title: '系统提示', title: '系统提示',
......
package com.xxl.job.admin.controller;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring/*.xml"})
public class AbstractSpringMvcTest {
@Autowired
private WebApplicationContext applicationContext;
protected MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext).build();
}
}
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.util.PropertiesUtil;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import javax.servlet.http.Cookie;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
public class JobInfoControllerTest extends AbstractSpringMvcTest {
private Cookie cookie;
@Before
public void login() throws Exception {
MvcResult ret = mockMvc.perform(
post("/login")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("userName", PropertiesUtil.getString("xxl.job.login.username"))
.param("password", PropertiesUtil.getString("xxl.job.login.password"))
).andReturn();
cookie = ret.getResponse().getCookie(PermissionInterceptor.LOGIN_IDENTITY_KEY);
}
@Test
public void testAdd() throws Exception {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.add("jobGroup", "1");
MvcResult ret = mockMvc.perform(
post("/jobinfo/pageList")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
//.content(paramsJson)
.params(parameters)
.cookie(cookie)
).andReturn();
System.out.println(ret.getResponse().getContentAsString());
}
}
package com.xxl.job.dao.impl; package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.dao.XxlJobGroupDao; import com.xxl.job.admin.dao.XxlJobGroupDao;
......
package com.xxl.job.dao.impl; package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.dao.XxlJobInfoDao; import com.xxl.job.admin.dao.XxlJobInfoDao;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:spring/applicationcontext-*.xml") @ContextConfiguration(locations = "classpath*:spring/applicationcontext-*.xml")
public class XxlJobInfoTest { public class XxlJobInfoDaoTest {
@Resource @Resource
private XxlJobInfoDao xxlJobInfoDao; private XxlJobInfoDao xxlJobInfoDao;
@Test @Test
public void pageList(){ public void pageList(){
List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, 0, null); List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, 0, null);
int list_count = xxlJobInfoDao.pageListCount(0, 20, 0, null); int list_count = xxlJobInfoDao.pageListCount(0, 20, 0, null);
System.out.println(list); System.out.println(list);
System.out.println(list_count); System.out.println(list_count);
List<XxlJobInfo> list2 = xxlJobInfoDao.getJobsByGroup(1); List<XxlJobInfo> list2 = xxlJobInfoDao.getJobsByGroup(1);
} }
@Test @Test
public void save_load(){ public void save_load(){
XxlJobInfo info = new XxlJobInfo(); XxlJobInfo info = new XxlJobInfo();
info.setJobGroup(1); info.setJobGroup(1);
info.setJobCron("jobCron"); info.setJobCron("jobCron");
info.setJobDesc("desc"); info.setJobDesc("desc");
info.setAuthor("setAuthor"); info.setAuthor("setAuthor");
info.setAlarmEmail("setAlarmEmail"); info.setAlarmEmail("setAlarmEmail");
info.setExecutorRouteStrategy("setExecutorRouteStrategy"); info.setExecutorRouteStrategy("setExecutorRouteStrategy");
info.setExecutorHandler("setExecutorHandler"); info.setExecutorHandler("setExecutorHandler");
info.setExecutorParam("setExecutorParam"); info.setExecutorParam("setExecutorParam");
info.setExecutorBlockStrategy("setExecutorBlockStrategy"); info.setExecutorBlockStrategy("setExecutorBlockStrategy");
info.setExecutorFailStrategy("setExecutorFailStrategy"); info.setExecutorFailStrategy("setExecutorFailStrategy");
info.setGlueType("setGlueType"); info.setGlueType("setGlueType");
info.setGlueSource("setGlueSource"); info.setGlueSource("setGlueSource");
info.setGlueRemark("setGlueRemark"); info.setGlueRemark("setGlueRemark");
info.setChildJobKey("setChildJobKey"); info.setChildJobKey("setChildJobKey");
int count = xxlJobInfoDao.save(info); int count = xxlJobInfoDao.save(info);
XxlJobInfo info2 = xxlJobInfoDao.loadById(info.getId()); XxlJobInfo info2 = xxlJobInfoDao.loadById(info.getId());
info2.setJobCron("jobCron2"); info2.setJobCron("jobCron2");
info2.setJobDesc("desc2"); info2.setJobDesc("desc2");
info2.setAuthor("setAuthor2"); info2.setAuthor("setAuthor2");
info2.setAlarmEmail("setAlarmEmail2"); info2.setAlarmEmail("setAlarmEmail2");
info2.setExecutorRouteStrategy("setExecutorRouteStrategy2"); info2.setExecutorRouteStrategy("setExecutorRouteStrategy2");
info2.setExecutorHandler("setExecutorHandler2"); info2.setExecutorHandler("setExecutorHandler2");
info2.setExecutorParam("setExecutorParam2"); info2.setExecutorParam("setExecutorParam2");
info2.setExecutorBlockStrategy("setExecutorBlockStrategy2"); info2.setExecutorBlockStrategy("setExecutorBlockStrategy2");
info2.setExecutorFailStrategy("setExecutorFailStrategy2"); info2.setExecutorFailStrategy("setExecutorFailStrategy2");
info2.setGlueType("setGlueType2"); info2.setGlueType("setGlueType2");
info2.setGlueSource("setGlueSource2"); info2.setGlueSource("setGlueSource2");
info2.setGlueRemark("setGlueRemark2"); info2.setGlueRemark("setGlueRemark2");
info2.setGlueUpdatetime(new Date()); info2.setGlueUpdatetime(new Date());
info2.setChildJobKey("setChildJobKey2"); info2.setChildJobKey("setChildJobKey2");
int item2 = xxlJobInfoDao.update(info2); int item2 = xxlJobInfoDao.update(info2);
xxlJobInfoDao.delete(info2.getId()); xxlJobInfoDao.delete(info2.getId());
List<XxlJobInfo> list2 = xxlJobInfoDao.getJobsByGroup(1); List<XxlJobInfo> list2 = xxlJobInfoDao.getJobsByGroup(1);
int ret3 = xxlJobInfoDao.findAllCount(); int ret3 = xxlJobInfoDao.findAllCount();
} }
} }
package com.xxl.job.dao.impl; package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobLog; import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.dao.XxlJobLogDao; import com.xxl.job.admin.dao.XxlJobLogDao;
import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
......
package com.xxl.job.dao.impl; package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobLogGlue; import com.xxl.job.admin.core.model.XxlJobLogGlue;
import com.xxl.job.admin.dao.XxlJobLogGlueDao; import com.xxl.job.admin.dao.XxlJobLogGlueDao;
......
package com.xxl.job.dao.impl; package com.xxl.job.admin.dao;
import com.xxl.job.admin.core.model.XxlJobRegistry; import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.admin.dao.XxlJobRegistryDao; import com.xxl.job.admin.dao.XxlJobRegistryDao;
......
package com.xxl.job.admin.util;
import com.xxl.job.admin.core.util.MailUtil;
import org.junit.Test;
import java.text.MessageFormat;
/**
* email util test
*
* @author xuxueli 2017-12-22 17:16:23
*/
public class MailUtilTest {
@Test
public void registryTest() throws Exception {
String mailBodyTemplate = "<h5>监控告警明细:</span>" +
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >" +
" <tr>\n" +
" <td>执行器</td>\n" +
" <td>JobKey</td>\n" +
" <td>任务描述</td>\n" +
" <td>告警类型</td>\n" +
" </tr>\n" +
" <thead/>\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>{0}</td>\n" +
" <td>{1}</td>\n" +
" <td>{2}</td>\n" +
" <td>调度失败</td>\n" +
" </tr>\n" +
" <tbody>\n" +
"</table>";
mailBodyTemplate = MessageFormat.format(mailBodyTemplate, "执行器A", "1_1", "任务A1");
boolean ret = MailUtil.sendMail("931591021@qq.com", "调度中心监控报警" , mailBodyTemplate);
System.out.println(ret);
}
}
package com.xxl.job.admin.util;
import com.xxl.job.admin.core.util.PropertiesUtil;
import org.junit.Test;
/**
* prop util test
*
* @author xuxueli 2017-12-25 15:17:36
*/
public class PropertiesUtilTest {
@Test
public void registryTest() throws Exception {
System.out.println(PropertiesUtil.getString("xxl.job.login.username"));
}
}
package com.xxl.job.dao.impl; package com.xxl.job.adminbiz;
import com.xxl.job.core.biz.AdminBiz; import com.xxl.job.core.biz.AdminBiz;
import com.xxl.job.core.biz.model.RegistryParam; import com.xxl.job.core.biz.model.RegistryParam;
...@@ -9,7 +9,8 @@ import org.junit.Assert; ...@@ -9,7 +9,8 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
/** /**
* admin-api client, test * admin api test
*
* @author xuxueli 2017-07-28 22:14:52 * @author xuxueli 2017-07-28 22:14:52
*/ */
public class AdminBizTest { public class AdminBizTest {
...@@ -18,6 +19,11 @@ public class AdminBizTest { ...@@ -18,6 +19,11 @@ public class AdminBizTest {
private static String addressUrl = "http://127.0.0.1:8080/xxl-job-admin".concat(AdminBiz.MAPPING); private static String addressUrl = "http://127.0.0.1:8080/xxl-job-admin".concat(AdminBiz.MAPPING);
private static String accessToken = null; private static String accessToken = null;
/**
* registry executor
*
* @throws Exception
*/
@Test @Test
public void registryTest() throws Exception { public void registryTest() throws Exception {
AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject(); AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject();
...@@ -28,6 +34,11 @@ public class AdminBizTest { ...@@ -28,6 +34,11 @@ public class AdminBizTest {
Assert.assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE); Assert.assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE);
} }
/**
* registry executor remove
*
* @throws Exception
*/
@Test @Test
public void registryRemove() throws Exception { public void registryRemove() throws Exception {
AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject(); AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject();
...@@ -38,6 +49,11 @@ public class AdminBizTest { ...@@ -38,6 +49,11 @@ public class AdminBizTest {
Assert.assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE); Assert.assertTrue(returnT.getCode() == ReturnT.SUCCESS_CODE);
} }
/**
* trigger job for once
*
* @throws Exception
*/
@Test @Test
public void triggerJob() throws Exception { public void triggerJob() throws Exception {
AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject(); AdminBiz adminBiz = (AdminBiz) new NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject();
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId> <artifactId>xxl-job</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>xxl-job-core</artifactId> <artifactId>xxl-job-core</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
...@@ -49,11 +49,11 @@ ...@@ -49,11 +49,11 @@
<!-- jackson --> <!-- jackson -->
<dependency> <dependency>
<groupId>org.codehaus.jackson</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-mapper-asl</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson-mapper-asl.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<!-- httpclient --> <!-- httpclient -->
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
......
...@@ -59,7 +59,7 @@ public class ExecutorBizImpl implements ExecutorBiz { ...@@ -59,7 +59,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
@Override @Override
public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum) { public ReturnT<LogResult> log(long logDateTim, int logId, int fromLineNum) {
// log filename: yyyy-MM-dd/9999.log // log filename: logPath/yyyy-MM-dd/9999.log
String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId); String logFileName = XxlJobFileAppender.makeLogFileName(new Date(logDateTim), logId);
LogResult logResult = XxlJobFileAppender.readLog(logFileName, fromLineNum); LogResult logResult = XxlJobFileAppender.readLog(logFileName, fromLineNum);
...@@ -74,7 +74,8 @@ public class ExecutorBizImpl implements ExecutorBiz { ...@@ -74,7 +74,8 @@ public class ExecutorBizImpl implements ExecutorBiz {
String removeOldReason = null; String removeOldReason = null;
// valid:jobHandler + jobThread // valid:jobHandler + jobThread
if (GlueTypeEnum.BEAN==GlueTypeEnum.match(triggerParam.getGlueType())) { GlueTypeEnum glueTypeEnum = GlueTypeEnum.match(triggerParam.getGlueType());
if (GlueTypeEnum.BEAN == glueTypeEnum) {
// new jobhandler // new jobhandler
IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler()); IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
...@@ -96,7 +97,7 @@ public class ExecutorBizImpl implements ExecutorBiz { ...@@ -96,7 +97,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
} }
} }
} else if (GlueTypeEnum.GLUE_GROOVY==GlueTypeEnum.match(triggerParam.getGlueType())) { } else if (GlueTypeEnum.GLUE_GROOVY == glueTypeEnum) {
// valid old jobThread // valid old jobThread
if (jobThread != null && if (jobThread != null &&
...@@ -119,8 +120,7 @@ public class ExecutorBizImpl implements ExecutorBiz { ...@@ -119,8 +120,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage()); return new ReturnT<String>(ReturnT.FAIL_CODE, e.getMessage());
} }
} }
} else if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(triggerParam.getGlueType()) } else if (glueTypeEnum!=null && glueTypeEnum.isScript()) {
|| GlueTypeEnum.GLUE_PYTHON==GlueTypeEnum.match(triggerParam.getGlueType()) ) {
// valid old jobThread // valid old jobThread
if (jobThread != null && if (jobThread != null &&
......
...@@ -4,11 +4,12 @@ import com.xxl.job.core.biz.AdminBiz; ...@@ -4,11 +4,12 @@ import com.xxl.job.core.biz.AdminBiz;
import com.xxl.job.core.biz.ExecutorBiz; import com.xxl.job.core.biz.ExecutorBiz;
import com.xxl.job.core.biz.impl.ExecutorBizImpl; import com.xxl.job.core.biz.impl.ExecutorBizImpl;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobFileAppender; import com.xxl.job.core.log.XxlJobFileAppender;
import com.xxl.job.core.rpc.netcom.NetComClientProxy; import com.xxl.job.core.rpc.netcom.NetComClientProxy;
import com.xxl.job.core.rpc.netcom.NetComServerFactory; import com.xxl.job.core.rpc.netcom.NetComServerFactory;
import com.xxl.job.core.thread.JobThread; import com.xxl.job.core.thread.JobThread;
import com.xxl.job.core.util.NetUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
...@@ -28,7 +29,7 @@ public class XxlJobExecutor implements ApplicationContextAware { ...@@ -28,7 +29,7 @@ public class XxlJobExecutor implements ApplicationContextAware {
// ---------------------- param ---------------------- // ---------------------- param ----------------------
private String ip; private String ip;
private int port = 9999; private int port;
private String appName; private String appName;
private String adminAddresses; private String adminAddresses;
private String accessToken; private String accessToken;
...@@ -71,14 +72,10 @@ public class XxlJobExecutor implements ApplicationContextAware { ...@@ -71,14 +72,10 @@ public class XxlJobExecutor implements ApplicationContextAware {
initAdminBizList(adminAddresses, accessToken); initAdminBizList(adminAddresses, accessToken);
// init executor-jobHandlerRepository // init executor-jobHandlerRepository
if (applicationContext != null) { initJobHandlerRepository(applicationContext);
initJobHandlerRepository(applicationContext);
}
// init logpath // init logpath
if (logPath!=null && logPath.trim().length()>0) { XxlJobFileAppender.initLogPath(logPath);
XxlJobFileAppender.logPath = logPath;
}
// init executor-server // init executor-server
initExecutorServer(port, ip, appName, accessToken); initExecutorServer(port, ip, appName, accessToken);
...@@ -121,6 +118,10 @@ public class XxlJobExecutor implements ApplicationContextAware { ...@@ -121,6 +118,10 @@ public class XxlJobExecutor implements ApplicationContextAware {
// ---------------------- executor-server(jetty) ---------------------- // ---------------------- executor-server(jetty) ----------------------
private NetComServerFactory serverFactory = new NetComServerFactory(); private NetComServerFactory serverFactory = new NetComServerFactory();
private void initExecutorServer(int port, String ip, String appName, String accessToken) throws Exception { private void initExecutorServer(int port, String ip, String appName, String accessToken) throws Exception {
// valid param
port = port>0?port: NetUtil.findAvailablePort(9999);
// start server
NetComServerFactory.putService(ExecutorBiz.class, new ExecutorBizImpl()); // rpc-service, base on jetty NetComServerFactory.putService(ExecutorBiz.class, new ExecutorBizImpl()); // rpc-service, base on jetty
NetComServerFactory.setAccessToken(accessToken); NetComServerFactory.setAccessToken(accessToken);
serverFactory.start(port, ip, appName); // jetty + registry serverFactory.start(port, ip, appName); // jetty + registry
...@@ -140,13 +141,17 @@ public class XxlJobExecutor implements ApplicationContextAware { ...@@ -140,13 +141,17 @@ public class XxlJobExecutor implements ApplicationContextAware {
return jobHandlerRepository.get(name); return jobHandlerRepository.get(name);
} }
private static void initJobHandlerRepository(ApplicationContext applicationContext){ private static void initJobHandlerRepository(ApplicationContext applicationContext){
if (applicationContext == null) {
return;
}
// init job handler action // init job handler action
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHander.class); Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);
if (serviceBeanMap!=null && serviceBeanMap.size()>0) { if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
for (Object serviceBean : serviceBeanMap.values()) { for (Object serviceBean : serviceBeanMap.values()) {
if (serviceBean instanceof IJobHandler){ if (serviceBean instanceof IJobHandler){
String name = serviceBean.getClass().getAnnotation(JobHander.class).value(); String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
IJobHandler handler = (IJobHandler) serviceBean; IJobHandler handler = (IJobHandler) serviceBean;
if (loadJobHandler(name) != null) { if (loadJobHandler(name) != null) {
throw new RuntimeException("xxl-job jobhandler naming conflicts."); throw new RuntimeException("xxl-job jobhandler naming conflicts.");
......
...@@ -5,19 +5,40 @@ package com.xxl.job.core.glue; ...@@ -5,19 +5,40 @@ package com.xxl.job.core.glue;
*/ */
public enum GlueTypeEnum { public enum GlueTypeEnum {
BEAN("BEAN模式"), BEAN("BEAN模式", false, null, null),
GLUE_GROOVY("GLUE模式(Java)"), GLUE_GROOVY("GLUE模式(Java)", false, null, null),
GLUE_SHELL("GLUE模式(Shell)"), GLUE_SHELL("GLUE模式(Shell)", true, "bash", ".sh"),
GLUE_PYTHON("GLUE模式(Python)"); GLUE_PYTHON("GLUE模式(Python)", true, "python", ".py"),
GLUE_NODEJS("GLUE模式(Nodejs)", true, "node", ".js");
private String desc; private String desc;
private GlueTypeEnum(String desc) { private boolean isScript;
private String cmd;
private String suffix;
private GlueTypeEnum(String desc, boolean isScript, String cmd, String suffix) {
this.desc = desc; this.desc = desc;
this.isScript = isScript;
this.cmd = cmd;
this.suffix = suffix;
} }
public String getDesc() { public String getDesc() {
return desc; return desc;
} }
public boolean isScript() {
return isScript;
}
public String getCmd() {
return cmd;
}
public String getSuffix() {
return suffix;
}
public static GlueTypeEnum match(String name){ public static GlueTypeEnum match(String name){
for (GlueTypeEnum item: GlueTypeEnum.values()) { for (GlueTypeEnum item: GlueTypeEnum.values()) {
if (item.name().equals(name)) { if (item.name().equals(name)) {
...@@ -26,4 +47,5 @@ public enum GlueTypeEnum { ...@@ -26,4 +47,5 @@ public enum GlueTypeEnum {
} }
return null; return null;
} }
} }
...@@ -3,17 +3,45 @@ package com.xxl.job.core.handler; ...@@ -3,17 +3,45 @@ package com.xxl.job.core.handler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
/** /**
* remote job handler * job handler
*
* @author xuxueli 2015-12-19 19:06:38 * @author xuxueli 2015-12-19 19:06:38
*/ */
public abstract class IJobHandler { public abstract class IJobHandler {
/** success */
public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);
/** fail */
public static final ReturnT<String> FAIL = new ReturnT<String>(500, null);
/** fail retry */
public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);
/** /**
* job handler * execute handler, invoked when executor receives a scheduling request
* @param params *
* @param param
* @return * @return
* @throws Exception * @throws Exception
*/ */
public abstract ReturnT<String> execute(String... params) throws Exception; public abstract ReturnT<String> execute(String param) throws Exception;
/**
* init handler, invoked when JobThread init
*/
public void init() {
// TODO
}
/**
* destroy handler, invoked when JobThread destroy
*/
public void destroy() {
// TODO
}
} }
...@@ -13,7 +13,7 @@ import java.lang.annotation.Target; ...@@ -13,7 +13,7 @@ import java.lang.annotation.Target;
@Target({ElementType.TYPE}) @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Inherited @Inherited
public @interface JobHander { public @interface JobHandler {
String value() default ""; String value() default "";
......
...@@ -21,9 +21,9 @@ public class GlueJobHandler extends IJobHandler { ...@@ -21,9 +21,9 @@ public class GlueJobHandler extends IJobHandler {
} }
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("----------- glue.version:"+ glueUpdatetime +" -----------"); XxlJobLogger.log("----------- glue.version:"+ glueUpdatetime +" -----------");
return jobHandler.execute(params); return jobHandler.execute(param);
} }
} }
...@@ -6,6 +6,7 @@ import com.xxl.job.core.handler.IJobHandler; ...@@ -6,6 +6,7 @@ import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.log.XxlJobFileAppender; import com.xxl.job.core.log.XxlJobFileAppender;
import com.xxl.job.core.log.XxlJobLogger; import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.util.ScriptUtil; import com.xxl.job.core.util.ScriptUtil;
import com.xxl.job.core.util.ShardingUtil;
/** /**
* Created by xuxueli on 17/4/27. * Created by xuxueli on 17/4/27.
...@@ -29,29 +30,38 @@ public class ScriptJobHandler extends IJobHandler { ...@@ -29,29 +30,38 @@ public class ScriptJobHandler extends IJobHandler {
} }
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
// cmd + script-file-name if (!glueType.isScript()) {
String cmd = "bash"; return new ReturnT<String>(IJobHandler.FAIL.getCode(), "glueType["+ glueType +"] invalid.");
String scriptFileName = null;
if (GlueTypeEnum.GLUE_SHELL == glueType) {
cmd = "bash";
scriptFileName = XxlJobFileAppender.logPath.concat("gluesource/").concat(String.valueOf(jobId)).concat("_").concat(String.valueOf(glueUpdatetime)).concat(".sh");
} else if (GlueTypeEnum.GLUE_PYTHON == glueType) {
cmd = "python";
scriptFileName = XxlJobFileAppender.logPath.concat("gluesource/").concat(String.valueOf(jobId)).concat("_").concat(String.valueOf(glueUpdatetime)).concat(".py");
} }
// cmd
String cmd = glueType.getCmd();
// make script file // make script file
String scriptFileName = XxlJobFileAppender.getLogPath()
.concat("/gluesource/")
.concat(String.valueOf(jobId))
.concat("_")
.concat(String.valueOf(glueUpdatetime))
.concat(glueType.getSuffix());
ScriptUtil.markScriptFile(scriptFileName, gluesource); ScriptUtil.markScriptFile(scriptFileName, gluesource);
// log file // log file
String logFileName = XxlJobFileAppender.logPath.concat(XxlJobFileAppender.contextHolder.get()); String logFileName = XxlJobFileAppender.contextHolder.get();
// script params:0=param、1=分片序号、2=分片总数
ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
String[] scriptParams = new String[3];
scriptParams[0] = param;
scriptParams[1] = String.valueOf(shardingVO.getIndex());
scriptParams[2] = String.valueOf(shardingVO.getTotal());
// invoke // invoke
XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------"); XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------");
int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, params); int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, scriptParams);
ReturnT<String> result = (exitValue==0)?ReturnT.SUCCESS:new ReturnT<String>(ReturnT.FAIL_CODE, "script exit value("+exitValue+") is failed"); ReturnT<String> result = (exitValue==0)?IJobHandler.SUCCESS:new ReturnT<String>(IJobHandler.FAIL.getCode(), "script exit value("+exitValue+") is failed");
return result; return result;
} }
......
...@@ -18,11 +18,35 @@ public class XxlJobFileAppender { ...@@ -18,11 +18,35 @@ public class XxlJobFileAppender {
// for JobThread (support log for child thread of job handler) // for JobThread (support log for child thread of job handler)
//public static ThreadLocal<String> contextHolder = new ThreadLocal<String>(); //public static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>(); public static final InheritableThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // TODO, concurrent issues
public static String logPath = "/data/applogs/xxl-job/jobhandler/";
// log base path
private static String logBasePath = "/data/applogs/xxl-job/jobhandler";
public static void initLogPath(String logPath){
// init
if (logPath!=null && logPath.trim().length()>0) {
logBasePath = logPath;
}
// mk base dir
File logPathDir = new File(logBasePath);
if (!logPathDir.exists()) {
logPathDir.mkdirs();
}
logBasePath = logPathDir.getPath();
// mk glue dir
File glueBaseDir = new File(logPathDir, "gluesource");
if (!glueBaseDir.exists()) {
glueBaseDir.mkdirs();
}
}
public static String getLogPath() {
return logBasePath;
}
/** /**
* log filename: yyyy-MM-dd/9999.log * log filename, like "logPath/yyyy-MM-dd/9999.log"
* *
* @param triggerDate * @param triggerDate
* @param logId * @param logId
...@@ -30,21 +54,18 @@ public class XxlJobFileAppender { ...@@ -30,21 +54,18 @@ public class XxlJobFileAppender {
*/ */
public static String makeLogFileName(Date triggerDate, int logId) { public static String makeLogFileName(Date triggerDate, int logId) {
// filePath/ // filePath/yyyy-MM-dd
File filePathDir = new File(logPath); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // avoid concurrent problem, can not be static
if (!filePathDir.exists()) { File logFilePath = new File(getLogPath(), sdf.format(triggerDate));
filePathDir.mkdirs(); if (!logFilePath.exists()) {
} logFilePath.mkdir();
}
// filePath/yyyy-MM-dd/
String nowFormat = sdf.format(new Date()); // filePath/yyyy-MM-dd/9999.log
File filePathDateDir = new File(filePathDir, nowFormat); String logFileName = logFilePath.getPath()
if (!filePathDateDir.exists()) { .concat("/")
filePathDateDir.mkdirs(); .concat(String.valueOf(logId))
} .concat(".log");
// filePath/yyyy-MM-dd/9999.log
String logFileName = XxlJobFileAppender.sdf.format(triggerDate).concat("/").concat(String.valueOf(logId)).concat(".log");
return logFileName; return logFileName;
} }
...@@ -56,17 +77,11 @@ public class XxlJobFileAppender { ...@@ -56,17 +77,11 @@ public class XxlJobFileAppender {
*/ */
public static void appendLog(String logFileName, String appendLog) { public static void appendLog(String logFileName, String appendLog) {
// log
if (appendLog == null) {
appendLog = "";
}
appendLog += "\r\n";
// log file // log file
if (logFileName==null || logFileName.trim().length()==0) { if (logFileName==null || logFileName.trim().length()==0) {
return; return;
} }
File logFile = new File(logPath, logFileName); File logFile = new File(logFileName);
if (!logFile.exists()) { if (!logFile.exists()) {
try { try {
...@@ -76,6 +91,12 @@ public class XxlJobFileAppender { ...@@ -76,6 +91,12 @@ public class XxlJobFileAppender {
return; return;
} }
} }
// log
if (appendLog == null) {
appendLog = "";
}
appendLog += "\r\n";
// append file content // append file content
try { try {
...@@ -111,7 +132,7 @@ public class XxlJobFileAppender { ...@@ -111,7 +132,7 @@ public class XxlJobFileAppender {
if (logFileName==null || logFileName.trim().length()==0) { if (logFileName==null || logFileName.trim().length()==0) {
return new LogResult(fromLineNum, 0, "readLog fail, logFile not found", true); return new LogResult(fromLineNum, 0, "readLog fail, logFile not found", true);
} }
File logFile = new File(logPath, logFileName); File logFile = new File(logFileName);
if (!logFile.exists()) { if (!logFile.exists()) {
return new LogResult(fromLineNum, 0, "readLog fail, logFile not exists", true); return new LogResult(fromLineNum, 0, "readLog fail, logFile not exists", true);
......
...@@ -3,6 +3,8 @@ package com.xxl.job.core.log; ...@@ -3,6 +3,8 @@ package com.xxl.job.core.log;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
...@@ -12,51 +14,68 @@ import java.util.Date; ...@@ -12,51 +14,68 @@ import java.util.Date;
*/ */
public class XxlJobLogger { public class XxlJobLogger {
private static Logger logger = LoggerFactory.getLogger("xxl-job logger"); private static Logger logger = LoggerFactory.getLogger("xxl-job logger");
private static SimpleDateFormat xxlJobLoggerFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static SimpleDateFormat xxlJobLoggerFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // TODO,concurrent issue
/** /**
* append log * append log
* *
* @param callInfo
* @param appendLog * @param appendLog
*/ */
public static void log(String appendLog) { private static void logDetail(StackTraceElement callInfo, String appendLog) {
// logFileName
String logFileName = XxlJobFileAppender.contextHolder.get();
if (logFileName==null || logFileName.trim().length()==0) {
return;
}
// "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log"; /*// "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log";
StackTraceElement[] stackTraceElements = new Throwable().getStackTrace(); StackTraceElement[] stackTraceElements = new Throwable().getStackTrace();
StackTraceElement callInfo = stackTraceElements[1]; StackTraceElement callInfo = stackTraceElements[1];*/
StringBuffer stringBuffer = new StringBuffer(); StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(xxlJobLoggerFormat.format(new Date())).append(" ") stringBuffer.append(xxlJobLoggerFormat.format(new Date())).append(" ")
.append("["+ callInfo.getClassName() +"]").append("-") .append("["+ callInfo.getClassName() + "#" + callInfo.getMethodName() +"]").append("-")
.append("["+ callInfo.getMethodName() +"]").append("-")
.append("["+ callInfo.getLineNumber() +"]").append("-") .append("["+ callInfo.getLineNumber() +"]").append("-")
.append("["+ Thread.currentThread().getName() +"]").append(" ") .append("["+ Thread.currentThread().getName() +"]").append(" ")
.append(appendLog!=null?appendLog:""); .append(appendLog!=null?appendLog:"");
String formatAppendLog = stringBuffer.toString(); String formatAppendLog = stringBuffer.toString();
// appendlog // appendlog
XxlJobFileAppender.appendLog(logFileName, formatAppendLog); String logFileName = XxlJobFileAppender.contextHolder.get();
if (logFileName!=null && logFileName.trim().length()>0) {
logger.warn("[{}]: {}", logFileName, formatAppendLog); XxlJobFileAppender.appendLog(logFileName, formatAppendLog);
} else {
logger.info(">>>>>>>>>>> {}", formatAppendLog);
}
} }
/** /**
* append log with pattern * append log with pattern
* *
* @
*
* @param appendLogPattern like "aaa {0} bbb {1} ccc" * @param appendLogPattern like "aaa {0} bbb {1} ccc"
* @param appendLogArguments like "111, true" * @param appendLogArguments like "111, true"
*/ */
public static void log(String appendLogPattern, Object ... appendLogArguments) { public static void log(String appendLogPattern, Object ... appendLogArguments) {
String appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);
log(appendLog); String appendLog = appendLogPattern;
if (appendLogArguments!=null && appendLogArguments.length>0) {
appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);
}
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
logDetail(callInfo, appendLog);
}
/**
* append exception stack
*
* @param e
*/
public static void log(Throwable e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
String appendLog = stringWriter.toString();
StackTraceElement callInfo = new Throwable().getStackTrace()[1];
logDetail(callInfo, appendLog);
} }
} }
...@@ -36,6 +36,12 @@ public class NetComClientProxy implements FactoryBean<Object> { ...@@ -36,6 +36,12 @@ public class NetComClientProxy implements FactoryBean<Object> {
new InvocationHandler() { new InvocationHandler() {
@Override @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// filter method like "Object.toString()"
if (Object.class.getName().equals(method.getDeclaringClass().getName())) {
logger.error(">>>>>>>>>>> xxl-rpc proxy class-method not support [{}.{}]", method.getDeclaringClass().getName(), method.getName());
throw new RuntimeException("xxl-rpc proxy class-method not support");
}
// request // request
RpcRequest request = new RpcRequest(); RpcRequest request = new RpcRequest();
...@@ -46,7 +52,7 @@ public class NetComClientProxy implements FactoryBean<Object> { ...@@ -46,7 +52,7 @@ public class NetComClientProxy implements FactoryBean<Object> {
request.setMethodName(method.getName()); request.setMethodName(method.getName());
request.setParameterTypes(method.getParameterTypes()); request.setParameterTypes(method.getParameterTypes());
request.setParameters(args); request.setParameters(args);
// send // send
RpcResponse response = client.send(request); RpcResponse response = client.send(request);
......
...@@ -44,7 +44,7 @@ public class JettyServer { ...@@ -44,7 +44,7 @@ public class JettyServer {
try { try {
// Start server // Start server
server.start(); server.start();
logger.info(">>>>>>>>>>>> xxl-job jetty server start success at port:{}.", port); logger.info(">>>>>>>>>>> xxl-job jetty server start success at port:{}.", port);
// Start Registry-Server // Start Registry-Server
ExecutorRegistryThread.getInstance().start(port, ip, appName); ExecutorRegistryThread.getInstance().start(port, ip, appName);
......
...@@ -28,11 +28,11 @@ public class ExecutorRegistryThread extends Thread { ...@@ -28,11 +28,11 @@ public class ExecutorRegistryThread extends Thread {
// valid // valid
if (appName==null || appName.trim().length()==0) { if (appName==null || appName.trim().length()==0) {
logger.warn(">>>>>>>>>>>> xxl-job, executor registry config fail, appName is null."); logger.warn(">>>>>>>>>>> xxl-job, executor registry config fail, appName is null.");
return; return;
} }
if (XxlJobExecutor.getAdminBizList() == null) { if (XxlJobExecutor.getAdminBizList() == null) {
logger.warn(">>>>>>>>>>>> xxl-job, executor registry config fail, adminAddresses is null."); logger.warn(">>>>>>>>>>> xxl-job, executor registry config fail, adminAddresses is null.");
return; return;
} }
...@@ -99,7 +99,7 @@ public class ExecutorRegistryThread extends Thread { ...@@ -99,7 +99,7 @@ public class ExecutorRegistryThread extends Thread {
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
logger.warn(">>>>>>>>>>>> xxl-job, executor registry thread destory."); logger.info(">>>>>>>>>>> xxl-job, executor registry thread destory.");
} }
}); });
......
...@@ -57,7 +57,7 @@ public class JobThread extends Thread{ ...@@ -57,7 +57,7 @@ public class JobThread extends Thread{
public ReturnT<String> pushTriggerQueue(TriggerParam triggerParam) { public ReturnT<String> pushTriggerQueue(TriggerParam triggerParam) {
// avoid repeat // avoid repeat
if (triggerLogIdSet.contains(triggerParam.getLogId())) { if (triggerLogIdSet.contains(triggerParam.getLogId())) {
logger.debug("repeate trigger job, logId:{}", triggerParam.getLogId()); logger.info(">>>>>>>>>>> repeate trigger job, logId:{}", triggerParam.getLogId());
return new ReturnT<String>(ReturnT.FAIL_CODE, "repeate trigger job, logId:" + triggerParam.getLogId()); return new ReturnT<String>(ReturnT.FAIL_CODE, "repeate trigger job, logId:" + triggerParam.getLogId());
} }
...@@ -91,59 +91,42 @@ public class JobThread extends Thread{ ...@@ -91,59 +91,42 @@ public class JobThread extends Thread{
@Override @Override
public void run() { public void run() {
// init
try {
handler.init();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
// execute
while(!toStop){ while(!toStop){
running = false; running = false;
idleTimes++; idleTimes++;
try {
TriggerParam triggerParam = null;
ReturnT<String> executeResult = null;
try {
// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout) // to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
TriggerParam triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS); triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
if (triggerParam!=null) { if (triggerParam!=null) {
running = true; running = true;
idleTimes = 0; idleTimes = 0;
triggerLogIdSet.remove(triggerParam.getLogId()); triggerLogIdSet.remove(triggerParam.getLogId());
// parse param // log filename, like "logPath/yyyy-MM-dd/9999.log"
String[] handlerParams = (triggerParam.getExecutorParams()!=null && triggerParam.getExecutorParams().trim().length()>0) String logFileName = XxlJobFileAppender.makeLogFileName(new Date(triggerParam.getLogDateTim()), triggerParam.getLogId());
? (String[])(Arrays.asList(triggerParam.getExecutorParams().split(",")).toArray()) : null; XxlJobFileAppender.contextHolder.set(logFileName);
ShardingUtil.setShardingVo(new ShardingUtil.ShardingVO(triggerParam.getBroadcastIndex(), triggerParam.getBroadcastTotal()));
// handle job
ReturnT<String> executeResult = null; // execute
try { XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Param:" + triggerParam.getExecutorParams());
// log filename: yyyy-MM-dd/9999.log executeResult = handler.execute(triggerParam.getExecutorParams());
String logFileName = XxlJobFileAppender.makeLogFileName(new Date(triggerParam.getLogDateTim()), triggerParam.getLogId()); if (executeResult == null) {
executeResult = IJobHandler.FAIL;
XxlJobFileAppender.contextHolder.set(logFileName);
ShardingUtil.setShardingVo(new ShardingUtil.ShardingVO(triggerParam.getBroadcastIndex(), triggerParam.getBroadcastTotal()));
XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Params:" + Arrays.toString(handlerParams));
executeResult = handler.execute(handlerParams);
if (executeResult == null) {
executeResult = ReturnT.FAIL;
}
XxlJobLogger.log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + executeResult);
} catch (Exception e) {
if (toStop) {
XxlJobLogger.log("<br>----------- JobThread toStop, stopReason:" + stopReason);
}
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
String errorMsg = stringWriter.toString();
executeResult = new ReturnT<String>(ReturnT.FAIL_CODE, errorMsg);
XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------");
}
// callback handler info
if (!toStop) {
// commonm
TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), executeResult));
} else {
// is killed
ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [业务运行中,被强制终止]");
TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));
} }
XxlJobLogger.log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + executeResult);
} else { } else {
if (idleTimes > 30) { if (idleTimes > 30) {
XxlJobExecutor.removeJobThread(jobId, "excutor idel times over limit."); XxlJobExecutor.removeJobThread(jobId, "excutor idel times over limit.");
...@@ -151,16 +134,30 @@ public class JobThread extends Thread{ ...@@ -151,16 +134,30 @@ public class JobThread extends Thread{
} }
} catch (Throwable e) { } catch (Throwable e) {
if (toStop) { if (toStop) {
XxlJobLogger.log("<br>----------- xxl-job toStop, stopReason:" + stopReason); XxlJobLogger.log("<br>----------- JobThread toStop, stopReason:" + stopReason);
} }
StringWriter stringWriter = new StringWriter(); StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter)); e.printStackTrace(new PrintWriter(stringWriter));
String errorMsg = stringWriter.toString(); String errorMsg = stringWriter.toString();
XxlJobLogger.log("----------- xxl-job JobThread Exception:" + errorMsg); executeResult = new ReturnT<String>(ReturnT.FAIL_CODE, errorMsg);
}
} XxlJobLogger.log("<br>----------- JobThread Exception:" + errorMsg + "<br>----------- xxl-job job execute end(error) -----------");
} finally {
if(triggerParam != null) {
// callback handler info
if (!toStop) {
// commonm
TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), executeResult));
} else {
// is killed
ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [业务运行中,被强制终止]");
TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));
}
}
}
}
// callback trigger request in queue // callback trigger request in queue
while(triggerQueue !=null && triggerQueue.size()>0){ while(triggerQueue !=null && triggerQueue.size()>0){
TriggerParam triggerParam = triggerQueue.poll(); TriggerParam triggerParam = triggerQueue.poll();
...@@ -170,7 +167,14 @@ public class JobThread extends Thread{ ...@@ -170,7 +167,14 @@ public class JobThread extends Thread{
TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult)); TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));
} }
} }
logger.info(">>>>>>>>>>>> xxl-job JobThread stoped, hashCode:{}", Thread.currentThread()); // destroy
try {
handler.destroy();
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
logger.info(">>>>>>>>>>> xxl-job JobThread stoped, hashCode:{}", Thread.currentThread());
} }
} }
...@@ -40,7 +40,7 @@ public class TriggerCallbackThread { ...@@ -40,7 +40,7 @@ public class TriggerCallbackThread {
// valid // valid
if (XxlJobExecutor.getAdminBizList() == null) { if (XxlJobExecutor.getAdminBizList() == null) {
logger.warn(">>>>>>>>>>>> xxl-job, executor callback config fail, adminAddresses is null."); logger.warn(">>>>>>>>>>> xxl-job, executor callback config fail, adminAddresses is null.");
return; return;
} }
...@@ -80,7 +80,7 @@ public class TriggerCallbackThread { ...@@ -80,7 +80,7 @@ public class TriggerCallbackThread {
} catch (Exception e) { } catch (Exception e) {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} }
logger.warn(">>>>>>>>>>>> xxl-job, executor callback thread destory."); logger.info(">>>>>>>>>>> xxl-job, executor callback thread destory.");
} }
}); });
......
...@@ -64,7 +64,7 @@ public class HttpClientUtil { ...@@ -64,7 +64,7 @@ public class HttpClientUtil {
EntityUtils.consume(entity); EntityUtils.consume(entity);
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("", e); logger.error(e.getMessage(), e);
throw e; throw e;
} finally { } finally {
httpPost.releaseConnection(); httpPost.releaseConnection();
......
package com.xxl.job.core.util; package com.xxl.job.core.util;
import com.fasterxml.jackson.core.JsonGenerationException;
import org.codehaus.jackson.JsonGenerationException; import com.fasterxml.jackson.core.JsonParseException;
import org.codehaus.jackson.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference;
import org.codehaus.jackson.map.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
......
package com.xxl.job.core.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.ServerSocket;
/**
* net util
*
* @author xuxueli 2017-11-29 17:00:25
*/
public class NetUtil {
private static Logger logger = LoggerFactory.getLogger(NetUtil.class);
/**
* find avaliable port
*
* @param defaultPort
* @return
*/
public static int findAvailablePort(int defaultPort) {
int portTmp = defaultPort;
while (portTmp < 65535) {
if (!isPortUsed(portTmp)) {
return portTmp;
} else {
portTmp++;
}
}
portTmp = defaultPort--;
while (portTmp > 0) {
if (!isPortUsed(portTmp)) {
return portTmp;
} else {
portTmp--;
}
}
throw new IllegalStateException("no available port.");
}
/**
* check port used
*
* @param port
* @return
*/
public static boolean isPortUsed(int port) {
boolean used = false;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
used = false;
} catch (IOException e) {
logger.debug(">>>>>>>>>>> xxl-job, port[{}] is in use.", port);
used = true;
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
logger.info("");
}
}
}
return used;
}
}
package com.xxl.job.core.util; package com.xxl.job.core.util;
import com.xxl.job.core.log.XxlJobFileAppender;
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.PumpStreamHandler; import org.apache.commons.exec.PumpStreamHandler;
import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
...@@ -27,18 +25,6 @@ public class ScriptUtil { ...@@ -27,18 +25,6 @@ public class ScriptUtil {
* @throws IOException * @throws IOException
*/ */
public static void markScriptFile(String scriptFileName, String content) throws IOException { public static void markScriptFile(String scriptFileName, String content) throws IOException {
// filePath/
File filePathDir = new File(XxlJobFileAppender.logPath);
if (!filePathDir.exists()) {
filePathDir.mkdirs();
}
// filePath/gluesource/
File filePathSourceDir = new File(filePathDir, "gluesource");
if (!filePathSourceDir.exists()) {
filePathSourceDir.mkdirs();
}
// make file, filePath/gluesource/666-123456789.py // make file, filePath/gluesource/666-123456789.py
FileOutputStream fileOutputStream = null; FileOutputStream fileOutputStream = null;
try { try {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId> <artifactId>xxl-job</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>xxl-job-executor-samples</artifactId> <artifactId>xxl-job-executor-samples</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>xxl-job-executor-samples</artifactId> <artifactId>xxl-job-executor-samples</artifactId>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>xxl-job-executor-sample-jfinal</artifactId> <artifactId>xxl-job-executor-sample-jfinal</artifactId>
...@@ -16,7 +16,14 @@ ...@@ -16,7 +16,14 @@
<dependency> <dependency>
<groupId>com.jfinal</groupId> <groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId> <artifactId>jfinal</artifactId>
<version>2.0</version> <version>2.2</version>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-api.version}</version>
</dependency> </dependency>
<!-- xxl-job --> <!-- xxl-job -->
...@@ -26,11 +33,6 @@ ...@@ -26,11 +33,6 @@
<version>${project.parent.version}</version> <version>${project.parent.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -20,14 +20,14 @@ import java.util.concurrent.TimeUnit; ...@@ -20,14 +20,14 @@ import java.util.concurrent.TimeUnit;
public class DemoJobHandler extends IJobHandler { public class DemoJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World."); XxlJobLogger.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
XxlJobLogger.log("beat at:" + i); XxlJobLogger.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2); TimeUnit.SECONDS.sleep(2);
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -14,7 +14,7 @@ import com.xxl.job.core.util.ShardingUtil; ...@@ -14,7 +14,7 @@ import com.xxl.job.core.util.ShardingUtil;
public class ShardingJobHandler extends IJobHandler { public class ShardingJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
// 分片参数 // 分片参数
ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
...@@ -29,7 +29,7 @@ public class ShardingJobHandler extends IJobHandler { ...@@ -29,7 +29,7 @@ public class ShardingJobHandler extends IJobHandler {
} }
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -7,7 +7,7 @@ xxl.job.executor.ip= ...@@ -7,7 +7,7 @@ xxl.job.executor.ip=
xxl.job.executor.port=9997 xxl.job.executor.port=9997
### xxl-job log path ### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/ xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job, access token ### xxl-job, access token
xxl.job.accessToken= xxl.job.accessToken=
\ No newline at end of file
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5"> id="WebApp_ID" version="2.5">
<display-name>jfinal-demo</display-name> <display-name>xxl-job-executor-sample-jfinal</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>xxl-job-executor-sample-jfinal</param-value>
</context-param>
<!-- jfinal --> <!-- jfinal -->
<filter> <filter>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job-executor-samples</artifactId> <artifactId>xxl-job-executor-samples</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>xxl-job-executor-sample-spring</artifactId> <artifactId>xxl-job-executor-sample-spring</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
......
...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler; ...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger; import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -15,24 +15,24 @@ import java.util.concurrent.TimeUnit; ...@@ -15,24 +15,24 @@ import java.util.concurrent.TimeUnit;
* 开发步骤: * 开发步骤:
* 1、新建一个继承com.xxl.job.core.handler.IJobHandler的Java类; * 1、新建一个继承com.xxl.job.core.handler.IJobHandler的Java类;
* 2、该类被Spring容器扫描为Bean实例,如加“@Component”注解; * 2、该类被Spring容器扫描为Bean实例,如加“@Component”注解;
* 3、添加 “@JobHander(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称对应的是调度中心新建任务的JobHandler属性的值。 * 3、添加 “@JobHandler(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称对应的是调度中心新建任务的JobHandler属性的值。
* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; * 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
* *
* @author xuxueli 2015-12-19 19:43:36 * @author xuxueli 2015-12-19 19:43:36
*/ */
@JobHander(value="demoJobHandler") @JobHandler(value="demoJobHandler")
@Component @Component
public class DemoJobHandler extends IJobHandler { public class DemoJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World."); XxlJobLogger.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
XxlJobLogger.log("beat at:" + i); XxlJobLogger.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2); TimeUnit.SECONDS.sleep(2);
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler; ...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger; import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.util.ShardingUtil; import com.xxl.job.core.util.ShardingUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -13,12 +13,12 @@ import org.springframework.stereotype.Service; ...@@ -13,12 +13,12 @@ import org.springframework.stereotype.Service;
* *
* @author xuxueli 2017-07-25 20:56:50 * @author xuxueli 2017-07-25 20:56:50
*/ */
@JobHander(value="shardingJobHandler") @JobHandler(value="shardingJobHandler")
@Service @Service
public class ShardingJobHandler extends IJobHandler { public class ShardingJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
// 分片参数 // 分片参数
ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
...@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler { ...@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler {
} }
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="fileEncoding" value="utf-8" /> <property name="fileEncoding" value="utf-8" />
......
...@@ -7,7 +7,7 @@ xxl.job.executor.ip= ...@@ -7,7 +7,7 @@ xxl.job.executor.ip=
xxl.job.executor.port=9999 xxl.job.executor.port=9999
### xxl-job log path ### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/ xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job, access token ### xxl-job, access token
xxl.job.accessToken= xxl.job.accessToken=
\ No newline at end of file
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5"> id="WebApp_ID" version="2.5">
<display-name>xxl-job-executor-sample-spring</display-name>
<context-param> <context-param>
<param-name>webAppRootKey</param-name> <param-name>webAppRootKey</param-name>
<param-value>xxl-job-executor-sample-spring</param-value> <param-value>xxl-job-executor-sample-spring</param-value>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.xuxueli</groupId> <groupId>com.xuxueli</groupId>
<artifactId>xxl-job-executor-samples</artifactId> <artifactId>xxl-job-executor-samples</artifactId>
<version>1.8.2-SNAPSHOT</version> <version>1.9.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>xxl-job-executor-sample-springboot</artifactId> <artifactId>xxl-job-executor-sample-springboot</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
......
package com.xxl.job.executor.mvc.controller; //package com.xxl.job.executor.mvc.controller;
//
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; //import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller; //import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; //import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; //import org.springframework.web.bind.annotation.ResponseBody;
//
@Controller //@Controller
@EnableAutoConfiguration //@EnableAutoConfiguration
public class IndexController { //public class IndexController {
//
@RequestMapping("/") // @RequestMapping("/")
@ResponseBody // @ResponseBody
String index() { // String index() {
return "xxl job executor running."; // return "xxl job executor running.";
} // }
//
} //}
\ No newline at end of file \ No newline at end of file
...@@ -2,9 +2,9 @@ package com.xxl.job.executor.service.jobhandler; ...@@ -2,9 +2,9 @@ package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger; import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -13,26 +13,26 @@ import java.util.concurrent.TimeUnit; ...@@ -13,26 +13,26 @@ import java.util.concurrent.TimeUnit;
* 任务Handler的一个Demo(Bean模式) * 任务Handler的一个Demo(Bean模式)
* *
* 开发步骤: * 开发步骤:
* 1、继承 “IJobHandler” * 1、新建一个继承com.xxl.job.core.handler.IJobHandler的Java类
* 2、装配到Spring,例如加 “@Service” 注解; * 2、该类被Spring容器扫描为Bean实例,如加“@Component”注解;
* 3、加 “@JobHander” 注解,注解value值为新增任务生成的JobKey的值;多个JobKey用逗号分割; * 3、添加 “@JobHandler(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称对应的是调度中心新建任务的JobHandler属性的值。
* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志; * 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
* *
* @author xuxueli 2015-12-19 19:43:36 * @author xuxueli 2015-12-19 19:43:36
*/ */
@JobHander(value="demoJobHandler") @JobHandler(value="demoJobHandler")
@Service @Component
public class DemoJobHandler extends IJobHandler { public class DemoJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World."); XxlJobLogger.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
XxlJobLogger.log("beat at:" + i); XxlJobLogger.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2); TimeUnit.SECONDS.sleep(2);
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler; ...@@ -2,7 +2,7 @@ package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander; import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger; import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.core.util.ShardingUtil; import com.xxl.job.core.util.ShardingUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -13,12 +13,12 @@ import org.springframework.stereotype.Service; ...@@ -13,12 +13,12 @@ import org.springframework.stereotype.Service;
* *
* @author xuxueli 2017-07-25 20:56:50 * @author xuxueli 2017-07-25 20:56:50
*/ */
@JobHander(value="shardingJobHandler") @JobHandler(value="shardingJobHandler")
@Service @Service
public class ShardingJobHandler extends IJobHandler { public class ShardingJobHandler extends IJobHandler {
@Override @Override
public ReturnT<String> execute(String... params) throws Exception { public ReturnT<String> execute(String param) throws Exception {
// 分片参数 // 分片参数
ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo(); ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
...@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler { ...@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler {
} }
} }
return ReturnT.SUCCESS; return SUCCESS;
} }
} }
...@@ -11,10 +11,10 @@ xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin ...@@ -11,10 +11,10 @@ xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job executor address ### xxl-job executor address
xxl.job.executor.appname=xxl-job-executor-sample xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip= xxl.job.executor.ip=
xxl.job.executor.port=9998 xxl.job.executor.port=-1
### xxl-job log path ### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/ xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job, access token ### xxl-job, access token
xxl.job.accessToken= xxl.job.accessToken=
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论