调度日志-前后端,重构

v1.3
xueli.xue 9 years ago
parent 670f71e557
commit e26f94e4fa

@ -29,4 +29,5 @@ git.osc地址http://git.oschina.net/xuxueli0323/xxl-job
# 其他说明
清楚僵尸任务qrtz_cron_triggers、qrtz_triggers、qrtz_job_details顺序删除
V1.2新增任务日志记得执行“qrtz_trigger_log”生成表结构

@ -0,0 +1,35 @@
/*
Navicat MySQL Data Transfer
Source Server : meme-127.0.0.1
Source Server Version : 50544
Source Host : 127.0.0.1:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50544
File Encoding : 65001
Date: 2015-12-30 23:27:14
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for qrtz_trigger_log
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_trigger_log`;
CREATE TABLE `qrtz_trigger_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_name` varchar(255) NOT NULL,
`job_cron` varchar(128) DEFAULT NULL,
`job_class` varchar(255) DEFAULT NULL,
`job_data` varchar(2048) DEFAULT NULL,
`trigger_time` datetime DEFAULT NULL,
`trigger_status` varchar(255) DEFAULT NULL,
`trigger_msg` varchar(255) DEFAULT NULL,
`handle_time` datetime DEFAULT NULL,
`handle_status` varchar(255) DEFAULT NULL,
`handle_msg` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=127 DEFAULT CHARSET=utf8;

@ -1,5 +1,6 @@
package com.xxl.job.controller;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -7,6 +8,8 @@ import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@ -42,26 +45,39 @@ public class JobLogController {
return ReturnT.FAIL;
}
@RequestMapping("/")
public String index(Model model) {
@RequestMapping
public String index(Model model, String jobName, String filterTime) {
model.addAttribute("jobName", jobName);
model.addAttribute("filterTime", filterTime);
return "joblog/index";
}
@RequestMapping("/pageList")
@ResponseBody
public Map<String, Object> pageList(@RequestParam(required = false) String jobName,
@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length) {
System.out.println(start);
System.out.println(length);
System.out.println(jobName);
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length,
String jobName, String filterTime) {
// parse param
Date triggerTimeStart = null;
Date triggerTimeEnd = null;
if (StringUtils.isNotBlank(filterTime)) {
String[] temp = filterTime.split(" - ");
if (temp!=null && temp.length == 2) {
try {
triggerTimeEnd = DateUtils.parseDate(temp[0], new String[]{"yyyy-MM-dd HH:mm:ss"});
triggerTimeEnd = DateUtils.parseDate(temp[1], new String[]{"yyyy-MM-dd HH:mm:ss"});
} catch (ParseException e) {
e.printStackTrace();
}
}
}
List<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobName);
int list_count = xxlJobLogDao.pageListCount(start, length, jobName);
// page query
List<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobName, triggerTimeStart, triggerTimeEnd);
int list_count = xxlJobLogDao.pageListCount(start, length, jobName, triggerTimeStart, triggerTimeEnd);
// package result
Map<String, Object> maps = new HashMap<String, Object>();
maps.put("draw", list_count); // 请求次数
maps.put("recordsTotal", list_count); // 总记录数
maps.put("recordsFiltered", list_count);// 过滤后的总记录数
maps.put("data", list); // 分页列表

@ -78,9 +78,17 @@
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobLog">
SELECT <include refid="Base_Column_List" />
FROM qrtz_trigger_log AS t
<if test="jobName != null and jobName!=''">
WHERE t.job_name = #{jobName}
</if>
<trim prefix="WHERE" prefixOverrides="AND | OR" >
<if test="jobName != null and jobName!=''">
AND t.job_name = #{jobName}
</if>
<if test="triggerTimeStart != null">
AND t.trigger_time <![CDATA[ > ]]> #{triggerTimeStart}
</if>
<if test="triggerTimeEnd != null">
AND t.trigger_time <![CDATA[ < ]]> #{triggerTimeEnd}
</if>
</trim>
ORDER BY id DESC
LIMIT #{offset}, #{pagesize}
</select>
@ -88,9 +96,17 @@
<select id="pageListCount" parameterType="java.util.HashMap" resultType="int">
SELECT count(1)
FROM qrtz_trigger_log AS t
<if test="jobName != null and jobName!=''">
WHERE t.job_name = #{jobName}
</if>
<trim prefix="WHERE" prefixOverrides="AND | OR" >
<if test="jobName != null and jobName!=''">
AND t.job_name = #{jobName}
</if>
<if test="triggerTimeStart != null">
AND t.trigger_time <![CDATA[ > ]]> #{triggerTimeStart}
</if>
<if test="triggerTimeEnd != null">
AND t.trigger_time <![CDATA[ < ]]> #{triggerTimeEnd}
</if>
</trim>
</select>
</mapper>

@ -1,6 +1,7 @@
package com.xxl.job.dao;
import java.util.Date;
import java.util.List;
import com.xxl.job.core.model.XxlJobLog;
@ -15,8 +16,8 @@ public interface IXxlJobLogDao {
public int updateHandleInfo(XxlJobLog xxlJobLog);
public List<XxlJobLog> pageList(int offset, int pagesize,String jobName);
public List<XxlJobLog> pageList(int offset, int pagesize,String jobName, Date triggerTimeStart, Date triggerTimeEnd);
public int pageListCount(int offset, int pagesize,String jobName);
public int pageListCount(int offset, int pagesize,String jobName, Date triggerTimeStart, Date triggerTimeEnd);
}

@ -1,5 +1,6 @@
package com.xxl.job.dao.impl;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -38,20 +39,24 @@ public class XxlJobLogDaoImpl implements IXxlJobLogDao {
}
@Override
public List<XxlJobLog> pageList(int offset, int pagesize, String jobName) {
public List<XxlJobLog> pageList(int offset, int pagesize,String jobName, Date triggerTimeStart, Date triggerTimeEnd) {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("offset", offset);
params.put("pagesize", pagesize);
params.put("jobName", jobName);
params.put("triggerTimeStart", triggerTimeStart);
params.put("triggerTimeEnd", triggerTimeEnd);
return sqlSessionTemplate.selectList("XxlJobLogMapper.pageList", params);
}
@Override
public int pageListCount(int offset, int pagesize, String jobName) {
public int pageListCount(int offset, int pagesize,String jobName, Date triggerTimeStart, Date triggerTimeEnd) {
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("offset", offset);
params.put("pagesize", pagesize);
params.put("jobName", jobName);
params.put("triggerTimeStart", triggerTimeStart);
params.put("triggerTimeEnd", triggerTimeEnd);
return sqlSessionTemplate.selectOne("XxlJobLogMapper.pageListCount", params);
}

@ -65,7 +65,7 @@
<ul class="sidebar-menu">
<li class="header">常用模块</li>
<li class="nav-click" ><a href="${request.contextPath}/job/"><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}/help"><i class="fa fa-circle-o text-yellow"></i><span>使用教程</span></a></li>
</ul>
</section>

@ -80,8 +80,10 @@
<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>
</#if>
<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-info btn-xs update" type="button">更新corn</button>
<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>
<button class="btn btn-warning btn-xs" type="job_del" type="button"
onclick="javascript:window.open('${request.contextPath}/joblog?jobName=${item['TriggerKey'].name}')" >查看日志</button>
</p>
</td>
</tr>

@ -6,14 +6,8 @@
<@netCommon.commonStyle />
<!-- DataTables -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.css">
<!-- DataTables CSS -->
<link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.7/css/jquery.dataTables.css">
<!-- jQuery -->
<script type="text/javascript" charset="utf8" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<!-- DataTables -->
<script type="text/javascript" charset="utf8" src="http://cdn.datatables.net/1.10.7/js/jquery.dataTables.js"></script>
<!-- daterangepicker -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker-bs3.css">
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
@ -35,35 +29,51 @@
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-5">
<div class="input-group">
<span class="input-group-addon">
调度时间
</span>
<input type="text" class="form-control" id="filterTime" readonly
value="<#if triggerTimeStart?exists && triggerTimeEnd?exists >${triggerTimeStart?if_exists?string('yyyy-MM-dd HH:mm:ss')} - ${triggerTimeEnd?if_exists?string('yyyy-MM-dd HH:mm:ss')}</#if>" >
</div>
</div>
<div class="col-xs-5">
<div class="input-group">
<span class="input-group-addon">
jobName
</span>
<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
</div>
</div>
<div class="col-xs-2">
<button class="btn btn-block btn-info" id="searchBtn">搜索</button>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">调度列表</h3>
</div>
<div class="box-header"><h3 class="box-title">调度日志</h3></div>
<div class="box-body">
<table id="joblog_list" class="table table-bordered table-striped display">
<table id="joblog_list" class="table table-bordered table-striped display" width="100%" >
<thead>
<tr>
<th>id</th>
<th>jobName</th>
<th>jobCron</th>
<th>jobClass</th>
<th>jobData</th>
<th>triggerTime</th>
<th>triggerStatus</th>
<th>triggerMsg</th>
<th>handleTime</th>
<th>handleStatus</th>
<th>handleMsg</th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th>id</th>
<th>jobName</th>
<th>jobCron</th>
<th>jobClass</th>
<th>handleTime</th>
<th>handleStatus</th>
</tr>
</tfoot>
</table>
</div>
</div>
@ -83,6 +93,9 @@
<!-- DataTables -->
<script src="${request.contextPath}/static/adminlte/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.min.js"></script>
<!-- daterangepicker -->
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>
<script>var base_url = '${request.contextPath}';</script>
<script src="${request.contextPath}/static/js/joblog.index.1.js"></script>
</body>

@ -0,0 +1,335 @@
/*!
* Stylesheet for the Date Range Picker, for use with Bootstrap 3.x
*
* Copyright 2013-2015 Dan Grossman ( http://www.dangrossman.info )
* Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php
*
* Built for http://www.improvely.com
*/
.daterangepicker.dropdown-menu {
max-width: none;
z-index: 3000;
}
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
float: left;
margin: 4px;
}
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
float: right;
margin: 4px;
}
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
float: none;
}
.daterangepicker .ranges {
width: 160px;
text-align: left;
}
.daterangepicker .ranges .range_inputs>div {
float: left;
}
.daterangepicker .ranges .range_inputs>div:nth-child(2) {
padding-left: 11px;
}
.daterangepicker .calendar {
display: none;
max-width: 270px;
}
.daterangepicker.show-calendar .calendar {
display: block;
}
.daterangepicker .calendar.single .calendar-date {
border: none;
}
.daterangepicker .calendar th, .daterangepicker .calendar td {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
white-space: nowrap;
text-align: center;
min-width: 32px;
}
.daterangepicker .daterangepicker_start_input label,
.daterangepicker .daterangepicker_end_input label {
color: #333;
display: block;
font-size: 11px;
font-weight: normal;
height: 20px;
line-height: 20px;
margin-bottom: 2px;
text-shadow: #fff 1px 1px 0px;
text-transform: uppercase;
width: 74px;
}
.daterangepicker .ranges input {
font-size: 11px;
}
.daterangepicker .ranges .input-mini {
border: 1px solid #ccc;
border-radius: 4px;
color: #555;
display: block;
font-size: 11px;
height: 30px;
line-height: 30px;
vertical-align: middle;
margin: 0 0 10px 0;
padding: 0 6px;
width: 74px;
}
.daterangepicker .ranges ul {
list-style: none;
margin: 0;
padding: 0;
}
.daterangepicker .ranges li {
font-size: 13px;
background: #f5f5f5;
border: 1px solid #f5f5f5;
color: #08c;
padding: 3px 12px;
margin-bottom: 8px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
cursor: pointer;
}
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
background: #08c;
border: 1px solid #08c;
color: #fff;
}
.daterangepicker .calendar-date {
border: 1px solid #ddd;
padding: 4px;
border-radius: 4px;
background: #fff;
}
.daterangepicker .calendar-time {
text-align: center;
margin: 8px auto 0 auto;
line-height: 30px;
}
.daterangepicker {
position: absolute;
background: #fff;
top: 100px;
left: 20px;
padding: 4px;
margin-top: 1px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.daterangepicker.opensleft:before {
position: absolute;
top: -7px;
right: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensleft:after {
position: absolute;
top: -6px;
right: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.openscenter:before {
position: absolute;
top: -7px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.openscenter:after {
position: absolute;
top: -6px;
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.opensright:before {
position: absolute;
top: -7px;
left: 9px;
display: inline-block;
border-right: 7px solid transparent;
border-bottom: 7px solid #ccc;
border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker.opensright:after {
position: absolute;
top: -6px;
left: 10px;
display: inline-block;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
content: '';
}
.daterangepicker.dropup{
margin-top: -5px;
}
.daterangepicker.dropup:before{
top: initial;
bottom:-7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.dropup:after{
top: initial;
bottom:-6px;
border-bottom: initial;
border-top: 6px solid #fff;
}
.daterangepicker table {
width: 100%;
margin: 0;
}
.daterangepicker td, .daterangepicker th {
text-align: center;
width: 20px;
height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
}
.daterangepicker td.off {
color: #999;
}
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999;
}
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
background: #eee;
}
.daterangepicker td.in-range {
background: #ebf4f8;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.daterangepicker td.start-date {
-webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px;
}
.daterangepicker td.end-date {
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
}
.daterangepicker td.start-date.end-date {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #357ebd;
border-color: #3071a9;
color: #fff;
}
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc;
}
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px;
padding: 1px;
height: auto;
margin: 0;
cursor: default;
}
.daterangepicker select.monthselect {
margin-right: 2%;
width: 56%;
}
.daterangepicker select.yearselect {
width: 40%;
}
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 50px;
margin-bottom: 0;
}
.daterangepicker_start_input {
float: left;
}
.daterangepicker_end_input {
float: left;
padding-left: 11px
}
.daterangepicker th.month {
width: auto;
}

File diff suppressed because one or more lines are too long

@ -1,20 +1,39 @@
$(function() {
// init date tables
$("#joblog_list").dataTable({
"serverSide": true,
var logTable = $("#joblog_list").dataTable({
"deferRender": true,
"processing" : true,
"serverSide": true,
"ajax": {
url: base_url + "/joblog/pageList"
url: base_url + "/joblog/pageList" ,
data : function ( d ) {
d.filterTime = $('#filterTime').val();
d.jobName = $('#jobName').val()
}
},
"processing" : true,
"deferRender": true,
"scrollX": true,
"columns": [
{ "data": 'id', "bSortable": false, "visible" : true},
{ "data": 'id', "bSortable": false, "visible" : false},
{ "data": 'jobName', "bSortable": false},
{ "data": 'jobCron', "bSortable": false},
{ "data": 'jobClass', "bSortable": false},
{ "data": 'jobData', "bSortable": false},
{
"data": 'triggerTime',
"bSortable": false,
"render": function ( data, type, row ) {
return moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss");
}
},
{ "data": 'triggerStatus', "bSortable": false},
{ "data": 'triggerMsg',"bSortable": false},
{ "data": 'handleTime',"bSortable": false},
{ "data": 'handleStatus' , "bSortable": false}
{ "data": 'handleStatus',"bSortable": false},
{ "data": 'handleMsg' , "bSortable": false}
],
"searching": false,
"ordering": true,
"language" : {
"sProcessing" : "处理中...",
"sLengthMenu" : "每页 _MENU_ 条记录",
@ -41,4 +60,36 @@ $(function() {
}
});
// 过滤时间
$('#filterTime').daterangepicker({
timePicker: true, //是否显示小时和分钟
timePickerIncrement: 10, //时间的增量,单位为分钟
timePicker12Hour : false, //是否使用12小时制来显示时间
format: 'YYYY-MM-DD HH:mm:ss',
separator : ' - ',
ranges : {
'最近1小时': [moment().subtract('hours',1), moment()],
'今日': [moment().startOf('day'), moment()],
'昨日': [moment().subtract('days', 1).startOf('day'), moment().subtract('days', 1).endOf('day')],
'最近7日': [moment().subtract('days', 6), moment()],
'最近30日': [moment().subtract('days', 29), moment()]
},
opens : 'right', //日期选择框的弹出位置
locale : {
customRangeLabel : '自定义',
applyLabel : '确定',
cancelLabel : '取消',
fromLabel : '起始时间',
toLabel : '结束时间',
daysOfWeek : [ '日', '一', '二', '三', '四', '五', '六' ],
monthNames : [ '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月' ],
firstDay : 1
}
});
// 搜索按钮
$('#searchBtn').on('click', function(){
logTable.fnDraw();
});
});

@ -57,8 +57,8 @@ public class XxlJobLogTest {
@Test
public void pageList(){
List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null);
int list_count = xxlJobLogDao.pageListCount(0, 20, null);
List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null, null, null);
int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null);
System.out.println(list);
System.out.println(list_count);

@ -94,7 +94,7 @@ public class HandlerRepository {
new Object[]{handlerData, _status, _msg, callback_response, this});
} else {
try {
TimeUnit.SECONDS.sleep(3);
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}

Loading…
Cancel
Save