springboot整合xxl-job,通过代码进行调度中心注册开启任务等
背景:
由于工作需要,当用户在登录时自动触发定时任务。而不需要我们手动到调度中心管理页面去创建任务。
工程介绍:
分为两个项目,第一个是调度中心的项目(xxl-job-admin)。第二个是我们自己的项目(myProject)。
步骤如下:
调度中心操作步骤
1.下载xxl-job的源码
点击进入xxl-job项目官网地址
源码下载地址-github
源码下载地址-gitee
1.1、gitee为例,下载2.4.0版本。
1.2、下载代码压缩包
1.3、下载完成,解压压缩包目录展示
1.4、数据库建表,打开doc文件夹,里面有sql文件。到数据库执行就可以创建xxl-job项目所需要的表了。
1.5、打开xxl-job-admin
项目(我这里使用的是idea工具)
展开目录如下:
1.6、更新配置(主要两个配置:1.端口默认8080(也可以自定义)2.数据库配置))。报红地方不影响代码运行,可以不用管。
1.7、启动项目访问调度中心,访问地址:http://localhost:8080/xxl-job-admin,默认用户名:admin,默认密码:123456
a.启动日志:
b.登录页面:
c.登录进入首页
进入到以上页面就说明调度中心启动没有问题了,接下来就是改造调度中心为我们所用。
1.8、改造项目
1.8.0、任务组控制器添加新接口用于查找执行器(执行器的意思是,执行任务时用哪个执行器执行,必须要指定)。
a.进入JobGroupController,添加以下代码
代码如下:
@RequestMapping("/loadByAppName")@ResponseBody@PermissionLimit(limit = false)public ReturnT<XxlJobGroup> loadByAppName(String param) {LoadByAppNameParam loadByAppNameParam = GsonTool.fromJson(param, LoadByAppNameParam.class);String appName = loadByAppNameParam.getAppName();XxlJobGroup jobGroup = xxlJobGroupDao.loadByAppName(appName);try {if (null != jobGroup) {return new ReturnT<XxlJobGroup>(jobGroup);} else {return new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);}} catch (Exception e) {e.printStackTrace();}return null;}
注:
@PermissionLimit(limit = false)注解的含义是跳过登录验证
b.进入XxlJobGroupDao文件添加如下代码
代码如下:
XxlJobGroup loadByAppName(@Param("name") String name);
c.进入XxlJobGroupMapper.xml文件添加如下代码
代码如下:
<select id="loadByAppName" parameterType="java.lang.String" resultMap="XxlJobGroup">SELECT<include refid="Base_Column_List"/>FROM xxl_job_group AS tWHERE t.app_name = #{name}</select>
d.LoadByAppNameParam.java文件是我自定义文件,用来接受appName参数的,后面会讲到。
代码如下:
public class LoadByAppNameParam {private String appName;public String getAppName() {return appName;}public void setAppName(String appName) {this.appName = appName;}}
e.测试,我在调度管理中创建了一个默认执行器,用postman调用接口测试,查看返回数据。注意:后面我还是用xxl-job自带的执行器来演示
我设置的本地ip地址,不填的话默认是当前主机的ip
postman测试接口,查找名为“xxl-job-executor-sample”的执行器。
1.8.1、在JobInfoController.java中添加两个接口
代码如下:
@RequestMapping("/addJob")@ResponseBody@PermissionLimit(limit = false)public ReturnT<String> addJob(String param) {System.out.println(param);XxlJobInfo xxlJobInfo = GsonTool.fromJson(param, XxlJobInfo.class);return xxlJobService.add(xxlJobInfo);}@RequestMapping("/removeJob")@ResponseBody@PermissionLimit(limit = false)public ReturnT<String> removeJob(String id) {return xxlJobService.remove(Integer.parseInt(id));}
这两个接口后面在代码里测试这里就不再演示了。
我们自己项目的操作步骤
1.创建SpringBoot工程(SpringBoot版本2.5.6,jdk版本为1.8,xxl-job-core依赖为2.4.0,lombok插件有使用到,hutool工具包5.5.0,阿里巴巴fastjson)
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.abliner</groupId><artifactId>myProject</artifactId><version>0.0.1-SNAPSHOT</version><name>myProject</name><description>myProject</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- xxl-job-core依赖 --><!-- https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core --><dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.0</version></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- hutool工具依赖 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-json</artifactId><version>5.5.0</version></dependency><!-- JSON转换工具 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.11</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
1.0、配置文件application.yml(配置文件默认是application.properties,我喜欢另一种风格所以改成了application.yml。指定启动端口为:8081)
代码如下:
server:port: 8081# Xxl-Job分布式定时任务调度中心
xxl:job:### 执行器通讯TOKEN [选填]:非空时启用;accessToken: default_tokenadmin:### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;addresses: http://127.0.0.1:8080/xxl-job-adminexecutor:### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。address:### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册appname: xxl-job-executor-sample### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";ip:### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;port: 9999### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;logpath: /data/applogs/xxl-job/jobhandler### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;logretentiondays: 30
注意:
配置调度中心的地址addresses,我这里用的默认的地址:http://127.0.0.1:8080/xxl-job-admin,如调度中心端口更改,那么我们自己项目里的端口也需要更新。accessToken也是一样,要与调度中心配置保持一致。
1.1、创建配置
1.1.0、创建xxl的配置(没有目录的新建目录,我这里新建了configure和xxl两个目录)
注意:
XxlJobConfig.java中忘记加“@Configuration注解”,导致调度中心注册失败,日志提示如下图:
代码演示:
完整代码如下:
package com.abliner.myproject.configure.xxl;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;/*** @author* @date 2023/12/11 14:58* @describe*/@Configuration
public class XxlJobConfig {private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.accessToken}")private String accessToken;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.address}")private String address;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setAddress(address);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;}/*** 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;** 1、引入依赖:* <dependency>* <groupId>org.springframework.cloud</groupId>* <artifactId>spring-cloud-commons</artifactId>* <version>${version}</version>* </dependency>** 2、配置文件,或者容器启动变量* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'** 3、获取IP* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();*/}
1.1.1、创建RestTemplateConfig.java用于网络请求的配置
完整代码如下:
package com.abliner.myproject.configure;import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;import java.util.ArrayList;
import java.util.List;/*** @author* @date 2023/12/11 16:19* @describe*/
@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate(RestTemplateBuilder builder) {//先获取到converter列表List<HttpMessageConverter<?>> converters = builder.build().getMessageConverters();for (HttpMessageConverter<?> converter : converters) {//因为我们只想要jsonConverter支持对text/html的解析if (converter instanceof MappingJackson2HttpMessageConverter) {try {//先将原先支持的MediaType列表拷出List<MediaType> mediaTypeList = new ArrayList<>(converter.getSupportedMediaTypes());//加入对text/html的支持mediaTypeList.add(MediaType.TEXT_PLAIN);//将已经加入了text/html的MediaType支持列表设置为其支持的媒体类型列表((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(mediaTypeList);} catch (Exception e) {e.printStackTrace();}}}return builder.build();}
}
1.2、创建XxlJobInfo.java(没有目录的新建目录,我这里新建了model目录。这个对象后面会使用到)
完整代码如下:
package com.abliner.myproject.model;import java.util.Date;/*** @author* @date 2023/12/11 15:14* @describe*/
public class XxlJobInfo {private int id; // 主键IDprivate int jobGroup; // 执行器主键IDprivate String jobDesc;private Date addTime;private Date updateTime;private String author; // 负责人private String alarmEmail; // 报警邮件private String scheduleType; // 调度类型private String scheduleConf; // 调度配置,值含义取决于调度类型private String misfireStrategy; // 调度过期策略private String executorRouteStrategy; // 执行器路由策略private String executorHandler; // 执行器,任务Handler名称private String executorParam; // 执行器,任务参数private String executorBlockStrategy; // 阻塞处理策略private int executorTimeout; // 任务执行超时时间,单位秒private int executorFailRetryCount; // 失败重试次数private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnumprivate String glueSource; // GLUE源代码private String glueRemark; // GLUE备注private Date glueUpdatetime; // GLUE更新时间private String childJobId; // 子任务ID,多个逗号分隔private int triggerStatus; // 调度状态:0-停止,1-运行private long triggerLastTime; // 上次调度时间private long triggerNextTime; // 下次调度时间public int getId() {return id;}public void setId(int id) {this.id = id;}public int getJobGroup() {return jobGroup;}public void setJobGroup(int jobGroup) {this.jobGroup = jobGroup;}public String getJobDesc() {return jobDesc;}public void setJobDesc(String jobDesc) {this.jobDesc = jobDesc;}public Date getAddTime() {return addTime;}public void setAddTime(Date addTime) {this.addTime = addTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getAlarmEmail() {return alarmEmail;}public void setAlarmEmail(String alarmEmail) {this.alarmEmail = alarmEmail;}public String getScheduleType() {return scheduleType;}public void setScheduleType(String scheduleType) {this.scheduleType = scheduleType;}public String getScheduleConf() {return scheduleConf;}public void setScheduleConf(String scheduleConf) {this.scheduleConf = scheduleConf;}public String getMisfireStrategy() {return misfireStrategy;}public void setMisfireStrategy(String misfireStrategy) {this.misfireStrategy = misfireStrategy;}public String getExecutorRouteStrategy() {return executorRouteStrategy;}public void setExecutorRouteStrategy(String executorRouteStrategy) {this.executorRouteStrategy = executorRouteStrategy;}public String getExecutorHandler() {return executorHandler;}public void setExecutorHandler(String executorHandler) {this.executorHandler = executorHandler;}public String getExecutorParam() {return executorParam;}public void setExecutorParam(String executorParam) {this.executorParam = executorParam;}public String getExecutorBlockStrategy() {return executorBlockStrategy;}public void setExecutorBlockStrategy(String executorBlockStrategy) {this.executorBlockStrategy = executorBlockStrategy;}public int getExecutorTimeout() {return executorTimeout;}public void setExecutorTimeout(int executorTimeout) {this.executorTimeout = executorTimeout;}public int getExecutorFailRetryCount() {return executorFailRetryCount;}public void setExecutorFailRetryCount(int executorFailRetryCount) {this.executorFailRetryCount = executorFailRetryCount;}public String getGlueType() {return glueType;}public void setGlueType(String glueType) {this.glueType = glueType;}public String getGlueSource() {return glueSource;}public void setGlueSource(String glueSource) {this.glueSource = glueSource;}public String getGlueRemark() {return glueRemark;}public void setGlueRemark(String glueRemark) {this.glueRemark = glueRemark;}public Date getGlueUpdatetime() {return glueUpdatetime;}public void setGlueUpdatetime(Date glueUpdatetime) {this.glueUpdatetime = glueUpdatetime;}public String getChildJobId() {return childJobId;}public void setChildJobId(String childJobId) {this.childJobId = childJobId;}public int getTriggerStatus() {return triggerStatus;}public void setTriggerStatus(int triggerStatus) {this.triggerStatus = triggerStatus;}public long getTriggerLastTime() {return triggerLastTime;}public void setTriggerLastTime(long triggerLastTime) {this.triggerLastTime = triggerLastTime;}public long getTriggerNextTime() {return triggerNextTime;}public void setTriggerNextTime(long triggerNextTime) {this.triggerNextTime = triggerNextTime;}
}
1.3、添加XxlUtil.java工具类,我们要远程调用调度中心需要用到(我这里新建了tool目录)
完整代码如下:
package com.abliner.myproject.tool;import cn.hutool.json.JSONUtil;
import com.abliner.myproject.model.XxlJobInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;import java.util.HashMap;
import java.util.Map;/*** @author* @date 2023/12/11 15:22* @describe*/
@Component
@RequiredArgsConstructor
public class XxlUtil {@Value("${xxl.job.admin.addresses}")private String xxlJobAdminAddress;private final RestTemplate restTemplate;// xxl-job各种请求地址private static final String ADD_INFO_URL = "/jobinfo/addJob";private static final String REMOVE_INFO_URL = "/jobinfo/removeJob";private static final String GET_GROUP_ID = "/jobgroup/loadByAppName";/*** 添加任务** @param xxlJobInfo* @param appName* @return*/public String addJob(XxlJobInfo xxlJobInfo, String appName) {//组装参数Map<String, Object> params = new HashMap<>();params.put("appName", appName);String json = JSONUtil.toJsonStr(params);//调用xxl-job接口添加任务String result = doPost(xxlJobAdminAddress + GET_GROUP_ID, json);//获取执行器的idJSONObject jsonObject = JSON.parseObject(result);Map<String, Object> map = (Map<String, Object>) jsonObject.get("content");Integer groupId = (Integer) map.get("id");xxlJobInfo.setJobGroup(groupId);String xxlJobInfoJson = JSONUtil.toJsonStr(xxlJobInfo);//添加这个jobreturn doPost(xxlJobAdminAddress + ADD_INFO_URL, xxlJobInfoJson);}// 删除jobpublic String removeJob(long jobId) {MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();map.add("id", String.valueOf(jobId));return doPostWithFormData(xxlJobAdminAddress + REMOVE_INFO_URL, map);}/*** 远程调用** @param url* @param json*/private String doPost(String url, String json) {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();map.add("param", json);HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, entity, String.class);return responseEntity.getBody();}private String doPostWithFormData(String url, MultiValueMap<String, String> map) {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, entity, String.class);return responseEntity.getBody();}}
1.4、编写XxlService.java(注意新建service和impl目录)
完整代码如下:
package com.abliner.myproject.service.impl;import com.abliner.myproject.model.XxlJobInfo;
import com.abliner.myproject.tool.XxlUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;/*** @author* @date 2023/12/11 15:43* @describe*/
@Service
@Slf4j
@RequiredArgsConstructor
public class XxlService {private final XxlUtil xxlUtil;@Value("${xxl.job.executor.appname}")private String appName;public void addJob(XxlJobInfo xxlJobInfo) {xxlUtil.addJob(xxlJobInfo, appName);log.info("任务已添加");}}
1.5、新建时间转换工具类DateUtils.java
完整代码如下:
package com.abliner.myproject.tool;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;/*** @author* @date 2023/12/11 15:56* @describe*/
public class DateUtils {// 使用 DateTimeFormatter 格式化时间public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd HH mm ss");/*** 时间转换Cron表达式** @param dateTime* @return Cron表达式* @author*/public static String getCron(LocalDateTime dateTime) {String formattedDateTime = dateTime.format(formatter);String[] dateTimeParts = formattedDateTime.split(" ");String cron = String.format("%s %s %s %s %s ? %s-%s", dateTimeParts[5], dateTimeParts[4], dateTimeParts[3], dateTimeParts[2], dateTimeParts[1], dateTimeParts[0], dateTimeParts[0]);return cron;}}
1.6、模拟登录请求
1.6.0、controlelr层->LoginController.java
完整代码如下:
package com.abliner.myproject.controller;import com.abliner.myproject.service.LoginService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @author* @date 2023/12/11 15:40* @describe*/
@RestController
@RequestMapping("server")
public class LoginController {@Resourceprivate LoginService loginService;@GetMapping("/login")public String login(@RequestParam("name") String name,@RequestParam("password") String password) {loginService.login(name, password);return "登录成功";}}
1.6.2、service层->LoginService.java
完整代码如下:
package com.abliner.myproject.service;/*** @author* @date 2023/12/11 15:48* @describe*/
public interface LoginService {/*** 登录** @param name* @param password* */void login(String name,String password);}
1.6.3、service实现层->LoginServiceImpl.java
完整代码如下:
package com.abliner.myproject.service.impl;import com.abliner.myproject.model.XxlJobInfo;
import com.abliner.myproject.service.LoginService;
import com.abliner.myproject.tool.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import javax.annotation.Resource;
import java.time.LocalDateTime;/*** @author * @date 2023/12/11 15:51* @describe*/
@Service
public class LoginServiceImpl implements LoginService {@Resourceprivate XxlService xxlService;/*** 登录** @param name* @param password*/@Overridepublic void login(String name, String password) {if (!StringUtils.isEmpty(password)) {if ("123456".equals(password)) {// 登录成功// 创建一个1分钟后向用户问好的任务LocalDateTime scheduleTime = LocalDateTime.now().plusMinutes(1L);XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setJobDesc("定时给用户发送通知");xxlJobInfo.setAuthor("imHJ");xxlJobInfo.setScheduleType("CRON");xxlJobInfo.setScheduleConf(DateUtils.getCron(scheduleTime));xxlJobInfo.setGlueType("BEAN");xxlJobInfo.setExecutorHandler("sayHelloHandler");xxlJobInfo.setExecutorParam(name);xxlJobInfo.setMisfireStrategy("DO_NOTHING");xxlJobInfo.setExecutorRouteStrategy("FIRST");xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");xxlJobInfo.setTriggerStatus(1);//将任务提交到xxl-job-adminxxlService.addJob(xxlJobInfo);}}}
}
1.6.4、新建JobHandler.java执行器,用于处理任务(定时任务执行的具体业务)
完整代码如下:
package com.abliner.myproject.handler;import com.abliner.myproject.tool.XxlUtil;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;/*** @author* @date 2023/12/11 16:05* @describe*/
@Component
@Slf4j
public class JobHandler {private final XxlUtil xxlUtil;public JobHandler(XxlUtil xxlUtil) {this.xxlUtil = xxlUtil;}@XxlJob(value = "sayHelloHandler")public void execute() {String userName = XxlJobHelper.getJobParam();log.info("欢迎您: {}!", userName);// 避免一次性任务,留在界面,这里手动删除处理掉long jobId = XxlJobHelper.getJobId();xxlUtil.removeJob(jobId);}}
以上是全部代码的编写,最后测试,还是用postman来测试。
A.postman展示
B.调度中心展示
C.idea控制台展示
最后整个流程执行完成。
相关文章:

springboot整合xxl-job,通过代码进行调度中心注册开启任务等
背景:由于工作需要,当用户在登录时自动触发定时任务。而不需要我们手动到调度中心管理页面去创建任务。 工程介绍:分为两个项目,第一个是调度中心的项目(xxl-job-admin)。第二个是我们自己的项目࿰…...

k8s集群部分使用gpu资源的pod出现UnexpectedAdmissionError问题
记录一次排查UnexpectedAdmissionError问题的过程 1. 问题 环境 3master节点N个GPU节点 kubelet版本:v1.19.4 kubernetes版本:v1.19.4 生产环境K8S集群,莫名其妙的出现大量UnexpectedAdmissionError状态的Pod,导致部分任务执…...

自定义 el-select 和 el-input 样式
文章目录 需求分析el-select 样式el-input 样式el-table 样式 需求 自定义 选择框的下拉框的样式和输入框 分析 el-select 样式 .select_box{// 默认placeholder:deep .el-input__inner::placeholder {font-size: 14px;font-weight: 500;color: #3E534F;}// 默认框状态样式更…...
解决本地centos虚拟机重启,自动变换 ip 地址的问题
修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 原配置: TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"dhcp" DEFROUTE"yes" IPV4_FAILURE_FATAL"no" IPV6INI…...
pt36项目短信OAth2.0
5、短信验证码 1、注册容联云账号,登录并查看开发文档(以下分析来自接口文档) 2、开发文档【准备1】:请求URL地址1.示例:https://app.cloopen.com:8883/2013-12-26/Accounts/{}/SMS/TemplateSMS?sig{}ACCOUNT SID# s…...

教师们如何一对一私发成绩?
在传统的教育中,老师通常会通过班级群或家长会等方式发布学生的成绩信息。然而,这种公开的方式可能会让一些学生感到尴尬和不安,因为他们可能不愿意让其他人知道他们的成绩情况。为了解决这个问题,今天我就给老师们推荐一款免费的…...

12.11
1.q,w,e亮led1,2,3; a,s,d灭led1,2,3; main.c #include "uar1.h"#include "led.h"void delay(int ms){int i,j;for(i0;i<ms;i){for…...
Spring JdbcTemplate
一、简介 Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作。它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装。spring 框架为我们提供了很多的操作模板类。 针对操作关系型数据: jdbcTemplateHibe…...

力扣编程题算法初阶之双指针算法+代码分析
目录 第一题:复写零 第二题:快乐数: 第三题:盛水最多的容器 第四题:有效三角形的个数 第一题:复写零 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 思路: 上期…...

实现安装“自由化”!在Windows 11中如何绕过“您尝试安装的应用程序未通过微软验证”
这篇文章描述了如果你不能安装应用程序,而是当你在Windows 11中看到消息“您尝试安装的应用程序未通过微软验证”时该怎么办。完成这些步骤将取消你安装的应用程序必须经过Microsoft验证的要求。 使用设置应用程序 “设置”应用程序提供了绕过此警告消息的最简单方法,以便你…...

【mysql】下一行减去上一行数据、自增序列场景应用
背景 想获取if_yc为1连续账期数据 思路 获取所有if_yc为1的账期数据下一行减去上一行账期,如果为1则为连续,不等于1就为断档获取不等于1的最小账期,就是离当前账期最近连续账期 代码 以下为mysql语法: select acct_month f…...

CLIP在Github上的使用教程
CLIP的github链接:https://github.com/openai/CLIP CLIP Blog,Paper,Model Card,Colab CLIP(对比语言-图像预训练)是一个在各种(图像、文本)对上进行训练的神经网络。可以用自然语…...

入职字节外包一个月,我离职了。。。
有一种打工人的羡慕,叫做“大厂”。 真是年少不知大厂香,错把青春插稻秧。 但是,在深圳有一群比大厂员工更庞大的群体,他们顶着大厂的“名”,做着大厂的工作,还可以享受大厂的伙食,却没有大厂…...
SpringBoot的web开发
与其明天开始,不如现在行动! 文章目录 web开发1 web场景1.1 自动配置1.2 默认效果 💎总结 web开发 SpringBoot的web开发能力是由SpringMVC提供的 1 web场景 1.1 自动配置 整合web场景 <dependency><groupId>org.springframewo…...
传染病传播速度
题干 R0值是基本传染数的简称,指的是在没有采取任何干预措施的情况下,平均每位感染者在传染期内使易感者个体致病的数量。数字越大说明传播能力越强,控制难度越大。一个人传染的人的数量可以用幂运算来计算。假设奥密克戎的R0为10࿰…...

前端打包环境配置步骤
获取node安装包并解压 获取node安装包 wget https://npmmirror.com/mirrors/node/v16.14.0/node-v16.14.0-linux-x64.tar.xz 解压 tar -xvf node-v16.14.0-linux-x64.tar.xz 创建软链接 sudo ln -s 此文件夹的绝对路径/bin/node /usr/local/bin/node,具体执行如下…...
css的4种引入方式--内联样式(标签内style)、内部样式表(<style>)、外部样式表(<link>、@import)
1.内联样式(Inline Styles):可以直接在HTML元素的style属性中定义CSS样式。 例如: <p style"color: red; font-size: 16px;">这是一段红色的文本</p>内联样式适用于对单个元素应用特定的样式,…...

GPT-4 变懒了?官方回复
你是否注意到,最近使用 ChatGPT 的时候,当你向它提出一些问题,却得到的回应似乎变得简短而敷衍了?对于这一现象,ChatGPT 官方给出了回应。 译文:我们听到了你们所有关于 GPT4 变得更懒的反馈!我…...
编译器和 IR:LLVM IR、SPIR-V 和 MLIR
编译器通常是各种开发工具链中的关键组件,可提高开发人员的工作效率。编译器通常用作独立的黑匣子,它使用高级源程序并生成语义上等效的低级源程序。不过,它仍然是内部结构倾向的;内部之间流动的内容就称为中间表示 (IR࿰…...

蓝牙物联网对接技术难点有哪些?
#物联网# 蓝牙物联网对接技术难点主要包括以下几个方面: 1、设备兼容性:蓝牙技术有多种版本和规格,如蓝牙4.0、蓝牙5.0等,不同版本之间的兼容性可能存在问题。同时,不同厂商生产的蓝牙设备也可能存在兼容性问题。 2、…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...