提交 bedb34a4 authored 作者: xueli.xue's avatar xueli.xue

JobBean交互完善

上级 23423855
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/webapp"/>
<classpathentry excluding="**/*.min.js|**/node_modules/*|**/bower_components/*" kind="src" path="target/m2e-wtp/web-resources"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
disabled=06target
eclipse.preferences.version=1
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<artifactId>xxl-job-simple</artifactId> <artifactId>xxl-job-simple</artifactId>
<version>1.1.2-SNAPSHOT</version> <version>1.1.2-SNAPSHOT</version>
<packaging>war</packaging> <packaging>war</packaging>
<properties> <properties>
<spring.version>3.2.14.RELEASE</spring.version> <spring.version>3.2.14.RELEASE</spring.version>
</properties> </properties>
...@@ -129,7 +129,14 @@ ...@@ -129,7 +129,14 @@
<artifactId>quartz</artifactId> <artifactId>quartz</artifactId>
<version>2.2.1</version> <version>2.2.1</version>
</dependency> </dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.6</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.xxl.controller; package com.xxl.job.controller;
import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.quartz.CronExpression; import org.quartz.CronExpression;
...@@ -13,27 +18,67 @@ import org.springframework.ui.Model; ...@@ -13,27 +18,67 @@ import org.springframework.ui.Model;
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;
import com.xxl.quartz.DynamicSchedulerUtil; import com.xxl.job.core.model.ReturnT;
import com.xxl.quartz.ReturnT; import com.xxl.job.core.util.DynamicSchedulerUtil;
import com.xxl.job.service.job.DemoJobBean;
import com.xxl.job.service.job.DemoJobBeanB;
/**
* index controller
* @author xuxueli 2015-12-19 16:13:16
*/
@Controller @Controller
public class IndexController { public class IndexController {
// local job bean list
public static Map<String, String> jobBeanMap = new HashMap<String, String>();
@RequestMapping("") @RequestMapping("")
public String index(Model model) { public String index(Model model) {
jobBeanMap.put(DemoJobBean.class.getName(), "测试任务");
jobBeanMap.put(DemoJobBeanB.class.getName(), "测试任务B");
model.addAttribute("jobBeanMap", jobBeanMap);
// job list
List<Map<String, Object>> jobList = DynamicSchedulerUtil.getJobList(); List<Map<String, Object>> jobList = DynamicSchedulerUtil.getJobList();
model.addAttribute("jobList", jobList); model.addAttribute("jobList", jobList);
return "job/index"; return "job/index";
} }
@RequestMapping("/add") @RequestMapping("/help")
public String help(Model model) {
return "job/help";
}
@SuppressWarnings("unchecked")
@RequestMapping("/job/add")
@ResponseBody @ResponseBody
public ReturnT<String> add(String triggerKeyName, String cronExpression, String jobClassName, String jobDesc) { public ReturnT<String> add(HttpServletRequest request) {
String triggerKeyName = null;
String cronExpression = null;
Map<String, Object> jobData = new HashMap<String, Object>();
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
Set<Map.Entry<String, String[]>> paramSet = request.getParameterMap().entrySet();
for (Entry<String, String[]> param : paramSet) {
if (param.getKey().equals("triggerKeyName")) {
triggerKeyName = param.getValue()[0];
} else if (param.getKey().equals("cronExpression")) {
cronExpression = param.getValue()[0];
} else {
jobData.put(param.getKey(), param.getValue().length>0?param.getValue()[0]:param.getValue());
}
}
// triggerKeyName // triggerKeyName
if (StringUtils.isBlank(triggerKeyName)) { if (StringUtils.isBlank(triggerKeyName)) {
return new ReturnT<String>(500, "请输入“任务key”"); return new ReturnT<String>(500, "请输入“任务key”");
} }
// cronExpression // cronExpression
if (StringUtils.isBlank(cronExpression)) { if (StringUtils.isBlank(cronExpression)) {
return new ReturnT<String>(500, "请输入“任务corn”"); return new ReturnT<String>(500, "请输入“任务corn”");
...@@ -41,37 +86,45 @@ public class IndexController { ...@@ -41,37 +86,45 @@ public class IndexController {
if (!CronExpression.isValidExpression(cronExpression)) { if (!CronExpression.isValidExpression(cronExpression)) {
return new ReturnT<String>(500, "“任务corn”不合法"); return new ReturnT<String>(500, "“任务corn”不合法");
} }
// jobClassName
Class<?> clazz = null; // jobData
if (jobData.get(DynamicSchedulerUtil.job_desc)==null || jobData.get(DynamicSchedulerUtil.job_desc).toString().trim().length()==0) {
return new ReturnT<String>(500, "请输入“任务描述”");
}
// job_bean
String job_bean = (String) jobData.get(DynamicSchedulerUtil.job_bean);
if (StringUtils.isBlank(job_bean)) {
return new ReturnT<String>(500, "JobBean不可为空");
}
// jobClass
Class<? extends Job> jobClass = null;
try { try {
clazz = Class.forName(jobClassName); Class<?> clazz = Class.forName(job_bean);
if (clazz!=null) {
jobClass = (Class<? extends Job>) clazz;
}
} catch (ClassNotFoundException e1) { } catch (ClassNotFoundException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
if (clazz == null) { if (jobClass == null) {
return new ReturnT<String>(500, "“任务Impl”不合法"); return new ReturnT<String>(500, "JobBean未知");
}
if (!Job.class.isAssignableFrom(clazz)) {
return new ReturnT<String>(500, "“任务Impl”类必须继承Job接口");
}
@SuppressWarnings("unchecked")
Class<? extends Job> jobClass = (Class<? extends Job>)clazz;
// jobDesc
if (StringUtils.isBlank(jobDesc)) {
return new ReturnT<String>(500, "请输入“任务描述”");
} }
try { try {
Map<String, Object> jobData = new HashMap<String, Object>(); boolean result = DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, jobData);
jobData.put(DynamicSchedulerUtil.job_desc, jobDesc); if (!result) {
DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, jobData); return new ReturnT<String>(500, "任务ID重复,请更换确认");
}
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} catch (SchedulerException e) { } catch (SchedulerException e) {
e.printStackTrace(); e.printStackTrace();
} }
return ReturnT.FAIL; return ReturnT.FAIL;
} }
@RequestMapping("/reschedule") @RequestMapping("/job/reschedule")
@ResponseBody @ResponseBody
public ReturnT<String> reschedule(String triggerKeyName, String cronExpression) { public ReturnT<String> reschedule(String triggerKeyName, String cronExpression) {
// triggerKeyName // triggerKeyName
...@@ -94,7 +147,7 @@ public class IndexController { ...@@ -94,7 +147,7 @@ public class IndexController {
return ReturnT.FAIL; return ReturnT.FAIL;
} }
@RequestMapping("/remove") @RequestMapping("/job/remove")
@ResponseBody @ResponseBody
public ReturnT<String> remove(String triggerKeyName) { public ReturnT<String> remove(String triggerKeyName) {
try { try {
...@@ -106,7 +159,7 @@ public class IndexController { ...@@ -106,7 +159,7 @@ public class IndexController {
} }
} }
@RequestMapping("/pause") @RequestMapping("/job/pause")
@ResponseBody @ResponseBody
public ReturnT<String> pause(String triggerKeyName) { public ReturnT<String> pause(String triggerKeyName) {
try { try {
...@@ -118,7 +171,7 @@ public class IndexController { ...@@ -118,7 +171,7 @@ public class IndexController {
} }
} }
@RequestMapping("/resume") @RequestMapping("/job/resume")
@ResponseBody @ResponseBody
public ReturnT<String> resume(String triggerKeyName) { public ReturnT<String> resume(String triggerKeyName) {
try { try {
...@@ -130,9 +183,16 @@ public class IndexController { ...@@ -130,9 +183,16 @@ public class IndexController {
} }
} }
@RequestMapping("/help") @RequestMapping("/job/trigger")
public String help(Model model) { @ResponseBody
return "job/help"; public ReturnT<String> triggerJob(String triggerKeyName) {
try {
DynamicSchedulerUtil.triggerJob(triggerKeyName);
return ReturnT.SUCCESS;
} catch (SchedulerException e) {
e.printStackTrace();
return ReturnT.FAIL;
}
} }
} }
package com.xxl.quartz; package com.xxl.job.core.model;
/** /**
* common return * common return
......
package com.xxl.job.core.model;
import java.util.Date;
/**
* xxl-job log, used to track trigger process
* @author xuxueli 2015-12-19 23:19:09
*/
public class XxlJobLog {
private String jobTriggerUuid;
private String jobHandleName;
// trigger info
private Date triggerTime;
private String triggerStatus;
private String triggerDetailLog;
// handle info
private Date handleTime;
private String handleStatus;
private String handleDetailLog;
public String getJobTriggerUuid() {
return jobTriggerUuid;
}
public void setJobTriggerUuid(String jobTriggerUuid) {
this.jobTriggerUuid = jobTriggerUuid;
}
public String getJobHandleName() {
return jobHandleName;
}
public void setJobHandleName(String jobHandleName) {
this.jobHandleName = jobHandleName;
}
public Date getTriggerTime() {
return triggerTime;
}
public void setTriggerTime(Date triggerTime) {
this.triggerTime = triggerTime;
}
public String getTriggerStatus() {
return triggerStatus;
}
public void setTriggerStatus(String triggerStatus) {
this.triggerStatus = triggerStatus;
}
public String getTriggerDetailLog() {
return triggerDetailLog;
}
public void setTriggerDetailLog(String triggerDetailLog) {
this.triggerDetailLog = triggerDetailLog;
}
public Date getHandleTime() {
return handleTime;
}
public void setHandleTime(Date handleTime) {
this.handleTime = handleTime;
}
public String getHandleStatus() {
return handleStatus;
}
public void setHandleStatus(String handleStatus) {
this.handleStatus = handleStatus;
}
public String getHandleDetailLog() {
return handleDetailLog;
}
public void setHandleDetailLog(String handleDetailLog) {
this.handleDetailLog = handleDetailLog;
}
@Override
public String toString() {
return "XxlJobLog [jobTriggerUuid=" + jobTriggerUuid + ", jobHandleName=" + jobHandleName
+ ", triggerTime=" + triggerTime + ", triggerStatus=" + triggerStatus + ", triggerDetailLog="
+ triggerDetailLog + ", handleTime=" + handleTime + ", handleStatus=" + handleStatus
+ ", handleDetailLog=" + handleDetailLog + "]";
}
}
package com.xxl.quartz; package com.xxl.job.core.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
...@@ -26,6 +26,10 @@ import org.slf4j.LoggerFactory; ...@@ -26,6 +26,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/**
* base quartz scheduler util
* @author xuxueli 2015-12-19 16:13:53
*/
public final class DynamicSchedulerUtil implements InitializingBean { public final class DynamicSchedulerUtil implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(DynamicSchedulerUtil.class); private static final Logger logger = LoggerFactory.getLogger(DynamicSchedulerUtil.class);
...@@ -74,6 +78,8 @@ public final class DynamicSchedulerUtil implements InitializingBean { ...@@ -74,6 +78,8 @@ public final class DynamicSchedulerUtil implements InitializingBean {
} }
public static final String job_desc = "job_desc"; public static final String job_desc = "job_desc";
public static final String job_bean = "job_bean";
// addJob 新增 // addJob 新增
public static boolean addJob(String triggerKeyName, String cronExpression, Class<? extends Job> jobClass, Map<String, Object> jobData) throws SchedulerException { public static boolean addJob(String triggerKeyName, String cronExpression, Class<? extends Job> jobClass, Map<String, Object> jobData) throws SchedulerException {
// TriggerKey : name + group // TriggerKey : name + group
...@@ -173,5 +179,22 @@ public final class DynamicSchedulerUtil implements InitializingBean { ...@@ -173,5 +179,22 @@ public final class DynamicSchedulerUtil implements InitializingBean {
} }
return result; return result;
} }
// run 执行一次
public static boolean triggerJob(String triggerKeyName) throws SchedulerException {
// TriggerKey : name + group
String group = Scheduler.DEFAULT_GROUP;
JobKey jobKey = JobKey.jobKey(triggerKeyName, group);
boolean result = false;
if (scheduler.checkExists(jobKey)) {
scheduler.triggerJob(jobKey);
result = true;
logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
} else {
logger.info(">>>>>>>>>>> runJob fail, jobKey:{}", jobKey);
}
return result;
}
} }
\ No newline at end of file
package com.xxl.service; package com.xxl.job.service;
/**
* local trigger, only exists in local jvm
* @author xuxueli 2015-12-17 17:29:23
*/
public interface ITriggerService { public interface ITriggerService {
public void beat(); public void beat();
......
package com.xxl.service.impl; package com.xxl.job.service.impl;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.xxl.service.ITriggerService; import com.xxl.job.service.ITriggerService;
/**
* local trigger, only exists in local jvm
* @author xuxueli 2015-12-17 17:31:24
*/
@Service("triggerService") @Service("triggerService")
public class TriggerServiceImpl implements ITriggerService { public class TriggerServiceImpl implements ITriggerService {
private static transient Logger logger = LoggerFactory.getLogger(TriggerServiceImpl.class); private static transient Logger logger = LoggerFactory.getLogger(TriggerServiceImpl.class);
public void beat() { public void beat() {
logger.info(">>>>>>>>>> xxl-job : local quartz beat success."); logger.info(">>>>>>>>>>> xxl-job beat success.");
} }
} }
package com.xxl.job.service.job;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* http job bean
* @author xuxueli 2015-12-17 18:20:34
*/
public class DemoJobBean extends QuartzJobBean {
private static Logger logger = LoggerFactory.getLogger(DemoJobBean.class);
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
String triggerKey = context.getTrigger().getKey().getName();
String triggerGroup = context.getTrigger().getKey().getGroup();
Map<String, Object> jobDataMap = context.getMergedJobDataMap().getWrappedMap();
// jobDataMap 2 params
Map<String, String> params = new HashMap<String, String>();
if (jobDataMap!=null && jobDataMap.size()>0) {
for (Entry<String, Object> item : jobDataMap.entrySet()) {
params.put(item.getKey(), String.valueOf(item.getValue()));
}
}
logger.info(">>>>>>>>>>> xxl-job run :jobId:{}, group:{}, jobDataMap:{}",
new Object[]{triggerKey, triggerGroup, jobDataMap});
}
}
\ No newline at end of file
package com.xxl.job.service.job;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* http job bean
* @author xuxueli 2015-12-17 18:20:34
*/
public class DemoJobBeanB extends QuartzJobBean {
private static Logger logger = LoggerFactory.getLogger(DemoJobBeanB.class);
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
String triggerKey = context.getTrigger().getKey().getName();
String triggerGroup = context.getTrigger().getKey().getGroup();
Map<String, Object> jobDataMap = context.getMergedJobDataMap().getWrappedMap();
// jobDataMap 2 params
Map<String, String> params = new HashMap<String, String>();
if (jobDataMap!=null && jobDataMap.size()>0) {
for (Entry<String, Object> item : jobDataMap.entrySet()) {
params.put(item.getKey(), String.valueOf(item.getValue()));
}
}
logger.info(">>>>>>>>>>> xxl-job run :jobId:{}, group:{}, jobDataMap:{}",
new Object[]{triggerKey, triggerGroup, jobDataMap});
}
}
\ No newline at end of file
package com.xxl.service.job;
import java.util.Date;
import org.apache.commons.lang.time.FastDateFormat;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class JobDetailDemo extends QuartzJobBean {
private static Logger logger = LoggerFactory.getLogger(JobDetailDemo.class);
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
logger.info("全站静态化[DB] run at :{}", FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
package com.xxl.service.job;
import java.util.concurrent.TimeUnit;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xxl.quartz.DynamicSchedulerUtil;
public class TestDynamicJob implements Job {
private static Logger logger = LoggerFactory.getLogger(TestDynamicJob.class);
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
logger.info("xxl-job run: name:{}, group:{}, job_desc:{}",
new Object[]{context.getTrigger().getKey().getName(), context.getTrigger().getKey().getGroup(),
context.getMergedJobDataMap().get(DynamicSchedulerUtil.job_desc)});
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
http://www.springframework.org/schema/util/spring-util.xsd"> http://www.springframework.org/schema/util/spring-util.xsd">
<context:annotation-config /> <context:annotation-config />
<context:component-scan base-package="com.xxl.service.impl, com.xxl.dao.impl" /> <context:component-scan base-package="com.xxl.job.service" />
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/template/" /> <property name="templateLoaderPath" value="/WEB-INF/template/" />
...@@ -19,11 +19,6 @@ ...@@ -19,11 +19,6 @@
<property name="location" value="classpath:freemarker.properties" /> <property name="location" value="classpath:freemarker.properties" />
</bean> </bean>
</property> </property>
<property name="freemarkerVariables">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:freemarker.variables.properties" />
</bean>
</property>
</bean> </bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
<context:annotation-config /> <context:annotation-config />
<context:component-scan base-package="com.xxl.service.impl, com.xxl.dao.impl" /> <context:component-scan base-package="com.xxl.service.impl, com.xxl.dao.impl" />
<!-- c3p0:Main数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${c3p0.driverClass}" /> <property name="driverClass" value="${c3p0.driverClass}" />
<property name="jdbcUrl" value="${c3p0.url}" /> <property name="jdbcUrl" value="${c3p0.url}" />
...@@ -35,7 +34,7 @@ ...@@ -35,7 +34,7 @@
<property name="mapperLocations" value="classpath*:com/xxl/core/model/mapper/*.xml"/> <property name="mapperLocations" value="classpath*:com/xxl/core/model/mapper/*.xml"/>
</bean> </bean>
<!-- Template在Junit测试的时候,必须使用scope="prototype",原因未知 --> <!-- scope must be "prototype" when junit -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype"> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory" /> <constructor-arg index="0" ref="sqlSessionFactory" />
</bean> </bean>
......
...@@ -9,37 +9,16 @@ ...@@ -9,37 +9,16 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"> http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Job trigger -->
<bean id="job02Trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" >
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.xxl.service.job.JobDetailDemo"/>
<property name="jobDataAsMap">
<map>
<!-- <entry key="xxService" value-ref="xxService" /> -->
</map>
</property>
<property name="durability" value="true" />
</bean>
</property>
<property name="cronExpression" value="0/3 * * * * ? *" />
</bean>
<!-- Job信息会被上报并持久化到mysql中,多个集群节点中竞争Job锁,只会有一台执行 -->
<bean id="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <bean id="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" /> <property name="dataSource" ref="dataSource" />
<property name="autoStartup" value="true" /> <property name="autoStartup" value="true" />
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" /> <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="configLocation" value="classpath:quartz.properties"/> <property name="configLocation" value="classpath:quartz.properties"/>
<property name="triggers">
<list>
<!-- <ref bean="job02Trigger" /> -->
</list>
</property>
</bean> </bean>
<!-- 调度器 --> <!-- 协同-调度器 -->
<bean id="dynamicSchedulerUtil" class="com.xxl.quartz.DynamicSchedulerUtil"> <bean id="dynamicSchedulerUtil" class="com.xxl.job.core.util.DynamicSchedulerUtil">
<!-- (轻易不要变更“调度器名称”, 任务创建时会绑定该“调度器名称”) -->
<property name="scheduler" ref="quartzScheduler"/> <property name="scheduler" ref="quartzScheduler"/>
</bean> </bean>
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
<property name="cronExpression" value="0/10 * * * * ? *" /> <property name="cronExpression" value="0/10 * * * * ? *" />
</bean> </bean>
<!-- Job被加载到内存中,每个集群节点相互独立,都会执行该任务 --> <!-- 进程-调度器 -->
<bean name="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <bean name="jvmQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers"> <property name="triggers">
<list> <list>
<ref bean="beatTrigger" /> <!-- <ref bean="beatTrigger" /> -->
</list> </list>
</property> </property>
</bean> </bean>
......
...@@ -12,15 +12,12 @@ ...@@ -12,15 +12,12 @@
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-3.0.xsd">
<!-- 事务管理器(声明式事务) -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" /> <property name="dataSource" ref="dataSource" />
</bean> </bean>
<!-- 启动事务注解(方式1:注解方式) -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!-- 事务通知(方式2:XML事务管理) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes> <tx:attributes>
<tx:method name="detail*" propagation="SUPPORTS" /> <tx:method name="detail*" propagation="SUPPORTS" />
...@@ -33,11 +30,8 @@ ...@@ -33,11 +30,8 @@
</tx:attributes> </tx:attributes>
</tx:advice> </tx:advice>
<!-- AOP配置 -->
<aop:config> <aop:config>
<!-- 定义一个切入点 -->
<aop:pointcut id="txoperation" expression="execution(* com.xxl.service.imp.*.*(..))" /> <aop:pointcut id="txoperation" expression="execution(* com.xxl.service.imp.*.*(..))" />
<!-- 切入点事务通知 -->
<aop:advisor pointcut-ref="txoperation" advice-ref="txAdvice" /> <aop:advisor pointcut-ref="txoperation" advice-ref="txAdvice" />
</aop:config> </aop:config>
......
# 静态文件地址
static_url=https://www.baidu.com/
\ No newline at end of file
log4j.rootLogger=info,console log4j.rootLogger=info,console,logFile
log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d - xxl-job-demo - %p [%c] - <%m>%n log4j.appender.console.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n
log4j.appender.logFile=org.apache.log4j.DailyRollingFileAppender log4j.appender.logFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logFile.File=${catalina.base}/logs/xxl-job-demo.log log4j.appender.logFile.File=${catalina.base}/logs/xxl-job-admin.log
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=%d - xxl-job-demo - %p [%c] - <%m>%n log4j.appender.logFile.layout.ConversionPattern=%d - xxl-job-admin - %p [%c] - <%m>%n
...@@ -18,6 +18,7 @@ org.quartz.jobStore.misfireThreshold: 60000 ...@@ -18,6 +18,7 @@ org.quartz.jobStore.misfireThreshold: 60000
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore #org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
# for cluster # for cluster
#org.quartz.jobStore.tablePrefix = WED_qrtz_
org.quartz.scheduler.instanceId: AUTO org.quartz.scheduler.instanceId: AUTO
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered: true org.quartz.jobStore.isClustered: true
......
...@@ -18,34 +18,35 @@ ...@@ -18,34 +18,35 @@
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-3.0.xsd">
<description>Spring-web MVC配置</description>
<mvc:annotation-driven /> <mvc:annotation-driven />
<context:component-scan base-package="com.xxl.controller" /> <context:component-scan base-package="com.xxl.job.controller" />
<mvc:resources mapping="/favicon.ico" location="/favicon.ico" /> <mvc:resources mapping="/favicon.ico" location="/favicon.ico" />
<mvc:resources mapping="/static/**" location="/static/" /> <!-- 不拦截static目录下 --> <mvc:resources mapping="/static/**" location="/static/" />
<mvc:resources mapping="/**/*.html" location="/" /> <!-- 不拦截.html后缀 --> <mvc:resources mapping="/**/*.html" location="/" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" /> <!-- 解析视图模板类 --> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
<property name="prefix" value="" /> <!-- 模板前后缀,指定html页面为模板 --> <property name="prefix" value="" />
<property name="suffix" value=".ftl" /> <property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=UTF-8" /> <!-- 模板输出内容编码 (此处应与defaultEncoding保持一致) --> <property name="contentType" value="text/html;charset=UTF-8" />
<property name="exposeSpringMacroHelpers" value="true" /> <!-- 访问Request/Session宏助手 --> <property name="exposeSpringMacroHelpers" value="true" />
<property name="exposeRequestAttributes" value="true" /> <!-- 允许访问Request属性,默认为false --> <property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" /> <!-- 允许访问Session属性,默认为false --> <property name="exposeSessionAttributes" value="true" />
<property name="requestContextAttribute" value="request" /> <!-- 将HttpServletRequest的属性存放到request这个变量中 --> <property name="requestContextAttribute" value="request" />
<property name="cache" value="true" /> <property name="cache" value="true" />
<property name="order" value="0" /> <property name="order" value="0" />
</bean> </bean>
<!-- <mvc:interceptors> <!--
// 自定义拦截器,支持SSO登陆拦截
<mvc:interceptors>
<mvc:interceptor> <mvc:interceptor>
<mvc:mapping path="/**"/> <mvc:mapping path="/**"/>
<bean class="com.xxl.controller.interceptor.PermissionInterceptor"/> <bean class="com.xxl.controller.interceptor.PermissionInterceptor"/>
</mvc:interceptor> </mvc:interceptor>
</mvc:interceptors> </mvc:interceptors>
<bean id="exceptionResolver" class="com.xxl.controller.resolver.WebExceptionResolver" /> --> <bean id="exceptionResolver" class="com.xxl.controller.resolver.WebExceptionResolver" />
-->
</beans> </beans>
\ No newline at end of file
...@@ -37,8 +37,6 @@ ...@@ -37,8 +37,6 @@
<script src="${request.contextPath}/static/adminlte/plugins/fastclick/fastclick.js"></script> <script src="${request.contextPath}/static/adminlte/plugins/fastclick/fastclick.js"></script>
<!-- AdminLTE App --> <!-- AdminLTE App -->
<script src="${request.contextPath}/static/adminlte/dist/js/app.min.js"></script> <script src="${request.contextPath}/static/adminlte/dist/js/app.min.js"></script>
<!-- SlimScroll 1.3.0 -->
<script src="${request.contextPath}/static/adminlte/plugins/slimScroll/jquery.slimscroll.min.js"></script>
<!-- scrollup --> <!-- scrollup -->
<script src="${request.contextPath}/static/plugins/scrollup/jquery.scrollUp.min.js"></script> <script src="${request.contextPath}/static/plugins/scrollup/jquery.scrollUp.min.js"></script>
...@@ -47,71 +45,15 @@ ...@@ -47,71 +45,15 @@
<#macro commonHeader> <#macro commonHeader>
<header class="main-header"> <header class="main-header">
<a href="${request.contextPath}/" class="logo">
<!-- Logo --> <span class="logo-mini"><b>X</b>XL</span>
<a href="${request.contextPath}/" class="logo"> <!-- mini logo for sidebar mini 50x50 pixels --> <span class="logo-lg"><b>任务调度</b>中心</span>
<span class="logo-mini"><b>X</b>XL</span> <!-- logo for regular state and mobile devices -->
<span class="logo-lg"><b>调度</b>中心</span>
</a> </a>
<!-- Header Navbar: style can be found in header.less -->
<nav class="navbar navbar-static-top" role="navigation"> <nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button-->
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"><span class="sr-only">切换导航</span></a> <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button"><span class="sr-only">切换导航</span></a>
<div class="navbar-custom-menu"></div>
<#--
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-bell-o"></i> <span class="label label-warning">5</span></a>
<ul class="dropdown-menu">
<li class="header">您有5条通知</li>
<li>
<ul class="menu">
<li><a href="#"> <i class="fa fa-warning text-yellow"></i>
这是一个不错的应用
</a></li>
<li><a href="#"> <i class="fa fa-warning text-yellow"></i>
这是一个很不错的应用
</a></li>
<li><a href="#"> <i class="fa fa-warning text-yellow"></i>
这是一个非常不错的应用
</a></li>
<li><a href="#"> <i class="fa fa-warning text-yellow"></i>
这是一个非常非常不错的应用
</a></li>
<li><a href="#"> <i class="fa fa-warning text-yellow"></i>
这是一个非常非常非常不错的应用
</a></li>
</ul>
</li>
<li class="footer"><a href="#">查看全部</a></li>
</ul>
</li>
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-user text-aqua"></i><span class="hidden-xs">${loginIdentity.userName}</span>
</a>
<ul class="dropdown-menu">
<li class="user-header">
<p>
${loginIdentity.realName} - 前端研发
<small>注册于 2012-11-20</small>
</p>
</li>
<li class="user-footer">
<div class="pull-left"><a href="#" class="btn btn-default btn-flat">资料</a></div>
<div class="pull-right"><a href="javascript:;" class="btn btn-default btn-flat" id="logoutBtn" >注销</a></div>
</li>
</ul></li>
<li><a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a></li>
</ul>
</div>
-->
</nav> </nav>
</header> </header>
</#macro> </#macro>
<#macro commonLeft> <#macro commonLeft>
...@@ -121,22 +63,9 @@ ...@@ -121,22 +63,9 @@
<section class="sidebar"> <section class="sidebar">
<!-- sidebar menu: : style can be found in sidebar.less --> <!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu"> <ul class="sidebar-menu">
<li class="header">常用模块</li> <li class="header">常用模块</li>
<li class="nav-click" ><a href="${request.contextPath}//"><i class="fa fa-circle-o text-red"></i> <span>调度管理</span></a></li> <li class="nav-click" ><a href="${request.contextPath}//"><i class="fa fa-circle-o text-red"></i> <span>调度中心</span></a></li>
<li class="nav-click" ><a href="${request.contextPath}/help"><i class="fa fa-circle-o text-yellow"></i><span>使用教程</span></a></li> <li class="nav-click" ><a href="${request.contextPath}/help"><i class="fa fa-circle-o text-yellow"></i><span>使用教程</span></a></li>
<#--
<li class="header">全部模块</li>
<li class="treeview nav-click">
<a href="#"><i class="fa fa-dashboard"></i> <span>调度中心</span><i class="fa fa-angle-left pull-right"></i></a>
<ul class="treeview-menu">
<li class="nav-click" ><a href="${request.contextPath}/job/index"><i class="fa fa-circle-o"></i>调度管理</a></li>
<li class="nav-click" ><a href="${request.contextPath}/job/help"><i class="fa fa-circle-o"></i>使用教程</a></li>
</ul>
</li>
-->
</ul> </ul>
</section> </section>
<!-- /.sidebar --> <!-- /.sidebar -->
...@@ -226,8 +155,8 @@ ...@@ -226,8 +155,8 @@
<b>Version</b> 1.0 <b>Version</b> 1.0
</div> </div>
<strong>Copyright &copy; 2015-2015 &nbsp; <strong>Copyright &copy; 2015-2015 &nbsp;
<a href="https://github.com/xuxueli/" target="_blank" >github</a>&nbsp; <a href="https://github.com/xuxueli/xxl-job" target="_blank" >github</a>&nbsp;
<a href="http://www.cnblogs.com/xuxueli/" target="_blank" >cnblog</a>. <a href="http://www.cnblogs.com/xuxueli/p/5021979.html" target="_blank" >cnblog</a>.
</strong> All rights reserved. </strong> All rights reserved.
</footer> </footer>
</#macro> </#macro>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>AdminLTE 2 | Dashboard</title> <title>调度中心</title>
<#import "/common/common.macro.ftl" as netCommon> <#import "/common/common.macro.ftl" as netCommon>
<@netCommon.commonStyle /> <@netCommon.commonStyle />
</head> </head>
...@@ -26,18 +26,41 @@ ...@@ -26,18 +26,41 @@
<!-- Main content --> <!-- Main content -->
<section class="content"> <section class="content">
<div class="callout callout-info"> <div class="callout callout-info">
<h4>简介:xxl-job</h4> <h4>简介:XXL_JOB</h4>
<p>调度管理平台:基于quartz封装实现的的集群任务调度管理平台.</p> <p>基于quartz封装实现的的集群任务调度管理平台.</p>
<p></p> <p></p>
</div> </div>
<div class="callout callout-default">
<div class="callout callout-info">
<h4>特点:</h4> <h4>特点:</h4>
<p>1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手.</p> <p>1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手.</p>
<p>2、动态:支持动态修改任务状态,动态暂停/恢复任务,即时生效.</p> <p>2、动态:支持动态修改任务状态,动态暂停/恢复任务,即时生效.</p>
<p>3、集群:任务信息持久化到mysql中,支持Job服务器集群(高可用),一个任务只会在其中一台服务器上执行.</p> <p>3、集群:任务信息持久化到mysql中,支持Job服务器集群(高可用),一个任务只会在其中一台服务器上执行.</p>
</div> </div>
<div class="callout callout-default">
<h4>分层模型:</h4>
<p>1、基础:基于quartz封装底层调度层,通过CORN自定义任务执行周期,最终执行自定义JobBean的execute方法,如需多个任务,需要开发多个JobBean实现.</p>
<p>2、分层:上述基础调度模型存在一定局限,调度层和任务层耦合,当新任务上线势必影响任务的正常调度,因此规划将调度系统分层为:调度层 + 任务层 + 通讯层.</p>
<p>
<div class="row">
<div class="col-xs-offset-1 col-xs-11">
<p>》调度模块:维护任务的调度信息,负责定时/周期性的发出调度请求.</p>
<p>》任务模块:具体的任务逻辑,负责接收调度模块的调度请求,执行任务逻辑.</p>
<p>》通讯模块:负责调度模块和任务模块之间的通讯.</p>
<p>(总而言之,一条完整任务由 “调度信息” 和 “任务信息” 组成.)</p>
</div>
</div>
</p>
</div>
<div class="callout callout-default">
<h4>调度属性解析 : 发出HTTP调度请求</h4>
<p>1、调度Key【必填】:调度信息的全局唯一标识.</p>
<p>2、调度Corn【必填】:调度执行的时间表达式.</p>
<p>3、调度描述【必填】:调度的简述.</p>
<p>4、调度URL【必填】:调度执行时发出HTTP请求的目标URL地址.</p>
<p>5、+args【选填】:调度执行时发出HTTP请求的附带的POST参数.</p>
</div>
</section> </section>
<!-- /.content --> <!-- /.content -->
</div> </div>
......
...@@ -19,10 +19,10 @@ ...@@ -19,10 +19,10 @@
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Content Header (Page header) --> <!-- Content Header (Page header) -->
<section class="content-header"> <section class="content-header">
<h1>使用教程<small>调度管理平台</small></h1> <h1>调度中心<small>调度管理</small></h1>
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a><i class="fa fa-dashboard"></i>调度中心</a></li> <li><a><i class="fa fa-dashboard"></i>调度中心</a></li>
<li class="active">使用教程</li> <li class="active">调度管理</li>
</ol> </ol>
</section> </section>
...@@ -32,17 +32,17 @@ ...@@ -32,17 +32,17 @@
<div class="col-xs-12"> <div class="col-xs-12">
<div class="box"> <div class="box">
<div class="box-header"> <div class="box-header">
<h3 class="box-title">任务列表</h3> <h3 class="box-title">调度列表</h3>
<button class="btn btn-primary btn-xs add" type="button">新增</button> <button class="btn btn-info btn-xs add" type="button">+新增任务</button>
</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">
<thead> <thead>
<tr> <tr>
<th>任务ID</th> <th>调度key</th>
<th>cron</th> <th>cron</th>
<th>Job类路径</th> <!--<th>类路径</th>-->
<th>简介</th> <th>参数</th>
<th>状态</th> <th>状态</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
...@@ -53,11 +53,13 @@ ...@@ -53,11 +53,13 @@
<tr> <tr>
<td>${item['TriggerKey'].name}</td> <td>${item['TriggerKey'].name}</td>
<td>${item['Trigger'].cronExpression}</td> <td>${item['Trigger'].cronExpression}</td>
<td>${item['JobDetail'].jobClass}</td> <!--<td>${item['JobDetail'].jobClass}</td>-->
<td> <td>
<#if item['JobDetail'].jobDataMap?exists> <#assign jobDataMap = item['JobDetail'].jobDataMap />
<#assign job_desc=item['JobDetail'].jobDataMap['job_desc'] /> <#if jobDataMap?exists && jobDataMap?keys?size gt 0>
${job_desc} <#list jobDataMap?keys as key>
${key} = ${jobDataMap[key]} <br>
</#list>
</#if> </#if>
</td> </td>
<td state="${item['TriggerState']}" > <td state="${item['TriggerState']}" >
...@@ -77,8 +79,9 @@ ...@@ -77,8 +79,9 @@
<#elseif item['TriggerState'] == 'PAUSED'> <#elseif item['TriggerState'] == 'PAUSED'>
<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button> <button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>
</#if> </#if>
<button class="btn btn-info btn-xs update" type="button">修改</button> <button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行一次</button>
<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> <button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>
<button class="btn btn-info btn-xs update" type="button">更新corn</button>
</p> </p>
</td> </td>
</tr> </tr>
...@@ -87,10 +90,10 @@ ...@@ -87,10 +90,10 @@
</tbody> </tbody>
<tfoot> <tfoot>
<tr> <tr>
<th>任务ID</th> <th>调度key</th>
<th>cron</th> <th>cron</th>
<th>Job类路径</th> <!--<th>类路径</th>-->
<th>简介</th> <th>参数</th>
<th>状态</th> <th>状态</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
...@@ -114,30 +117,39 @@ ...@@ -114,30 +117,39 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" >新增调度任务</h4> <h4 class="modal-title" >新增调度信息</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal form" role="form" > <form class="form-horizontal form" role="form" >
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">任务Key</label> <label for="firstname" class="col-sm-3 control-label">任务Key</label>
<div class="col-sm-10"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" ></div> <div class="col-sm-9"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">任务Corn</label> <label for="lastname" class="col-sm-3 control-label">任务Corn</label>
<div class="col-sm-10"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn[允许修改]" maxlength="100" ></div> <div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn[允许修改]" maxlength="100" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">任务Impl</label> <label for="lastname" class="col-sm-3 control-label">任务描述</label>
<div class="col-sm-10"><input type="text" class="form-control" name="jobClassName" placeholder="请输入任务Impl[不支持修改]" maxlength="100" ></div> <div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述[不支持修改]" maxlength="200" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">任务描述</label> <label for="lastname" class="col-sm-3 control-label">任务JobBean</label>
<div class="col-sm-10"><input type="text" class="form-control" name="jobDesc" placeholder="请输入任务描述[不支持修改]" maxlength="200" ></div> <div class="col-sm-9">
<select name="job_bean" >
<#if jobBeanMap?exists && jobBeanMap?size gt 0>
<#list jobBeanMap?keys as key>
<option value ="${key}" <#if key_index == 0>selected="selected"</#if> >${jobBeanMap[key]}[${key}]</option>
</#list>
</#if>
</select>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <div class="col-sm-offset-3 col-sm-9">
<button type="submit" class="btn btn-primary" >保存</button> <button type="submit" class="btn btn-primary" >保存</button>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-info pull-right addParam">+ arg</button>
</div> </div>
</div> </div>
</form> </form>
...@@ -151,7 +163,7 @@ ...@@ -151,7 +163,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title" >更新配置</h4> <h4 class="modal-title" >更新corn</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal form" role="form" > <form class="form-horizontal form" role="form" >
...@@ -163,14 +175,6 @@ ...@@ -163,14 +175,6 @@
<label for="lastname" class="col-sm-2 control-label">任务Corn</label> <label for="lastname" class="col-sm-2 control-label">任务Corn</label>
<div class="col-sm-10"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div> <div class="col-sm-10"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
</div> </div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">任务Impl</label>
<div class="col-sm-10"><input type="text" class="form-control" name="jobClassName" placeholder="请输入任务Impl" maxlength="100" readonly ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">任务描述</label>
<div class="col-sm-10"><input type="text" class="form-control" name="jobDesc" placeholder="请输入任务描述" maxlength="200" readonly ></div>
</div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" >保存</button> <button type="submit" class="btn btn-primary" >保存</button>
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
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-admin</display-name> <display-name>xxl-job-admin</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>xxl-job-admin</param-value>
</context-param>
<context-param> <context-param>
<param-name>contextConfigLocation</param-name> <param-name>contextConfigLocation</param-name>
......
*.DS_Store
*.log
*.zip
.idea
/nbproject/
/nbproject/private/
/node_modules/
ad.js
TODO
test.html
{
"asi" : true,
"browser" : true,
"eqeqeq" : false,
"eqnull" : true,
"es3" : true,
"expr" : true,
"jquery" : true,
"latedef" : "nofunc",
"laxbreak" : true,
"nonbsp" : true,
"strict" : true,
"undef" : true,
"unused" : true,
// External variabls and plugins
"predef": [ "AdminLTEOptions", "FastClick", "moment", "Morris", "Chart" ]
}
# AutoFill
AutoFill gives an Excel like option to a DataTable to click and drag over multiple cells, filling in information over the selected cells and incrementing numbers as needed. Key features include:
* Click and drag cell content insertion
* Automatic incrementing of numeric information
* Enable and disable on any column
* Detailed callback functions for customisation
* Support for both DataTables and browser window scrolling
# Installation
To use AutoFill, first download DataTables ( http://datatables.net/download ) and place the unzipped AutoFill package into a `extensions` directory in the DataTables package. This will allow the pages in the examples to operate correctly. To see the examples running, open the `examples` directory in your web-browser.
# Basic usage
AutoFill is initialised using the `$.fn.dataTable.AutoFill` constructor. For example:
```js
$(document).ready( function () {
var table = $('#example').dataTable();
new $.fn.dataTable.AutoFill( table );
} );
```
# Documentation / support
* Documentation: http://datatables.net/extensions/autofill/
* DataTables support forums: http://datatables.net/forums
# GitHub
If you fancy getting involved with the development of AutoFill and help make it better, please refer to its GitHub repo: https://github.com/DataTables/AutoFill
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* AutoFill styles
*/
div.AutoFill_filler {
display: none;
position: absolute;
height: 14px;
width: 14px;
background: url(../images/filler.png) no-repeat center center;
z-index: 1002;
}
div.AutoFill_border {
display: none;
position: absolute;
background-color: #0063dc;
z-index: 1001;
box-shadow: 0px 0px 5px #76b4ff;
-moz-box-shadow: 0px 0px 5px #76b4ff;
-webkit-box-shadow: 0px 0px 5px #76b4ff;
}
div.AutoFill_filler{display:none;position:absolute;height:14px;width:14px;background:url(../images/filler.png) no-repeat center center;z-index:1002}div.AutoFill_border{display:none;position:absolute;background-color:#0063dc;z-index:1001;box-shadow:0px 0px 5px #76b4ff;-moz-box-shadow:0px 0px 5px #76b4ff;-webkit-box-shadow:0px 0px 5px #76b4ff}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/ico" href="http://www.datatables.net/favicon.ico">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/syntax/shCore.css">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/demo.css">
<script type="text/javascript" language="javascript" src="../../../media/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/syntax/shCore.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/demo.js"></script>
<title>AutoFill examples - AutoFill examples</title>
</head>
<body class="dt-example">
<div class="container">
<section>
<h1>AutoFill example <span>AutoFill examples</span></h1>
<div class="info">
<p>AutoFill gives an Excel like option to a DataTable to click and drag over multiple cells, filling in
information over the selected cells and incrementing numbers as needed.</p>
<p>Thanks to <a href="http://www.phoniax.no/">Phoniax AS</a> for their sponsorship of this plug-in for
DataTables.</p>
</div>
</section>
</div>
<section>
<div class="footer">
<div class="gradient"></div>
<div class="liner">
<div class="toc">
<div class="toc-group">
<h3><a href="./index.html">Examples</a></h3>
<ul class="toc">
<li><a href="./simple.html">Basic initialisation</a></li>
<li><a href="./columns.html">Column options</a></li>
<li><a href="./scrolling.html">Scrolling DataTable</a></li>
<li><a href="./fill-both.html">Horizontal and vertical fill</a></li>
<li><a href="./fill-horizontal.html">Horizontal fill</a></li>
<li><a href="./complete-callback.html">Complete callback</a></li>
<li><a href="./step-callback.html">Step callback</a></li>
</ul>
</div>
</div>
<div class="epilogue">
<p>Please refer to the <a href="http://www.datatables.net">DataTables documentation</a> for full
information about its API properties and methods.<br>
Additionally, there are a wide range of <a href="http://www.datatables.net/extras">extras</a> and
<a href="http://www.datatables.net/plug-ins">plug-ins</a> which extend the capabilities of
DataTables.</p>
<p class="copyright">DataTables designed and created by <a href=
"http://www.sprymedia.co.uk">SpryMedia Ltd</a> &#169; 2007-2014<br>
DataTables is licensed under the <a href="http://www.datatables.net/mit">MIT license</a>.</p>
</div>
</div>
</div>
</section>
</body>
</html>
\ No newline at end of file
/*!
AutoFill 1.2.1
©2008-2014 SpryMedia Ltd - datatables.net/license
*/
(function(o,j,m){var l=function(c,k){var h=function(d,b){if(!(this instanceof h))throw"Warning: AutoFill must be initialised with the keyword 'new'";if(!c.fn.dataTableExt.fnVersionCheck("1.7.0"))throw"Warning: AutoFill requires DataTables 1.7 or greater";this.c={};this.s={filler:{height:0,width:0},border:{width:2},drag:{startX:-1,startY:-1,startTd:null,endTd:null,dragging:!1},screen:{interval:null,y:0,height:0,scrollTop:0},scroller:{top:0,bottom:0},columns:[]};this.dom={table:null,filler:null,borderTop:null,
borderRight:null,borderBottom:null,borderLeft:null,currentTarget:null};this.fnSettings=function(){return this.s};this._fnInit(d,b);return this};h.prototype={_fnInit:function(d,b){var a=this;this.s.dt=k.Api?(new k.Api(d)).settings()[0]:d.fnSettings();this.s.init=b||{};this.dom.table=this.s.dt.nTable;c.extend(!0,this.c,h.defaults,b);this._initColumns();var e=c("<div/>",{"class":"AutoFill_filler"}).appendTo("body");this.dom.filler=e[0];this.s.filler.height=e.height();this.s.filler.width=e.width();e[0].style.display=
"none";var g,f=j.body;""!==a.s.dt.oScroll.sY&&(a.s.dt.nTable.parentNode.style.position="relative",f=a.s.dt.nTable.parentNode);g=c("<div/>",{"class":"AutoFill_border"});this.dom.borderTop=g.clone().appendTo(f)[0];this.dom.borderRight=g.clone().appendTo(f)[0];this.dom.borderBottom=g.clone().appendTo(f)[0];this.dom.borderLeft=g.clone().appendTo(f)[0];e.on("mousedown.DTAF",function(b){this.onselectstart=function(){return false};a._fnFillerDragStart.call(a,b);return false});c("tbody",this.dom.table).on("mouseover.DTAF mouseout.DTAF",
">tr>td, >tr>th",function(b){a._fnFillerDisplay.call(a,b)});c(this.dom.table).on("destroy.dt.DTAF",function(){e.off("mousedown.DTAF").remove();c("tbody",this.dom.table).off("mouseover.DTAF mouseout.DTAF")})},_initColumns:function(){var d=this,b,a,e=this.s.dt,g=this.s.init;b=0;for(a=e.aoColumns.length;b<a;b++)this.s.columns[b]=c.extend(!0,{},h.defaults.column);e.oApi._fnApplyColumnDefs(e,g.aoColumnDefs||g.columnDefs,g.aoColumns||g.columns,function(a,b){d._fnColumnOptions(a,b)});b=0;for(a=e.aoColumns.length;b<
a;b++)if(e=this.s.columns[b],e.read||(e.read=this._fnReadCell),e.write||(e.read=this._fnWriteCell),!e.step)e.read=this._fnStep},_fnColumnOptions:function(d,b){var a=this.s.columns[d],c=function(c,d){b[d[0]]!==m&&(a[c]=b[d[0]]);b[d[1]]!==m&&(a[c]=b[d[1]])};c("enable",["bEnable","enable"]);c("read",["fnRead","read"]);c("write",["fnWrite","write"]);c("step",["fnStep","step"]);c("increment",["bIncrement","increment"])},_fnTargetCoords:function(d){var b=c(d).parents("tr")[0],a=this.s.dt.oInstance.fnGetPosition(d);
return{x:c("td",b).index(d),y:c("tr",b.parentNode).index(b),row:a[0],column:a[2]}},_fnUpdateBorder:function(d,b){var a=this.s.border.width,e=c(d).offset(),g=c(b).offset(),f=e.left-a,i=g.left+c(b).outerWidth(),n=e.top-a,h=g.top+c(b).outerHeight(),j=g.left+c(b).outerWidth()-e.left+2*a,k=g.top+c(b).outerHeight()-e.top+2*a;e.left>g.left&&(f=g.left-a,i=e.left+c(d).outerWidth(),j=e.left+c(d).outerWidth()-g.left+2*a);""!==this.s.dt.oScroll.sY&&(a=c(this.s.dt.nTable.parentNode).offset(),e=c(this.s.dt.nTable.parentNode).scrollTop(),
g=c(this.s.dt.nTable.parentNode).scrollLeft(),f-=a.left-g,i-=a.left-g,n-=a.top-e,h-=a.top-e);a=this.dom.borderTop.style;a.top=n+"px";a.left=f+"px";a.height=this.s.border.width+"px";a.width=j+"px";a=this.dom.borderBottom.style;a.top=h+"px";a.left=f+"px";a.height=this.s.border.width+"px";a.width=j+"px";a=this.dom.borderLeft.style;a.top=n+"px";a.left=f+"px";a.height=k+"px";a.width=this.s.border.width+"px";a=this.dom.borderRight.style;a.top=n+"px";a.left=i+"px";a.height=k+"px";a.width=this.s.border.width+
"px"},_fnFillerDragStart:function(d){var b=this,a=this.dom.currentTarget;this.s.drag.dragging=!0;b.dom.borderTop.style.display="block";b.dom.borderRight.style.display="block";b.dom.borderBottom.style.display="block";b.dom.borderLeft.style.display="block";var e=this._fnTargetCoords(a);this.s.drag.startX=e.x;this.s.drag.startY=e.y;this.s.drag.startTd=a;this.s.drag.endTd=a;this._fnUpdateBorder(a,a);c(j).bind("mousemove.AutoFill",function(a){b._fnFillerDragMove.call(b,a)});c(j).bind("mouseup.AutoFill",
function(a){b._fnFillerFinish.call(b,a)});this.s.screen.y=d.pageY;this.s.screen.height=c(o).height();this.s.screen.scrollTop=c(j).scrollTop();""!==this.s.dt.oScroll.sY&&(this.s.scroller.top=c(this.s.dt.nTable.parentNode).offset().top,this.s.scroller.bottom=this.s.scroller.top+c(this.s.dt.nTable.parentNode).height());this.s.screen.interval=setInterval(function(){var a=c(j).scrollTop();b.s.screen.y=b.s.screen.y+(a-b.s.screen.scrollTop);b.s.screen.height-b.s.screen.y+a<50?c("html, body").animate({scrollTop:a+
50},240,"linear"):b.s.screen.y-a<50&&c("html, body").animate({scrollTop:a-50},240,"linear");b.s.dt.oScroll.sY!==""&&(b.s.screen.y>b.s.scroller.bottom-50?c(b.s.dt.nTable.parentNode).animate({scrollTop:c(b.s.dt.nTable.parentNode).scrollTop()+50},240,"linear"):b.s.screen.y<b.s.scroller.top+50&&c(b.s.dt.nTable.parentNode).animate({scrollTop:c(b.s.dt.nTable.parentNode).scrollTop()-50},240,"linear"))},250)},_fnFillerDragMove:function(d){if(d.target&&"TD"==d.target.nodeName.toUpperCase()&&d.target!=this.s.drag.endTd){var b=
this._fnTargetCoords(d.target);"y"==this.c.mode&&b.x!=this.s.drag.startX&&(d.target=c("tbody>tr:eq("+b.y+")>td:eq("+this.s.drag.startX+")",this.dom.table)[0]);"x"==this.c.mode&&b.y!=this.s.drag.startY&&(d.target=c("tbody>tr:eq("+this.s.drag.startY+")>td:eq("+b.x+")",this.dom.table)[0]);"either"==this.c.mode&&(b.x!=this.s.drag.startX?d.target=c("tbody>tr:eq("+this.s.drag.startY+")>td:eq("+b.x+")",this.dom.table)[0]:b.y!=this.s.drag.startY&&(d.target=c("tbody>tr:eq("+b.y+")>td:eq("+this.s.drag.startX+
")",this.dom.table)[0]));"both"!==this.c.mode&&(b=this._fnTargetCoords(d.target));var a=this.s.drag;a.endTd=d.target;b.y>=this.s.drag.startY?this._fnUpdateBorder(a.startTd,a.endTd):this._fnUpdateBorder(a.endTd,a.startTd);this._fnFillerPosition(d.target)}this.s.screen.y=d.pageY;this.s.screen.scrollTop=c(j).scrollTop();""!==this.s.dt.oScroll.sY&&(this.s.scroller.scrollTop=c(this.s.dt.nTable.parentNode).scrollTop(),this.s.scroller.top=c(this.s.dt.nTable.parentNode).offset().top,this.s.scroller.bottom=
this.s.scroller.top+c(this.s.dt.nTable.parentNode).height())},_fnFillerFinish:function(){var d=this,b,a;c(j).unbind("mousemove.AutoFill mouseup.AutoFill");this.dom.borderTop.style.display="none";this.dom.borderRight.style.display="none";this.dom.borderBottom.style.display="none";this.dom.borderLeft.style.display="none";this.s.drag.dragging=!1;clearInterval(this.s.screen.interval);var e=[],g=this.dom.table,f=this._fnTargetCoords(this.s.drag.startTd),i=this._fnTargetCoords(this.s.drag.endTd),h=function(a){return d.s.dt.oApi._fnVisibleToColumnIndex(d.s.dt,
a)};if(f.y<=i.y)for(b=f.y;b<=i.y;b++)if(f.x<=i.x)for(a=f.x;a<=i.x;a++)e.push({node:c("tbody>tr:eq("+b+")>td:eq("+a+")",g)[0],x:a-f.x,y:b-f.y,colIdx:h(a)});else for(a=f.x;a>=i.x;a--)e.push({node:c("tbody>tr:eq("+b+")>td:eq("+a+")",g)[0],x:a-f.x,y:b-f.y,colIdx:h(a)});else for(b=f.y;b>=i.y;b--)if(f.x<=i.x)for(a=f.x;a<=i.x;a++)e.push({node:c("tbody>tr:eq("+b+")>td:eq("+a+")",g)[0],x:a-f.x,y:b-f.y,colIdx:h(a)});else for(a=f.x;a>=i.x;a--)e.push({node:c("tbody>tr:eq("+b+")>td:eq("+a+")",g)[0],x:f.x-a,y:f.y-
b,colIdx:h(a)});if(!(1>=e.length)){var g=[],m;b=0;for(a=e.length;b<a;b++){var f=e[b],i=this.s.columns[f.colIdx],h=i.read.call(i,f.node),l=i.step.call(i,f.node,h,m,b,f.x,f.y);i.write.call(i,f.node,l);m=l;g.push({cell:f,colIdx:f.colIdx,newValue:l,oldValue:h})}null!==this.c.complete&&this.c.complete.call(this,g);k.Api?(new k.Api(this.s.dt)).draw(!1):this.s.dt.oInstance.fnDraw()}},_fnFillerDisplay:function(d){var b=this.dom.filler;if(!this.s.drag.dragging){var a="td"==d.target.nodeName.toLowerCase()?
d.target:c(d.target).parents("td")[0],e=this._fnTargetCoords(a).column;if(this.s.columns[e].enable)if("mouseover"==d.type)this.dom.currentTarget=a,this._fnFillerPosition(a),b.style.display="block";else{if(!d.relatedTarget||!d.relatedTarget.className.match(/AutoFill/))b.style.display="none"}else b.style.display="none"}},_fnFillerPosition:function(d){var b=c(d).offset(),a=this.dom.filler;a.style.top=b.top-this.s.filler.height/2-1+c(d).outerHeight()+"px";a.style.left=b.left-this.s.filler.width/2-1+c(d).outerWidth()+
"px"}};k.AutoFill=h;k.AutoFill=h;h.version="1.2.1";h.defaults={mode:"y",complete:null,column:{enable:!0,increment:!0,read:function(d){return c(d).html()},write:function(d,b){var a=c(d).parents("table");if(k.Api)a.DataTable().cell(d).data(b);else{var a=a.dataTable(),e=a.fnGetPosition(d);a.fnUpdate(b,e[0],e[2],!1)}},step:function(c,b,a,e,g,f){c=/(\-?\d+)/;return(e=this.increment&&a?a.match(c):null)?a.replace(c,parseInt(e[1],10)+(0>g||0>f?-1:1)):a===m?b:a}}};return h};"function"===typeof define&&define.amd?
define(["jquery","datatables"],l):"object"===typeof exports?l(require("jquery"),require("datatables")):jQuery&&!jQuery.fn.dataTable.AutoFill&&l(jQuery,jQuery.fn.dataTable)})(window,document);
Copyright (c) 2010-2015 SpryMedia Limited
http://datatables.net
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# ColReorder
ColReorder adds the ability for the end user to click and drag column headers to reorder a table as they see fit, to DataTables. Key features include:
* Very easy integration with DataTables
* Tight integration with all other DataTables plug-ins
* The ability to exclude the first (or more) column from being movable
* Predefine a column order
* Save staving integration with DataTables
# Installation
To use ColReorder, first download DataTables ( http://datatables.net/download ) and place the unzipped ColReorder package into a `extensions` directory in the DataTables package. This will allow the pages in the examples to operate correctly. To see the examples running, open the `examples` directory in your web-browser.
# Basic usage
ColReorder is initialised using the `$.fn.dataTable.ColReorder` constructor. For example:
```js
$(document).ready( function () {
$('#example').DataTable();
new $.fn.dataTable.ColReorder( table );
} );
```
# Documentation / support
* Documentation: http://datatables.net/extensions/colreorder/
* DataTables support forums: http://datatables.net/forums
# GitHub
If you fancy getting involved with the development of ColReorder and help make it better, please refer to its GitHub repo: https://github.com/DataTables/ColReorder
/*
* Namespace DTCR - "DataTables ColReorder" plug-in
*/
table.DTCR_clonedTable {
background-color: rgba(255, 255, 255, 0.7);
z-index: 202;
}
div.DTCR_pointer {
width: 1px;
background-color: #0259C4;
z-index: 201;
}
\ No newline at end of file
table.DTCR_clonedTable{background-color:rgba(255,255,255,0.7);z-index:202}div.DTCR_pointer{width:1px;background-color:#0259C4;z-index:201}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/ico" href="http://www.datatables.net/favicon.ico">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/syntax/shCore.css">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/demo.css">
<script type="text/javascript" language="javascript" src="../../../media/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/syntax/shCore.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/demo.js"></script>
<title>ColReorder examples - ColReorder examples</title>
</head>
<body class="dt-example">
<div class="container">
<section>
<h1>ColReorder example <span>ColReorder examples</span></h1>
<div class="info">
<p>ColReorder adds the ability for the end user to click and drag column headers to reorder a table as they see fit, to DataTables. Key features include:</p>
<ul class="markdown">
<li>Very easy integration with DataTables</li>
<li>Tight integration with all other DataTables plug-ins</li>
<li>The ability to exclude the first (or more) column from being movable</li>
<li>Predefine a column order</li>
<li>Save staving integration with DataTables</li>
</ul>
</div>
</section>
</div>
<section>
<div class="footer">
<div class="gradient"></div>
<div class="liner">
<div class="toc">
<div class="toc-group">
<h3><a href="./index.html">Examples</a></h3>
<ul class="toc">
<li><a href="./simple.html">Basic initialisation</a></li>
<li><a href="./new_init.html">Initialisation using `new`</a></li>
<li><a href="./alt_insert.html">Alternative insert styling</a></li>
<li><a href="./realtime.html">Realtime updating</a></li>
<li><a href="./state_save.html">State saving</a></li>
<li><a href="./scrolling.html">Scrolling table</a></li>
<li><a href="./predefined.html">Predefined column ordering</a></li>
<li><a href="./reset.html">Reset ordering API</a></li>
<li><a href="./colvis.html">ColVis integration</a></li>
<li><a href="./fixedcolumns.html">FixedColumns integration</a></li>
<li><a href="./fixedheader.html">FixedHeader integration</a></li>
<li><a href="./jqueryui.html">jQuery UI styling</a></li>
<li><a href="./col_filter.html">Individual column filtering</a></li>
<li><a href="./server_side.html">Server-side processing</a></li>
</ul>
</div>
</div>
<div class="epilogue">
<p>Please refer to the <a href="http://www.datatables.net">DataTables documentation</a> for full information about its API properties and methods.<br>
Additionally, there are a wide range of <a href="http://www.datatables.net/extras">extras</a> and <a href="http://www.datatables.net/plug-ins">plug-ins</a>
which extend the capabilities of DataTables.</p>
<p class="copyright">DataTables designed and created by <a href="http://www.sprymedia.co.uk">SpryMedia Ltd</a> &#169; 2007-2015<br>
DataTables is licensed under the <a href="http://www.datatables.net/mit">MIT license</a>.</p>
</div>
</div>
</div>
</section>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/ico" href="http://www.datatables.net/favicon.ico">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
<title>ColReorder example - Server-side processing</title>
<link rel="stylesheet" type="text/css" href="../../../media/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="../css/dataTables.colReorder.css">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/syntax/shCore.css">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/demo.css">
<style type="text/css" class="init">
</style>
<script type="text/javascript" language="javascript" src="../../../media/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="../../../media/js/jquery.dataTables.js"></script>
<script type="text/javascript" language="javascript" src="../js/dataTables.colReorder.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/syntax/shCore.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/demo.js"></script>
<script type="text/javascript" language="javascript" class="init">
$(document).ready(function() {
$('#example').dataTable( {
dom: 'Rlfrtip',
processing: true,
serverSide: true,
ajax: "../../../examples/server_side/scripts/objects.php",
columns: [
{ data: "first_name" },
{ data: "last_name" },
{ data: "position" },
{ data: "office" },
{ data: "start_date" },
{ data: "salary" }
]
} );
} );
</script>
</head>
<body class="dt-example">
<div class="container">
<section>
<h1>ColReorder example <span>Server-side processing</span></h1>
<div class="info">
<p>Server-side processing can be exceptionally useful in DataTables when dealing with massive data sets, and ColReorder works with this as would be expected.</p>
<p>It is recommend that you use object based data with server-side processing and ColReorder, as this provides easily understandable mapping between the the
columns and the data relation on the server, otherwise you need to work out array indexes on each call!</p>
</div>
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Extn.</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Extn.</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
<ul class="tabs">
<li class="active">Javascript</li>
<li>HTML</li>
<li>CSS</li>
<li>Ajax</li>
<li>Server-side script</li>
</ul>
<div class="tabs">
<div class="js">
<p>The Javascript shown below is used to initialise the table shown in this example:</p><code class="multiline language-js">$(document).ready(function() {
$('#example').dataTable( {
dom: 'Rlfrtip',
processing: true,
serverSide: true,
ajax: &quot;../../../examples/server_side/scripts/objects.php&quot;,
columns: [
{ data: &quot;first_name&quot; },
{ data: &quot;last_name&quot; },
{ data: &quot;position&quot; },
{ data: &quot;office&quot; },
{ data: &quot;start_date&quot; },
{ data: &quot;salary&quot; }
]
} );
} );</code>
<p>In addition to the above code, the following Javascript library files are loaded for use in this example:</p>
<ul>
<li><a href="../../../media/js/jquery.js">../../../media/js/jquery.js</a></li>
<li><a href="../../../media/js/jquery.dataTables.js">../../../media/js/jquery.dataTables.js</a></li>
<li><a href="../js/dataTables.colReorder.js">../js/dataTables.colReorder.js</a></li>
</ul>
</div>
<div class="table">
<p>The HTML shown below is the raw HTML table element, before it has been enhanced by DataTables:</p>
</div>
<div class="css">
<div>
<p>This example uses a little bit of additional CSS beyond what is loaded from the library files (below), in order to correctly display the table. The
additional CSS used is shown below:</p><code class="multiline language-css"></code>
</div>
<p>The following CSS library files are loaded for use in this example to provide the styling of the table:</p>
<ul>
<li><a href="../../../media/css/jquery.dataTables.css">../../../media/css/jquery.dataTables.css</a></li>
<li><a href="../css/dataTables.colReorder.css">../css/dataTables.colReorder.css</a></li>
</ul>
</div>
<div class="ajax">
<p>This table loads data by Ajax. The latest data that has been loaded is shown below. This data will update automatically as any additional data is
loaded.</p>
</div>
<div class="php">
<p>The script used to perform the server-side processing for this table is shown below. Please note that this is just an example script using PHP. Server-side
processing scripts can be written in any language, using <a href="//datatables.net/manual/server-side">the protocol described in the DataTables
documentation</a>.</p>
</div>
</div>
</section>
</div>
<section>
<div class="footer">
<div class="gradient"></div>
<div class="liner">
<h2>Other examples</h2>
<div class="toc">
<div class="toc-group">
<h3><a href="./index.html">Examples</a></h3>
<ul class="toc active">
<li><a href="./simple.html">Basic initialisation</a></li>
<li><a href="./new_init.html">Initialisation using `new`</a></li>
<li><a href="./alt_insert.html">Alternative insert styling</a></li>
<li><a href="./realtime.html">Realtime updating</a></li>
<li><a href="./state_save.html">State saving</a></li>
<li><a href="./scrolling.html">Scrolling table</a></li>
<li><a href="./predefined.html">Predefined column ordering</a></li>
<li><a href="./reset.html">Reset ordering API</a></li>
<li><a href="./colvis.html">ColVis integration</a></li>
<li><a href="./fixedcolumns.html">FixedColumns integration</a></li>
<li><a href="./fixedheader.html">FixedHeader integration</a></li>
<li><a href="./jqueryui.html">jQuery UI styling</a></li>
<li><a href="./col_filter.html">Individual column filtering</a></li>
<li class="active"><a href="./server_side.html">Server-side processing</a></li>
</ul>
</div>
</div>
<div class="epilogue">
<p>Please refer to the <a href="http://www.datatables.net">DataTables documentation</a> for full information about its API properties and methods.<br>
Additionally, there are a wide range of <a href="http://www.datatables.net/extras">extras</a> and <a href="http://www.datatables.net/plug-ins">plug-ins</a>
which extend the capabilities of DataTables.</p>
<p class="copyright">DataTables designed and created by <a href="http://www.sprymedia.co.uk">SpryMedia Ltd</a> &#169; 2007-2015<br>
DataTables is licensed under the <a href="http://www.datatables.net/mit">MIT license</a>.</p>
</div>
</div>
</div>
</section>
</body>
</html>
\ No newline at end of file
Copyright (c) 2010-2015 SpryMedia Limited
http://datatables.net
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# ColVis
ColVis adds a button to the toolbars around DataTables which gives the end user of the table the ability to dynamically change the visibility of the columns in the table:
* Dynamically show and hide columns in a table
* Very easy integration with DataTables
* Ability to exclude columns from being either hidden or shown
* Save saving integration with DataTables
# Installation
To use ColVis, first download DataTables ( http://datatables.net/download ) and place the unzipped ColVis package into a `extensions` directory in the DataTables package. This will allow the pages in the examples to operate correctly. To see the examples running, open the `examples` directory in your web-browser.
# Basic usage
ColVis is initialised using the `C` option that it adds to DataTables' `dom` option. For example:
```js
$(document).ready( function () {
$('#example').dataTable( {
"dom": 'C<"clear">lfrtip'
} );
} );
```
# Documentation / support
* Documentation: http://datatables.net/extensions/colvis/
* DataTables support forums: http://datatables.net/forums
# GitHub
If you fancy getting involved with the development of ColVis and help make it better, please refer to its GitHub repo: https://github.com/DataTables/ColVis
div.ColVis{float:right;margin-bottom:1em}button.ColVis_Button,ul.ColVis_collection li{position:relative;float:left;margin-right:3px;padding:5px 8px;border:1px solid #999;cursor:pointer;*cursor:hand;font-size:0.88em;color:black !important;white-space:nowrap;-webkit-border-radius:2px;-moz-border-radius:2px;-ms-border-radius:2px;-o-border-radius:2px;border-radius:2px;-webkit-box-shadow:1px 1px 3px #ccc;-moz-box-shadow:1px 1px 3px #ccc;-ms-box-shadow:1px 1px 3px #ccc;-o-box-shadow:1px 1px 3px #ccc;box-shadow:1px 1px 3px #ccc;background:#ffffff;background:-webkit-linear-gradient(top, #fff 0%, #f3f3f3 89%, #f9f9f9 100%);background:-moz-linear-gradient(top, #fff 0%, #f3f3f3 89%, #f9f9f9 100%);background:-ms-linear-gradient(top, #fff 0%, #f3f3f3 89%, #f9f9f9 100%);background:-o-linear-gradient(top, #fff 0%, #f3f3f3 89%, #f9f9f9 100%);background:linear-gradient(top, #fff 0%, #f3f3f3 89%, #f9f9f9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f9f9f9',GradientType=0 )}.ColVis_Button:hover,ul.ColVis_collection li:hover{border:1px solid #666;text-decoration:none !important;-webkit-box-shadow:1px 1px 3px #999;-moz-box-shadow:1px 1px 3px #999;-ms-box-shadow:1px 1px 3px #999;-o-box-shadow:1px 1px 3px #999;box-shadow:1px 1px 3px #999;background:#f3f3f3;background:-webkit-linear-gradient(top, #f3f3f3 0%, #e2e2e2 89%, #f4f4f4 100%);background:-moz-linear-gradient(top, #f3f3f3 0%, #e2e2e2 89%, #f4f4f4 100%);background:-ms-linear-gradient(top, #f3f3f3 0%, #e2e2e2 89%, #f4f4f4 100%);background:-o-linear-gradient(top, #f3f3f3 0%, #e2e2e2 89%, #f4f4f4 100%);background:linear-gradient(top, #f3f3f3 0%, #e2e2e2 89%, #f4f4f4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3f3f3', endColorstr='#f4f4f4',GradientType=0 )}button.ColVis_Button{height:30px;padding:3px 8px}button.ColVis_Button::-moz-focus-inner{border:none !important;padding:0}button.ColVis_Button:active{outline:none}div.ColVis_collectionBackground{position:fixed;top:0;left:0;height:100%;width:100%;background-color:black;z-index:1100}ul.ColVis_collection{list-style:none;width:150px;padding:8px 8px 4px 8px;margin:0;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.4);background-color:#f3f3f3;background-color:rgba(255,255,255,0.3);overflow:hidden;z-index:2002;-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px;-webkit-box-shadow:3px 3px 5px rgba(0,0,0,0.3);-moz-box-shadow:3px 3px 5px rgba(0,0,0,0.3);-ms-box-shadow:3px 3px 5px rgba(0,0,0,0.3);-o-box-shadow:3px 3px 5px rgba(0,0,0,0.3);box-shadow:3px 3px 5px rgba(0,0,0,0.3)}ul.ColVis_collection li{position:relative;height:auto;left:0;right:0;padding:0.5em;display:block;float:none;margin-bottom:4px;-webkit-box-shadow:1px 1px 3px #999;-moz-box-shadow:1px 1px 3px #999;-ms-box-shadow:1px 1px 3px #999;-o-box-shadow:1px 1px 3px #999;box-shadow:1px 1px 3px #999}ul.ColVis_collection li{text-align:left}ul.ColVis_collection li.ColVis_Button:hover{border:1px solid #999;background-color:#f0f0f0}ul.ColVis_collection li span{display:inline-block;padding-left:0.5em;cursor:pointer}ul.ColVis_collection li.ColVis_Special{border-color:#555;background:#ededed;background:-webkit-linear-gradient(top, #ededed 0%, #d6d6d6 77%, #e8e8e8 100%);background:-moz-linear-gradient(top, #ededed 0%, #d6d6d6 77%, #e8e8e8 100%);background:-ms-linear-gradient(top, #ededed 0%, #d6d6d6 77%, #e8e8e8 100%);background:-o-linear-gradient(top, #ededed 0%, #d6d6d6 77%, #e8e8e8 100%);background:linear-gradient(to bottom, #ededed 0%, #d6d6d6 77%, #e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#e8e8e8',GradientType=0 )}ul.ColVis_collection li.ColVis_Special:hover{background:#e2e2e2;background:-webkit-linear-gradient(top, #d0d0d0 0%, #d5d5d5 89%, #e2e2e2 100%);background:-moz-linear-gradient(top, #d0d0d0 0%, #d5d5d5 89%, #e2e2e2 100%);background:-ms-linear-gradient(top, #d0d0d0 0%, #d5d5d5 89%, #e2e2e2 100%);background:-o-linear-gradient(top, #d0d0d0 0%, #d5d5d5 89%, #e2e2e2 100%);background:linear-gradient(top, #d0d0d0 0%, #d5d5d5 89%, #e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3f3f3', endColorstr='#e2e2e2',GradientType=0 )}span.ColVis_radio{display:inline-block;width:20px}div.ColVis_catcher{position:absolute;z-index:1101}.disabled{color:#999}
button.ColVis_Button,
ul.ColVis_collection li {
padding: 0.5em;
}
ul.ColVis_collection {
margin: 0;
padding: 0;
overflow: hidden;
z-index: 2002;
}
ul.ColVis_collection li {
clear: both;
display: block;
text-align: left;
margin: -1px 0 0 0;
}
ul.ColVis_collection li span {
display: inline-block;
padding-left: 0.5em;
cursor: pointer;
}
div.ColVis_collectionBackground {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: black;
z-index: 1100;
}
div.ColVis_catcher {
position: absolute;
z-index: 1101;
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/ico" href="http://www.datatables.net/favicon.ico">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=2.0">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/syntax/shCore.css">
<link rel="stylesheet" type="text/css" href="../../../examples/resources/demo.css">
<script type="text/javascript" language="javascript" src="../../../media/js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/syntax/shCore.js"></script>
<script type="text/javascript" language="javascript" src="../../../examples/resources/demo.js"></script>
<title>ColVis examples - ColVis examples</title>
</head>
<body class="dt-example">
<div class="container">
<section>
<h1>ColVis example <span>ColVis examples</span></h1>
<div class="info">
<p>ColVis adds a button to the toolbars around DataTables which gives the end user of the table the ability to dynamically change the visibility of the columns in
the table:</p>
<ul class="markdown">
<li>Dynamically show and hide columns in a table</li>
<li>Very easy integration with DataTables</li>
<li>Ability to exclude columns from being either hidden or shown</li>
<li>Save saving integration with DataTables</li>
</ul>
</div>
</section>
</div>
<section>
<div class="footer">
<div class="gradient"></div>
<div class="liner">
<div class="toc">
<div class="toc-group">
<h3><a href="./index.html">Examples</a></h3>
<ul class="toc">
<li><a href="./simple.html">Basic initialisation</a></li>
<li><a href="./new_init.html">`new` initialisation</a></li>
<li><a href="./text.html">Custom button text</a></li>
<li><a href="./exclude_columns.html">Exclude columns from list</a></li>
<li><a href="./title_callback.html">Column button callback</a></li>
<li><a href="./button_order.html">Button ordering</a></li>
<li><a href="./mouseover.html">Mouseover activation</a></li>
<li><a href="./group_columns.html">Group columns</a></li>
<li><a href="./two_tables.html">Two tables with individual controls</a></li>
<li><a href="./two_tables_identical.html">Two tables with shared controls</a></li>
<li><a href="./restore.html">Restore / show all</a></li>
<li><a href="./jqueryui.html">jQuery UI styling</a></li>
</ul>
</div>
</div>
<div class="epilogue">
<p>Please refer to the <a href="http://www.datatables.net">DataTables documentation</a> for full information about its API properties and methods.<br>
Additionally, there are a wide range of <a href="http://www.datatables.net/extras">extras</a> and <a href="http://www.datatables.net/plug-ins">plug-ins</a>
which extend the capabilities of DataTables.</p>
<p class="copyright">DataTables designed and created by <a href="http://www.sprymedia.co.uk">SpryMedia Ltd</a> &#169; 2007-2015<br>
DataTables is licensed under the <a href="http://www.datatables.net/mit">MIT license</a>.</p>
</div>
</div>
</div>
</section>
</body>
</html>
\ No newline at end of file
table.DTFC_Cloned thead,table.DTFC_Cloned tfoot{background-color:white}div.DTFC_Blocker{background-color:white}div.DTFC_LeftWrapper table.dataTable,div.DTFC_RightWrapper table.dataTable{margin-bottom:0;z-index:2}div.DTFC_LeftWrapper table.dataTable.no-footer,div.DTFC_RightWrapper table.dataTable.no-footer{border-bottom:none}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论