SpringBoot集成XXL-JOB實現(xiàn)任務(wù)管理全流程
一、前言
XXL-JOB 是一款輕量級分布式任務(wù)調(diào)度平臺,功能豐富、界面簡潔、易于擴展。本文介紹如何通過 Spring Boot 項目,使用 RestTemplate 和 Feign 的方式調(diào)用 XXL-JOB 后臺管理接口,實現(xiàn)任務(wù)的全生命周期管理(包括添加、修改、啟動、停止、刪除、查詢執(zhí)行器、查詢?nèi)罩镜炔僮鳎?/p>
二、項目結(jié)構(gòu)簡述
主要包含三個部分:
- Controller:對外提供 REST 接口;
- Service:封裝對 XXL-JOB 后臺的具體調(diào)用邏輯;
- FeignClient(可選):用于部分接口遠程調(diào)用。
三、Maven 依賴
只需引入 xxl-job-core 依賴(用于調(diào)度執(zhí)行器 JobHandler 的注冊等):
<!-- xxl-job 核心依賴 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1</version>
</dependency>
四、Controller 代碼詳解
@RestController
@RequestMapping("/xxl")
public class XxlJobController {
@Autowired
private XxlJobService jobService;
/**
* 添加任務(wù)
*/
@PostMapping("/add/job")
public Map addJob(@RequestParam String user, @RequestParam String pass) {
String cookie = jobService.login(user, pass);
return jobService.createJob(cookie);
}
/**
* 修改任務(wù)
*/
@PostMapping("/update/job")
public Map updateJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.updateJob(cookie, jobId);
}
/**
* 刪除任務(wù)
*/
@PostMapping("/remove/job")
public ResultModel removeJob(@RequestParam Integer jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.removeJob(cookie, jobId);
}
/**
* 啟動作業(yè)
*/
@PostMapping("/start/job")
public Map startJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.startJob(cookie, jobId);
}
/**
* 停止作業(yè)
*/
@PostMapping("/stop/job")
public Map stopJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.stopJob(cookie, jobId);
}
/**
* 獲取執(zhí)行器列表
*/
@GetMapping("/jobgroups")
public List<Map<String, Object>> getJobGroupList() {
String cookie = jobService.login("admin", "123456");
return jobService.getJobGroupList(cookie);
}
/**
* 獲取任務(wù)列表
*/
@GetMapping("/tasks")
public Map getJobList() {
String cookie = jobService.login("admin", "123456");
return jobService.getJobList(null, cookie);
}
/**
* 獲取任務(wù)日志
*/
@PostMapping("/jobLogs")
public Map getJobLogs(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.getJobLogs(cookie, jobId);
}
}
五、Service 接口設(shè)計
public interface XxlJobService {
String login(String user, String pass);
Map createJob(String cookie);
Map updateJob(String cookie, String jobId);
ResultModel removeJob(String cookie, Integer jobId);
Map startJob(String cookie, String jobId);
Map stopJob(String cookie, String jobId);
List<Map<String, Object>> getJobGroupList(String cookie);
Map getJobList(Integer jobGroup, String cookie);
Map getJobLogs(String cookie, String jobId);
}
六、Service 實現(xiàn)詳解
下面是部分關(guān)鍵實現(xiàn)說明。
1. 登錄獲取 Cookie
@Override
public String login(String user, String pass) {
Response response = client.login("application/x-www-form-urlencoded", user, pass);
Collection<String> cookies = response.headers().get("Set-Cookie");
for (String cookie : cookies) {
if (cookie.contains("XXL_JOB_LOGIN_IDENTITY")) {
return cookie.split(";")[0];
}
}
throw new RuntimeException("登錄失敗");
}
- 使用 FeignClient 調(diào)用登錄接口,提取 Cookie,用于后續(xù)請求認證。
2. 添加任務(wù)
@Override
public Map createJob(String cookie) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
paramMap.add("jobDesc", "定時任務(wù)");
paramMap.add("scheduleConf", "0 */1 * * * ?");
paramMap.add("executorHandler", "checkTimeout");
paramMap.add("executorParam", "xxl-feign");
paramMap.add("jobGroup", "1");
paramMap.add("author", "admin");
paramMap.add("scheduleType", "CRON");
paramMap.add("glueType", "BEAN");
paramMap.add("executorRouteStrategy", "FIRST");
paramMap.add("misfireStrategy", "DO_NOTHING");
paramMap.add("executorBlockStrategy", "SERIAL_EXECUTION");
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramMap, headers);
ResponseEntity<String> response = restTemplate.postForEntity(
"http://xxl-job-host:port/xxl-job-admin/jobinfo/add", entity, String.class);
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
}
- 替換
xxl-job-host:port為你部署的地址; - 參數(shù)含義詳見 XXL-JOB 后臺手動添加任務(wù)頁面。
3. 修改任務(wù)
@Override
public Map updateJob(String cookie, String jobId) {
// 和添加類似,帶上任務(wù) ID 即可更新
}
4. 啟動/停止任務(wù)
@Override
public Map startJob(String cookie, String jobId) {
// 調(diào)用接口:/jobinfo/start
}
@Override
public Map stopJob(String cookie, String jobId) {
// 調(diào)用接口:/jobinfo/stop
}
5. 獲取執(zhí)行器/任務(wù)/日志列表
/jobgroup/pageList:獲取執(zhí)行器;/jobinfo/pageList:獲取任務(wù)列表;/joblog/pageList:查詢?nèi)蝿?wù)日志。
七、統(tǒng)一響應(yīng)模型(可選)
可以封裝一個通用 ResultModel 響應(yīng)類統(tǒng)一格式返回。
八、調(diào)用測試建議
可使用 Postman 測試每個接口,注意設(shè)置:
- Content-Type 為
application/x-www-form-urlencoded; - 傳入正確的賬號密碼和參數(shù)值。
九、總結(jié)
通過本文提供的代碼,你可以用 Java 實現(xiàn)對 XXL-JOB 管理后臺的編程式控制,實現(xiàn)任務(wù)的全生命周期管理,非常適合自定義調(diào)度中心或自動化平臺集成。
十、 完整代碼
控制器層 XxlJobController.java
@RestController
@RequestMapping("/xxl")
public class XxlJobController {
@Autowired
private XxlJobService jobService;
/**
* 新增定時任務(wù)
*/
@PostMapping("/add/job")
public Map addJob(@RequestParam String user, @RequestParam String pass) {
String cookie = jobService.login(user, pass);
return jobService.createJob(cookie);
}
/**
* 修改定時任務(wù)
*/
@PostMapping("/update/job")
public Map updateJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.updateJob(cookie, jobId);
}
/**
* 刪除定時任務(wù)
*/
@PostMapping("/remove/job")
public ResultModel removeJob(@RequestParam Integer jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.removeJob(cookie, jobId);
}
/**
* 啟動作業(yè)
*/
@PostMapping("/start/job")
public Map startJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.startJob(cookie, jobId);
}
/**
* 停止作業(yè)
*/
@PostMapping("/stop/job")
public Map stopJob(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.stopJob(cookie, jobId);
}
/**
* 獲取執(zhí)行器列表
*/
@GetMapping("/jobgroups")
public List<Map<String, Object>> getJobGroupList() {
String cookie = jobService.login("admin", "123456");
return jobService.getJobGroupList(cookie);
}
/**
* 獲取任務(wù)列表
*/
@GetMapping("/tasks")
public Map getJobList() {
String cookie = jobService.login("admin", "123456");
return jobService.getJobList(null, cookie);
}
/**
* 查詢?nèi)蝿?wù)日志
*/
@PostMapping("/jobLogs")
public Map getJobLogs(@RequestParam String jobId) {
String cookie = jobService.login("admin", "123456");
return jobService.getJobLogs(cookie, jobId);
}
}
接口層:XxlJobService.java
public interface XxlJobService {
/**
* 登錄獲取 Cookie
*/
String login(String user, String pass);
/**
* 創(chuàng)建任務(wù)
*/
Map createJob(String cookie);
/**
* 修改任務(wù)
*/
Map updateJob(String cookie, String jobId);
/**
* 刪除任務(wù)
*/
ResultModel removeJob(String cookie, Integer jobId);
/**
* 啟動作業(yè)
*/
Map startJob(String cookie, String jobId);
/**
* 停止作業(yè)
*/
Map stopJob(String cookie, String jobId);
/**
* 查詢執(zhí)行器列表
*/
List<Map<String, Object>> getJobGroupList(String cookie);
/**
* 查詢?nèi)蝿?wù)列表
*/
Map getJobList(Integer jobGroup, String cookie);
/**
* 獲取任務(wù)日志
*/
Map getJobLogs(String cookie, String jobId);
}
實現(xiàn)層:XxlJobServiceImpl.java
@Service
public class XxlJobServiceImpl implements XxlJobService {
@Autowired
private XxlJobFeignClient client;
/**
* 調(diào)用 XXL-JOB 登錄接口,返回 Cookie
*/
@Override
public String login(String user, String pass) {
Response response = client.login("application/x-www-form-urlencoded", user, pass);
Collection<String> cookies = response.headers().get("Set-Cookie");
if (cookies != null) {
for (String cookie : cookies) {
if (cookie.contains("XXL_JOB_LOGIN_IDENTITY")) {
// 截取真正的 cookie 值
// 只取第一個部分
return cookie.split(";")[0];
}
}
}
throw new RuntimeException("登錄失敗,未獲取到認證 Cookie");
}
@Override
public Map createJob(String cookie) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
paramMap.add("jobDesc", "定時任務(wù)");
paramMap.add("scheduleConf", "0 */1 * * * ?");
paramMap.add("cronGen_display", "0 */1 * * * ?");
paramMap.add("schedule_conf_CRON", "0 */1 * * * ?");
paramMap.add("executorHandler", "checkTimeout");
paramMap.add("executorParam", "xxl-feign");
paramMap.add("jobGroup", "33");
paramMap.add("author", "admin");
paramMap.add("scheduleType", "CRON");
paramMap.add("glueType", "BEAN");
paramMap.add("executorRouteStrategy", "FIRST");
paramMap.add("misfireStrategy", "DO_NOTHING");
paramMap.add("executorBlockStrategy", "SERIAL_EXECUTION");
paramMap.add("executorTimeout", "0");
paramMap.add("executorFailRetryCount", "0");
paramMap.add("glueRemark", "GLUE代碼初始化");
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramMap, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin/jobinfo/add", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 修改任務(wù)(如修改調(diào)度頻率等)
*/
@Override
public Map updateJob(String cookie, String jobId) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> job = new LinkedMultiValueMap<>();
job.add("id", jobId);
job.add("jobGroup", "1");
job.add("jobDesc", "修改任務(wù)");
job.add("author", "admin");
job.add("scheduleType", "CRON");
// 改為每5分鐘執(zhí)行
job.add("scheduleConf", "0 */5 * * * ?");
job.add("executorRouteStrategy", "ROUND");
job.add("executorHandler", "demoJobHandler");
job.add("executorParam", "param-updated");
job.add("executorBlockStrategy", "SERIAL_EXECUTION");
job.add("glueType", "BEAN");
job.add("misfireStrategy", "DO_NOTHING");
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(job, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin/jobinfo/update", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 刪除任務(wù)
*/
@Override
public ResultModel removeJob(String cookie, Integer jobId) {
return client.removeJob(cookie, jobId);
}
/**
* 啟動作業(yè)
*/
@Override
public Map startJob(String cookie, String jobId) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
paramMap.add("id", jobId);
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramMap, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin//jobinfo/start", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 停止作業(yè)
*/
@Override
public Map stopJob(String cookie, String jobId) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
paramMap.add("id", jobId);
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramMap, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin//jobinfo/stop", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
@Override
public List<Map<String, Object>> getJobGroupList(String cookie) {
// 調(diào)用 Feign 客戶端獲取執(zhí)行器列表
Map<String, Object> response = client.getJobGroups(cookie, 0, 100);
// 從返回結(jié)果中獲取執(zhí)行器數(shù)據(jù)列表
return (List<Map<String, Object>>) response.get("data");
}
@Override
public Map getJobList(Integer jobGroup, String cookie) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.add("jobGroup", "33");
// 表示全部
parameters.add("triggerStatus","-1");
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(parameters, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin/jobinfo/pageList", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
@Override
public Map getJobLogs(String cookie, String jobId) {
RestTemplate restTemplate = new RestTemplate();
// 創(chuàng)建請求頭
HttpHeaders headers = new HttpHeaders();
headers.add("Cookie", cookie);
// 構(gòu)建查詢參數(shù)
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
//執(zhí)行器id(必傳)
params.add("jobGroup", "33");
//任務(wù)狀態(tài)(必傳)
params.add("logStatus", "-1");
// 任務(wù)ID
params.add("jobId", jobId);
// 當前頁碼
params.add("pageNum", "1");
// 每頁大小
params.add("pageSize", "10");
// 調(diào)用 Feign 客戶端的查詢?nèi)罩窘涌?
// return client.getJobLogs(cookie, params);
// 創(chuàng)建 HttpEntity 實例,包含請求頭和參數(shù)
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
// 發(fā)送 POST 請求
ResponseEntity<String> response = restTemplate.postForEntity("http://192.168.1.xxx:8080/xxl-job-admin//joblog/pageList", entity, String.class);
// 解析響應(yīng)為 HashMap
try {
return new ObjectMapper().readValue(response.getBody(), HashMap.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}Feign 客戶端:XxlJobFeignClient.java
@FeignClient(name = "xxlJobClient", url = "http://192.168.1.xxx:8080/xxl-job-admin")
public interface XxlJobFeignClient {
/**
* 登錄接口,必須先調(diào)用獲取 Cookie 才能訪問其它接口
*/
@PostMapping(value = "/login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
Response login(@RequestHeader("Content-Type") String contentType,
@RequestParam("userName") String userName,
@RequestParam("password") String password);
/**
* 新建任務(wù)接口
*/
@PostMapping("/jobinfo/add")
ResultModel addJob(@RequestHeader("Cookie") String cookie,
@RequestBody Map<String, Object> jobInfo);
/**
* 更新任務(wù)接口
*/
@PostMapping("/jobinfo/update")
ResultModel updateJob(@RequestHeader("Cookie") String cookie,
@RequestBody Map<String, Object> jobInfo);
/**
* 刪除任務(wù)接口
*/
@PostMapping("/jobinfo/remove")
ResultModel removeJob(@RequestHeader("Cookie") String cookie,
@RequestParam("id") Integer jobId);
/**
* 啟動任務(wù)接口
*/
@PostMapping("/jobinfo/start")
ResultModel startJob(@RequestHeader("Cookie") String cookie,
@RequestParam("id") Integer jobId);
/**
* 暫停任務(wù)接口
*/
@PostMapping("/jobinfo/stop")
ResultModel stopJob(@RequestHeader("Cookie") String cookie,
@RequestParam("id") Integer jobId);
/**
* 查執(zhí)行器列表接口
* @param cookie
* @param start
* @param length
* @return
*/
@GetMapping("/jobgroup/pageList")
Map<String, Object> getJobGroups(@RequestHeader("Cookie") String cookie,
@RequestParam("start") int start,
@RequestParam("length") int length);
/**
* 獲取任務(wù)列表
* @param cookie 登錄時獲得的 Cookie
* @param params 請求參數(shù)
* @return 任務(wù)列表
*/
@PostMapping("/jobinfo/pageList")
ResultModel getJobList(@RequestHeader("Cookie") String cookie, @RequestParam Map<String, Object> params);
/**
* 查詢?nèi)罩?
* @param cookie
* @param params
* @return
*/
@PostMapping("/joblog/pageList")
ResultModel getJobLogs(@RequestHeader("Cookie") String cookie, @RequestBody MultiValueMap<String, String> params);
}以上就是SpringBoot集成XXL-JOB實現(xiàn)任務(wù)管理全流程的詳細內(nèi)容,更多關(guān)于SpringBoot XXL-JOB任務(wù)管理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決tomcat發(fā)布工程后,WEB-INF/classes下文件不編譯的問題
Springboot集成Springbrick實現(xiàn)動態(tài)插件的步驟詳解

