任务分组管理,修改为执行器管理

v1.5
xueli.xue 8 years ago
parent 204d7848fe
commit 087cd1d435

@ -204,11 +204,12 @@ CREATE TABLE XXL_JOB_QRTZ_TRIGGER_REGISTRY (
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE XXL_JOB_QRTZ_TRIGGER_GROUP ( CREATE TABLE XXL_JOB_QRTZ_TRIGGER_GROUP (
`group_name` varchar(255) NOT NULL, `app_name` varchar(64) NOT NULL,
`group_desc` varchar(255) NOT NULL, `title` varchar(12) NOT NULL,
`order` int(11) NOT NULL, `order` tinyint(4) NOT NULL,
PRIMARY KEY (`group_name`) PRIMARY KEY (`app_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP VALUES ('xxl-job-executor-example', '示例项目', '1');
commit; commit;

@ -2,8 +2,11 @@ package com.xxl.job.admin.controller;
import com.xxl.job.admin.core.model.ReturnT; import com.xxl.job.admin.core.model.ReturnT;
import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.thread.JobRegistryHelper;
import com.xxl.job.admin.dao.IXxlJobGroupDao; import com.xxl.job.admin.dao.IXxlJobGroupDao;
import com.xxl.job.admin.dao.IXxlJobInfoDao; import com.xxl.job.admin.dao.IXxlJobInfoDao;
import com.xxl.job.core.registry.RegistHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
@ -30,6 +33,14 @@ public class JobGroupController {
@RequestMapping @RequestMapping
public String index(Model model) { public String index(Model model) {
List<XxlJobGroup> list = xxlJobGroupDao.findAll(); List<XxlJobGroup> list = xxlJobGroupDao.findAll();
if (CollectionUtils.isNotEmpty(list)) {
for (XxlJobGroup group: list) {
List<String> registryList = JobRegistryHelper.discover(RegistHelper.RegistType.EXECUTOR.name(), group.getAppName());
group.setRegistryList(registryList);
}
}
model.addAttribute("list", list); model.addAttribute("list", list);
return "jobgroup/jobgroup.index"; return "jobgroup/jobgroup.index";
} }
@ -39,17 +50,20 @@ public class JobGroupController {
public ReturnT<String> save(XxlJobGroup xxlJobGroup){ public ReturnT<String> save(XxlJobGroup xxlJobGroup){
// valid // valid
if (xxlJobGroup.getGroupName()==null || StringUtils.isBlank(xxlJobGroup.getGroupName())) { if (xxlJobGroup.getAppName()==null || StringUtils.isBlank(xxlJobGroup.getAppName())) {
return new ReturnT<String>(500, "请输入分组"); return new ReturnT<String>(500, "请输入AppName");
} }
if (xxlJobGroup.getGroupDesc()==null || StringUtils.isBlank(xxlJobGroup.getGroupDesc())) { if (xxlJobGroup.getAppName().length()>64) {
return new ReturnT<String>(500, "请输入描述"); return new ReturnT<String>(500, "AppName长度限制为4~64");
}
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
return new ReturnT<String>(500, "请输入名称");
} }
// check repeat // check repeat
XxlJobGroup group = xxlJobGroupDao.load(xxlJobGroup.getGroupName()); XxlJobGroup group = xxlJobGroupDao.load(xxlJobGroup.getAppName());
if (group!=null) { if (group!=null) {
return new ReturnT<String>(500, "分组已存在, 请勿重复添加"); return new ReturnT<String>(500, "AppName对应的执行器已存在, 请勿重复添加");
} }
int ret = xxlJobGroupDao.save(xxlJobGroup); int ret = xxlJobGroupDao.save(xxlJobGroup);
@ -59,21 +73,37 @@ public class JobGroupController {
@RequestMapping("/update") @RequestMapping("/update")
@ResponseBody @ResponseBody
public ReturnT<String> update(XxlJobGroup xxlJobGroup){ public ReturnT<String> update(XxlJobGroup xxlJobGroup){
// valid
if (xxlJobGroup.getAppName()==null || StringUtils.isBlank(xxlJobGroup.getAppName())) {
return new ReturnT<String>(500, "请输入AppName");
}
if (xxlJobGroup.getAppName().length()>64) {
return new ReturnT<String>(500, "AppName长度限制为4~64");
}
if (xxlJobGroup.getTitle()==null || StringUtils.isBlank(xxlJobGroup.getTitle())) {
return new ReturnT<String>(500, "请输入名称");
}
int ret = xxlJobGroupDao.update(xxlJobGroup); int ret = xxlJobGroupDao.update(xxlJobGroup);
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL; return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
} }
@RequestMapping("/remove") @RequestMapping("/remove")
@ResponseBody @ResponseBody
public ReturnT<String> remove(String groupName){ public ReturnT<String> remove(String appName){
// valid // valid
int count = xxlJobInfoDao.pageListCount(0, 10, groupName, null); int count = xxlJobInfoDao.pageListCount(0, 10, appName, null);
if (count > 0) { if (count > 0) {
return new ReturnT<String>(500, "该分组使用中, 不可删除"); return new ReturnT<String>(500, "该分组使用中, 不可删除");
} }
int ret = xxlJobGroupDao.remove(groupName); List<XxlJobGroup> allList = xxlJobGroupDao.findAll();
if (allList.size() == 1) {
return new ReturnT<String>(500, "删除失败, 系统需要至少预留一个默认分组");
}
int ret = xxlJobGroupDao.remove(appName);
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL; return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
} }

@ -1,28 +1,33 @@
package com.xxl.job.admin.core.model; package com.xxl.job.admin.core.model;
import java.util.List;
/** /**
* Created by xuxueli on 16/9/30. * Created by xuxueli on 16/9/30.
*/ */
public class XxlJobGroup { public class XxlJobGroup {
private String groupName; private String appName;
private String groupDesc; private String title;
private int order; private int order;
public String getGroupName() { // registry list
return groupName; private List<String> registryList;
public String getAppName() {
return appName;
} }
public void setGroupName(String groupName) { public void setAppName(String appName) {
this.groupName = groupName; this.appName = appName;
} }
public String getGroupDesc() { public String getTitle() {
return groupDesc; return title;
} }
public void setGroupDesc(String groupDesc) { public void setTitle(String title) {
this.groupDesc = groupDesc; this.title = title;
} }
public int getOrder() { public int getOrder() {
@ -32,4 +37,12 @@ public class XxlJobGroup {
public void setOrder(int order) { public void setOrder(int order) {
this.order = order; this.order = order;
} }
public List<String> getRegistryList() {
return registryList;
}
public void setRegistryList(List<String> registryList) {
this.registryList = registryList;
}
} }

@ -42,12 +42,12 @@ public class JobRegistryHelper {
if (list != null) { if (list != null) {
for (XxlJobRegistry item: list) { for (XxlJobRegistry item: list) {
String groupKey = makeGroupKey(item.getRegistryGroup(), item.getRegistryKey()); String groupKey = makeGroupKey(item.getRegistryGroup(), item.getRegistryKey());
List<String> dataSet = temp.get(groupKey); List<String> registryList = temp.get(groupKey);
if (dataSet == null) { if (registryList == null) {
dataSet = new ArrayList<String>(); registryList = new ArrayList<String>();
} }
dataSet.add(item.getRegistryValue()); registryList.add(item.getRegistryValue());
temp.put(groupKey, dataSet); temp.put(groupKey, registryList);
} }
} }
registMap = temp; registMap = temp;

@ -15,7 +15,7 @@ public interface IXxlJobGroupDao {
public int update(XxlJobGroup xxlJobGroup); public int update(XxlJobGroup xxlJobGroup);
public int remove(String groupName); public int remove(String appName);
public XxlJobGroup load(String groupName); public XxlJobGroup load(String appName);
} }

@ -33,13 +33,13 @@ public class XxlJobGroupDaoImpl implements IXxlJobGroupDao {
} }
@Override @Override
public int remove(String groupName) { public int remove(String appName) {
return sqlSessionTemplate.delete("XxlJobGroupMapper.remove", groupName); return sqlSessionTemplate.delete("XxlJobGroupMapper.remove", appName);
} }
@Override @Override
public XxlJobGroup load(String groupName) { public XxlJobGroup load(String appName) {
return sqlSessionTemplate.selectOne("XxlJobGroupMapper.load", groupName); return sqlSessionTemplate.selectOne("XxlJobGroupMapper.load", appName);
} }

@ -4,14 +4,14 @@
<mapper namespace="XxlJobGroupMapper"> <mapper namespace="XxlJobGroupMapper">
<resultMap id="XxlJobGroup" type="com.xxl.job.admin.core.model.XxlJobGroup" > <resultMap id="XxlJobGroup" type="com.xxl.job.admin.core.model.XxlJobGroup" >
<result column="group_name" property="groupName" /> <result column="app_name" property="appName" />
<result column="group_desc" property="groupDesc" /> <result column="title" property="title" />
<result column="order" property="order" /> <result column="order" property="order" />
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
t.group_name, t.app_name,
t.group_desc, t.title,
t.order t.order
</sql> </sql>
@ -22,26 +22,26 @@
</select> </select>
<insert id="save" parameterType="java.util.Map" > <insert id="save" parameterType="java.util.Map" >
INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `group_name`, `group_desc`, `order`) INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`)
values ( #{groupName}, #{groupDesc}, #{order}); values ( #{appName}, #{title}, #{order});
</insert> </insert>
<update id="update" parameterType="java.util.Map" > <update id="update" parameterType="java.util.Map" >
UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP
SET `group_desc` = #{groupDesc}, SET `title` = #{title},
`order` = #{order} `order` = #{order}
WHERE group_name = #{groupName} WHERE app_name = #{appName}
</update> </update>
<delete id="remove" parameterType="java.lang.String" > <delete id="remove" parameterType="java.lang.String" >
DELETE FROM XXL_JOB_QRTZ_TRIGGER_GROUP DELETE FROM XXL_JOB_QRTZ_TRIGGER_GROUP
WHERE group_name = #{groupName} WHERE app_name = #{appName}
</delete> </delete>
<select id="load" parameterType="java.lang.String" resultMap="XxlJobGroup"> <select id="load" parameterType="java.lang.String" resultMap="XxlJobGroup">
SELECT <include refid="Base_Column_List" /> SELECT <include refid="Base_Column_List" />
FROM XXL_JOB_QRTZ_TRIGGER_GROUP AS t FROM XXL_JOB_QRTZ_TRIGGER_GROUP AS t
WHERE t.group_name = #{groupName} WHERE t.app_name = #{appName}
</select> </select>
</mapper> </mapper>

@ -85,8 +85,8 @@
<li class="header">常用模块</li> <li class="header">常用模块</li>
<li class="nav-click" ><a href="${request.contextPath}/jobinfo"><i class="fa fa-circle-o text-red"></i> <span>调度管理</span></a></li> <li class="nav-click" ><a href="${request.contextPath}/jobinfo"><i class="fa fa-circle-o text-red"></i> <span>调度管理</span></a></li>
<li class="nav-click" ><a href="${request.contextPath}/joblog"><i class="fa fa-circle-o text-yellow"></i><span>调度日志</span></a></li> <li class="nav-click" ><a href="${request.contextPath}/joblog"><i class="fa fa-circle-o text-yellow"></i><span>调度日志</span></a></li>
<li class="nav-click" ><a href="${request.contextPath}/jobgroup"><i class="fa fa-circle-o text-red"></i> <span>分组管理</span></a></li> <li class="nav-click" ><a href="${request.contextPath}/jobgroup"><i class="fa fa-circle-o text-aqua"></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-red"></i><span>使用教程</span></a></li>
</ul> </ul>
</section> </section>
<!-- /.sidebar --> <!-- /.sidebar -->

@ -16,7 +16,7 @@
<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>

@ -20,7 +20,7 @@
<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>
</section> </section>
<!-- Main content --> <!-- Main content -->
@ -30,16 +30,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>&nbsp;&nbsp;
<button class="btn btn-success btn-xs pull-left2 add" >+新增分组</button> <button class="btn btn-info btn-xs pull-left2 add" >+新增执行器</button>
</div> </div>
<div class="box-body"> <div class="box-body">
<table id="joblog_list" class="table table-bordered table-striped display" width="100%" > <table id="joblog_list" class="table table-bordered table-striped display" width="100%" >
<thead> <thead>
<tr> <tr>
<th name="groupDesc" >名称</th> <th name="appName" >AppName</th>
<th name="groupName" >AppName</th> <th name="title" >名称</th>
<th name="order" >排序</th> <th name="order" >排序</th>
<th name="registryList" >OnLine</th>
<th name="operate" >操作</th> <th name="operate" >操作</th>
</tr> </tr>
</thead> </thead>
@ -47,12 +48,13 @@
<#if list?exists && list?size gt 0> <#if list?exists && list?size gt 0>
<#list list as group> <#list list as group>
<tr> <tr>
<td>${group.groupDesc}</td> <td>${group.appName}</td>
<td>${group.groupName}</td> <td>${group.title}</td>
<td>${group.order}</td> <td>${group.order}</td>
<td><#if group.registryList?exists><#list group.registryList as item><span class="badge bg-green">${item}</span><br></#list></#if></td>
<td> <td>
<button class="btn btn-warning btn-xs update" groupName="${group.groupName}" groupDesc="${group.groupDesc}" order="${group.order}" >编辑</button> <button class="btn btn-warning btn-xs update" appName="${group.appName}" title="${group.title}" order="${group.order}" >编辑</button>
<button class="btn btn-danger btn-xs remove" groupName="${group.groupName}" >删除</button> <button class="btn btn-danger btn-xs remove" appName="${group.appName}" >删除</button>
</td> </td>
</tr> </tr>
</#list> </#list>
@ -71,17 +73,17 @@
<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="lastname" class="col-sm-2 control-label">分组<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">AppName<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="groupName" placeholder="请输入“分组”" maxlength="200" ></div> <div class="col-sm-10"><input type="text" class="form-control" name="appName" placeholder="请输入“AppName”" maxlength="64" ></div>
</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="groupDesc" placeholder="请输入“描述”" maxlength="200" ></div> <div class="col-sm-10"><input type="text" class="form-control" name="title" placeholder="请输入“名称”" maxlength="12" ></div>
</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>
@ -105,17 +107,17 @@
<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="lastname" class="col-sm-2 control-label">分组<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">AppName<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="groupName" placeholder="请输入“分组”" maxlength="200" readonly ></div> <div class="col-sm-10"><input type="text" class="form-control" name="appName" placeholder="请输入“AppName”" maxlength="64" readonly ></div>
</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="groupDesc" placeholder="请输入“描述”" maxlength="200" ></div> <div class="col-sm-10"><input type="text" class="form-control" name="title" placeholder="请输入“名称”" maxlength="12" ></div>
</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>

@ -25,7 +25,7 @@
<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>

@ -2,20 +2,24 @@ $(function() {
// remove // remove
$('.remove').on('click', function(){ $('.remove').on('click', function(){
var groupName = $(this).attr('groupName'); var appName = $(this).attr('appName');
ComConfirm.show("确认删除分组?", function(){ ComConfirm.show("确认删除分组?", function(){
$.ajax({ $.ajax({
type : 'POST', type : 'POST',
url : base_url + '/jobgroup/remove', url : base_url + '/jobgroup/remove',
data : {"groupName":groupName}, data : {"appName":appName},
dataType : "json", dataType : "json",
success : function(data){ success : function(data){
if (data.code == 200) { if (data.code == 200) {
ComAlert.show(1, '删除成功'); ComAlert.show(1, '删除成功');
window.location.reload(); window.location.reload();
} else { } else {
ComAlert.show(2, '删除失败'); if (data.msg) {
ComAlert.show(2, data.msg);
} else {
ComAlert.show(2, '删除失败');
}
} }
}, },
}); });
@ -37,12 +41,12 @@ $(function() {
errorClass : 'help-block', errorClass : 'help-block',
focusInvalid : true, focusInvalid : true,
rules : { rules : {
groupName : { appName : {
required : true, required : true,
rangelength:[4,200], rangelength:[4,64],
myValid01 : true myValid01 : true
}, },
groupDesc : { title : {
required : true, required : true,
rangelength:[4, 12] rangelength:[4, 12]
}, },
@ -53,13 +57,13 @@ $(function() {
} }
}, },
messages : { messages : {
groupName : { appName : {
required :"请输入“分组”", required :"请输入“AppName”",
rangelength:"长度限制为4~200", rangelength:"AppName长度限制为4~64",
myValid01: "限制以小写字母开头,由小写字母、数字和中划线组成" myValid01: "限制以小写字母开头,由小写字母、数字和中划线组成"
}, },
groupDesc : { title : {
required :"请输入“描述”", required :"请输入“执行器名称”",
rangelength:"长度限制为4~12" rangelength:"长度限制为4~12"
}, },
order : { order : {
@ -104,8 +108,8 @@ $(function() {
}); });
$('.update').on('click', function(){ $('.update').on('click', function(){
$("#updateModal .form input[name='groupName']").val($(this).attr("groupName")); $("#updateModal .form input[name='appName']").val($(this).attr("appName"));
$("#updateModal .form input[name='groupDesc']").val($(this).attr("groupDesc")); $("#updateModal .form input[name='title']").val($(this).attr("title"));
$("#updateModal .form input[name='order']").val($(this).attr("order")); $("#updateModal .form input[name='order']").val($(this).attr("order"));
$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show'); $('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
@ -115,12 +119,12 @@ $(function() {
errorClass : 'help-block', errorClass : 'help-block',
focusInvalid : true, focusInvalid : true,
rules : { rules : {
groupName : { appName : {
required : true, required : true,
rangelength:[4,200], rangelength:[4,64],
myValid01 : true myValid01 : true
}, },
groupDesc : { title : {
required : true, required : true,
rangelength:[4, 12] rangelength:[4, 12]
}, },
@ -131,13 +135,13 @@ $(function() {
} }
}, },
messages : { messages : {
groupName : { appName : {
required :"请输入“分组”", required :"请输入“AppName”",
rangelength:"长度限制为4~200", rangelength:"AppName长度限制为4~64",
myValid01: "限制以小写字母开头,由小写字母、数字和中划线组成" myValid01: "限制以小写字母开头,由小写字母、数字和中划线组成"
}, },
groupDesc : { title : {
required :"请输入“描述”", required :"请输入“执行器名称”",
rangelength:"长度限制为4~12" rangelength:"长度限制为4~12"
}, },
order : { order : {

Loading…
Cancel
Save