当前位置: 首页 > news >正文

Springboot 使用quartz 定时任务 增删改查

在这里插入图片描述

前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 ,浏览量还不错 ,

  • Springboot 整合定时任务 )

所以就准备写第二篇, 如果你是一名Java工程师,你也可以会看到如下的页面 ,去添加定时任务

定时任务展示 :
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

很显然他们只是披着不同的皮而已,本质上都是定时任务 , 也就是将所有的任务数据 交给了 Spring 进行管理 ,最后 将 任务Job信息 ,以及 参数传递的信息 对外进行暴露 cron 的输入值 ,然后交给数据库去进行 传参 这里我们来演示下 上面做到流程

环境搭建

  1. 我们需要配置一个任务

这玩意 简单说 就是你要做什么事情 ,然后你要做这件事,你需要 用到定时任务, 所有 你就得 去实现人家第三方的库 ,这里我们用 quartz , 当然类似的还有很多很多,只是为了方便演示

   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency>

在第一次使用之前首先我们需要生成一下quartz 自带默认的表 ,大概会生成11 张的样子

  • 把yaml配置文件中的 initialize-schema: always 配置的 always 属性意思是:

  • 每次初始化都会重新生成表(执行一次删除,执行一次创建),生成后,可以修改为 never

  • 修改下列初始化结构的 yaml 属性 : initialize-schema:

    • always : 重复生成 ,你每次 都会重新生成
    • never: 不生成

所以你第一次可以用 always ,后面你就改成 never 就行了

spring:## quartz定时任务,采用数据库方式quartz:job-store-type: jdbcinitialize-schema: embedded#定时任务启动开关,true-开  false-关auto-startup: true#延迟1秒启动定时任务startup-delay: 1s#启动时更新己存在的Joboverwrite-existing-jobs: trueproperties:org:quartz:scheduler:instanceName: MySchedulerinstanceId: AUTOjobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: QRTZ_isClustered: falsemisfireThreshold: 12000clusterCheckinInterval: 15000threadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true

在这里插入图片描述

如果你不想自己去生成也可以去执行这个包下面的sql
在这里插入图片描述
在这里插入图片描述

我们在创建一张业务的表,方便待会弄增删改查

创建SQL


CREATE TABLE `sys_quartz_job` (`id` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,`create_by` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '创建人',`create_at` datetime DEFAULT NULL COMMENT '创建时间',`del_flag` int DEFAULT NULL COMMENT '删除状态',`update_by` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '修改人',`update_at` datetime DEFAULT NULL COMMENT '修改时间',`job_class_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '任务类名',`cron_expression` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT 'cron表达式',`parameter` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '参数',`meeting_record_id` int DEFAULT NULL COMMENT '会议室记录id',`description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '描述',`status` int DEFAULT NULL COMMENT '状态 0正常 -1停止',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;

加上这张表,我们就有了12 张表, 其他都是 框架自带的,一张我们自己生成的

编写MVC 代码

首先写一个类 ,你继承了人家quartz 的Job就可以用人家的功能,就这么简单,然后你已经有了一个任务了

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class QuartzDemoJob implements Job {static int i = 0;@Autowiredprivate QuartzDemoService quartzDemoService;public QuartzDemoJob() {}@Autowired   //这里不能直接注入,因为@Autowired注入是Spring的注入,要求注入对象与被注入对象都是在SpringIOC容器中存在,public QuartzDemoJob(QuartzDemoService quartzDemoService) {this.quartzDemoService = quartzDemoService;}@Transactional@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {// 编写 service 逻辑}public static String dateToStr(java.util.Date date, String strFormat) {SimpleDateFormat sf = new SimpleDateFormat(strFormat);return sf.format(date);}public static Date strToSqlDate(String strDate, String dateFormat) {SimpleDateFormat sf = new SimpleDateFormat(dateFormat);Date date = null;try {date = sf.parse(strDate);} catch (ParseException e) {e.printStackTrace();}return new Date(date != null ? date.getTime() : 0);}
}

你有了这个任务之后 ,你现在需要 交给Spring 进行管理 ,所以你需要搞个配置 ,这你看了我上篇文章 就明白了 吧
首先我们简单点 ,Job就是任务 说人话就是你要做的事 ,你把你要做的事写了个类,然后给Spring 进行管理 配置一下, 所以我们现在把 Job弄到配置类里面去

@Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();//关联我们自己的Job类factoryBean.setJobClass(QuartzDemoJob.class);  //QuartzDemoJob的实例化并没有经过Spring的处理,// Spring的注入是要求注入的对象和被注入的对象都要在Spring的IOC容器中return factoryBean;}

完整 代码 :


@Configuration
public class QuartzCoreConfig {/*** 1、创建Job对象*/@Beanpublic JobDetailFactoryBean jobDetailFactoryBean(){JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();//关联我们自己的Job类factoryBean.setJobClass(QuartzDemoJob.class);  //QuartzDemoJob的实例化并没有经过Spring的处理,// Spring的注入是要求注入的对象和被注入的对象都要在Spring的IOC容器中return factoryBean;}/*** 2、创建Trigger对象* Cron Trigger*/@Beanpublic CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){CronTriggerFactoryBean factoryBean=new CronTriggerFactoryBean();//关联JobDetail对象factoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));//设置触发时间factoryBean.setCronExpression("0/2 * * * * ?");  //每2秒触发一次, 分钟,小时,天,月,星期
//        factoryBean.setCronExpression("0 0-59 0-22 * * ?");  //在每天0-22点期间的每1分钟触发return factoryBean;}/*** 3、创建Scheduler*/@Beanpublic SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyadaptableJobFactory myadaptableJobFactory){SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();//关联triggerfactoryBean.setTriggers(cronTriggerFactoryBean.getObject());factoryBean.setJobFactory(myadaptableJobFactory);  //调用myadaptableJobFactory把对象注入到SpringIOC容器中return factoryBean;}
}

上面的流程图大概说下关联
在这里插入图片描述

SchedulerFactoryBean : 就是调度器的意思
CronTriggerFactoryBean : 就是 触发器的意思
JobDetailFactoryBean : 定时任务

在自己搞个工厂 将 quartz 手动创建一个实例


/*** 2. 编写工厂模式  加载进Spring*/
@Component("myadaptableJobFactory")  //将该类实例化,使得可以直接用
public class MyadaptableJobFactory extends AdaptableJobFactory {//AutowireCapableBeanFactory可以将一个对象添加到Spring IOC容器中,并且完成该对象注入@Autowiredprivate AutowireCapableBeanFactory autowireCapableBeanFactory;//该方法将实例化的任务对象手动的添加到SpringIOC容器中并且完成对象的注入@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object object = super.createJobInstance(bundle);//将object对象添加到Spring IOC容器中并完成注入this.autowireCapableBeanFactory.autowireBean(object);return object;}
}

上面我们做了三部

  1. 配置一个任务
  2. 将任务加载进行了Spring
  3. 创建了个工厂,自己注入

接下来完成三层 架构 MVC,搞个Controller ,只是提供思路,自己把他写完哈


@RestController
@RequestMapping("/sys/quartzJob")
@Slf4j
@Api(tags = "定时任务接口")
public class QuartzJobController {@Autowiredprivate IQuartzJobService quartzJobService;@Autowiredprivate Scheduler scheduler;/*** 分页列表查询** @param quartzJob* @param pageNo* @param pageSize* @param req* @return*/@RequestMapping(value = "/list", method = RequestMethod.GET)public Result<?> queryPageList(QuartzJob quartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {QueryWrapper<QuartzJob> queryWrapper = new QueryWrapper<>();queryWrapper.select("");Page<QuartzJob> page = new Page<QuartzJob>(pageNo, pageSize);IPage<QuartzJob> pageList = quartzJobService.page(page, queryWrapper);return Result.ok(pageList);}/*** 添加定时任务** @param quartzJob* @return*///@RequiresRoles("admin")@RequestMapping(value = "/add", method = RequestMethod.POST)public Result<?> add(@RequestBody QuartzJob quartzJob) {quartzJobService.saveAndScheduleJob(quartzJob);return Result.ok("创建定时任务成功");}/*** 更新定时任务** @param quartzJob* @return*///@RequiresRoles("admin")@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})public Result<?> eidt(@RequestBody QuartzJob quartzJob) {try {quartzJobService.editAndScheduleJob(quartzJob);} catch (SchedulerException e) {log.error(e.getMessage(), e);return Result.error("更新定时任务失败!");}return Result.ok("更新定时任务成功!");}/*** 通过id删除** @param id* @return*///@RequiresRoles("admin")@RequestMapping(value = "/delete", method = RequestMethod.DELETE)public Result<?> delete(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);if (quartzJob == null) {return Result.error("未找到对应实体");}quartzJobService.deleteAndStopJob(id);return Result.ok("删除成功!");}/*** 批量删除** @param ids* @return*///@RequiresRoles("admin")@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {if (ids == null || "".equals(ids.trim())) {return Result.error("参数不识别!");}for (String id : Arrays.asList(ids.split(""))) {QuartzJob job = quartzJobService.getById(id);quartzJobService.deleteAndStopJob(id);}return Result.ok("删除定时任务成功!");}/*** 暂停定时任务** @param id* @return*///@RequiresRoles("admin")@GetMapping(value = "/pause")@ApiOperation(value = "停止定时任务")public Result<Object> pauseJob(@RequestParam(name = "id") String id) {QuartzJob job = quartzJobService.getById(id);if (job == null) {return Result.error("定时任务不存在!");}quartzJobService.pause(job);return Result.ok("停止定时任务成功");}/*** 启动定时任务** @param id* @return*///@RequiresRoles("admin")@GetMapping(value = "/resume")@ApiOperation(value = "启动定时任务")public Result<Object> resumeJob(@RequestParam(name = "id") String id) {QuartzJob job = quartzJobService.getById(id);if (job == null) {return Result.error("定时任务不存在!");}quartzJobService.resumeJob(job);//scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));return Result.ok("启动定时任务成功");}/*** 通过id查询** @param id* @return*/@RequestMapping(value = "/queryById", method = RequestMethod.GET)public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);return Result.ok(quartzJob);}/*** 导出excel** @param request* @param quartzJob*/@RequestMapping(value = "/exportXls")public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {// Step.1 组装查询条件
//        QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
//        // Step.2 AutoPoi 导出Excel
//        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
//        List<QuartzJob> pageList = quartzJobService.list(queryWrapper);
//        // 导出文件名称
//        mv.addObject(NormalExcelConstants.FILE_NAME, "定时任务列表");
//        mv.addObject(NormalExcelConstants.CLASS, QuartzJob.class);
//        //获取当前登录用户
//        //update-begin---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------
//        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("定时任务列表数据", "导出人:" + user.getRealname(), "导出信息"));
//        //update-end---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------
//        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);return null;}/*** 通过excel导入数据** @param request* @param response* @return*/@RequestMapping(value = "/importExcel", method = RequestMethod.POST)public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 错误信息
        List<String> errorMessage = new ArrayList<>();
        int successLines = 0, errorLines = 0;
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获取上传文件对象
            MultipartFile file = entity.getValue();
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<QuartzJob> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);
                //add-begin-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
                for (QuartzJob job : listQuartzJobs) {
                    job.setStatus(CommonConstant.STATUS_DISABLE);
                }
                List<String> list = ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage, CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);
                //add-end-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
                errorLines += list.size();
                successLines += (listQuartzJobs.size() - errorLines);
//            } catch (Exception e) {
//                log.error(e.getMessage(), e);
//                return Result.error("文件导入失败!");
//            } finally {
//                try {
//                    file.getInputStream().close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }return Result.ok("");}/*** 立即执行** @param id* @return*///@RequiresRoles("admin")@GetMapping("/execute")public Result<?> execute(@RequestParam(name = "id", required = true) String id) {QuartzJob quartzJob = quartzJobService.getById(id);if (quartzJob == null) {return Result.error("未找到对应实体");}try {quartzJobService.execute(quartzJob);} catch (Exception e) {//e.printStackTrace();log.info("定时任务 立即执行失败>>" + e.getMessage());return Result.error("执行失败!");}return Result.ok("执行成功!");}}

@Data
@TableName("sys_quartz_job")
public class QuartzJob implements Serializable {private static final long serialVersionUID = 1L;/*** id*/@TableId(type = IdType.ASSIGN_ID)private java.lang.String id;/*** 创建人*/private java.lang.String createBy;/*** 创建时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")private java.util.Date createTime;/*** 删除状态*/private java.lang.Integer delFlag;/*** 修改人*/private java.lang.String updateBy;/*** 修改时间*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")private java.util.Date updateTime;/*** 任务类名*/@Excel(name = "任务类名", width = 40)private java.lang.String jobClassName;/*** cron表达式*/@Excel(name = "cron表达式", width = 30)private java.lang.String cronExpression;/*** 参数*/@Excel(name = "参数", width = 15)private java.lang.String parameter;/*** 描述*/@Excel(name = "描述", width = 40)private java.lang.String description;/*** 状态 0正常 -1停止*/@Excel(name = "状态", width = 15)private java.lang.Integer status;}```Mapper```java
@Mapper
public interface QuartzJobMapper extends BaseMapper<QuartzJob> {/*** 根据jobClassName查询* @param jobClassName 任务类名* @return*/public List<QuartzJob> findByJobClassName(@Param("jobClassName") String jobClassName);}```+ xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.schduletest.mapper.QuartzJobMapper"><!-- 根据jobClassName查询 --><select id="findByJobClassName" resultType="com.example.schduletest.entity.QuartzJob">select * from  sys_quartz_job  where job_class_name = #{jobClassName}</select>
</mapper>```+ Service ```java
package com.example.schduletest.service;import com.example.schduletest.entity.QuartzJob;
import org.quartz.SchedulerException;import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** @Description: 定时任务*/
public interface IQuartzJobService extends IService<QuartzJob> {/*** 通过类名寻找定时任务* @param jobClassName 类名* @return List<QuartzJob>*/List<QuartzJob> findByJobClassName(String jobClassName);/*** 保存定时任务* @param quartzJob* @return boolean*/boolean saveAndScheduleJob(QuartzJob quartzJob);/*** 编辑定时任务* @param quartzJob* @return boolean* @throws SchedulerException*/boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;/*** 删除定时任务* @param id* @return boolean*/boolean deleteAndStopJob(String id);/*** 恢复定时任务* @param quartzJob* @return*/boolean resumeJob(QuartzJob quartzJob);/*** 执行定时任务* @param quartzJob* @throws Exception*/void execute(QuartzJob quartzJob) throws Exception;/*** 暂停任务* @param quartzJob* @throws SchedulerException*/void pause(QuartzJob quartzJob);
}
  • 所有依赖
<?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.7.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>Schdule-Test</artifactId><version>0.0.1-SNAPSHOT</version><name>Schdule-Test</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version></properties><dependencies><!--Spring tx 坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3.1</version></dependency><!--         下一节需要用到的定时任务依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><!--         Spring 官方自带了依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-annotation</artifactId><version>4.4.0</version></dependency><dependency><groupId>me.zhengjie</groupId><artifactId>eladmin-system</artifactId><version>2.6</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • 完整yaml
server:port: 8080
spring:datasource:name: mydburl: jdbc:mysql://localhost:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverquartz:job-store-type: jdbc#定时任务启动开关,true-false-关auto-startup: true#延迟1秒启动定时任务startup-delay: 1s#启动时更新己存在的Joboverwrite-existing-jobs: trueproperties:org:quartz:scheduler:instanceName: MySchedulerinstanceId: AUTOjobStore:class: org.springframework.scheduling.quartz.LocalDataSourceJobStoredriverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegatetablePrefix: QRTZ_isClustered: falsemisfireThreshold: 12000clusterCheckinInterval: 15000threadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: truejdbc:initialize-schema: nevermybatis:mapper-locations: classpath:Mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径type-aliases-package: com.example.schduletest.entity  # 注意:对应实体类的路径

这是 本篇文章项目 结构 ,感谢大家的学习

在这里插入图片描述

  • 尾声:

终归本质来说,第三方框架, 最后集成在业务层面也大致只不过是个增删改查, 只不过 在业务层面不同而已,例如我们只是在新增的时候通过调度器创建了一个 Job

 public boolean saveAndScheduleJob(QuartzJob quartzJob) {// DB设置修改quartzJob.setDelFlag(1);boolean success = this.save(quartzJob);if (success) {if ("NORMAL".equals(quartzJob.getStatus())) {// 定时器添加this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());}}return success;}

博客项目演示层面 ,只是做了一个Demo : 更多 具体详情使用细节 ,请关注 源码实现细节

相关文章:

Springboot 使用quartz 定时任务 增删改查

前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 &#xff0c;浏览量还不错 &#xff0c; Springboot 整合定时任务 ) 所以就准备写第二篇&#xff0c; 如果你是一名Java工程师&#xff0c;你也可以会看到如下的页面 &#xff0c;去添加定时任务 定时任务展示 :…...

华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】

最近更新的博客 华为OD机试 - 热点网络统计 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 查找单入口空闲区域 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 好朋友 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 找出同班小朋友 | 备考思路,刷题要点…...

Linux常用命令汇总

1、tcpdump抓包 tcpdump这个命令是用来抓包的&#xff0c;默认情况下这个命令是没有的&#xff0c;需要安装一下&#xff1a; yum install -y tcpdump 使用这个命令的时候最好是加上你网卡的名称&#xff0c;不然可能使用不了&#xff1a; tcpdump -nn -i {网卡名称} 网卡名称…...

1.TCP、UDP区别、TCP/IP七层、四层模型、应用层协议(计网)

文章目录1.OSI 七层模型是什么&#xff1f;每一层的作用是什么&#xff1f;2.TCP/IP 四层模型是什么&#xff1f;每一层的作用是什么&#xff1f;应用层&#xff08;Application layer&#xff09;传输层&#xff08;Transport layer&#xff09;网络层&#xff08;Network lay…...

气敏电阻的原理,结构,分类及应用场景总结

🏡《总目录》 目录 1,概述2,结构3,工作原理4,分类4.1,加热方式分类4.2,材料分类4.3,氧化还原分类5,应用场景6,总结1,概述 气敏电阻是指电阻值随着环境中某种气体的浓度变化而变化的电阻,本文对其工作原理,结构,分类和应用场景进行总结。 2,结构 气敏电阻由防爆…...

实验10 拓扑排序与最短路径2022

A. DS图—图的最短路径&#xff08;无框架&#xff09;题目描述给出一个图的邻接矩阵&#xff0c;输入顶点v&#xff0c;用迪杰斯特拉算法求顶点v到其它顶点的最短路径。输入第一行输入t&#xff0c;表示有t个测试实例第二行输入顶点数n和n个顶点信息第三行起&#xff0c;每行输…...

C/C++每日一练(20230218)

目录 1. 整数转罗马数字 2. 跳跃游戏 II 3. 买卖股票的最佳时机 IV 1. 整数转罗马数字 罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X …...

【C语言】预编译

&#x1f6a9;write in front&#x1f6a9; &#x1f50e;大家好&#xff0c;我是謓泽&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f3c5;2021年度博客之星物联网与嵌入式开发TOP5&#xff5…...

音频信号处理笔记(一)

相关课程&#xff1a;【音频信号处理及深度学习教程】 文章目录01 信号的时域分析1.1 分帧1.1.1 幅值包络1.1.2 均方根能量0 信号的叠加&#xff1a;https://teropa.info/harmonics-explorer/ 一个复杂信号分解成若干简单信号分量之和。不同个频率信号的叠加: 由于和差化积&a…...

【深度学习】模型评估

上一章——多分类问题和多标签分类问题 文章目录算法诊断模型评估交叉验证测试算法诊断 如果你为问题拟合了一个假设函数&#xff0c;我们应当如何判断假设函数是否适当拟合了&#xff1f;我们可以通过观察代价函数的图像&#xff0c;当代价函数达到最低点的时候&#xff0c;此…...

AcWing《蓝桥杯集训·每日一题》—— 3777 砖块

AcWing《蓝桥杯集训每日一题》—— 3777. 砖块 文章目录AcWing《蓝桥杯集训每日一题》—— 3777. 砖块一、题目二、解题思路三、解题思路本次博客我是通过Notion软件写的&#xff0c;转md文件可能不太美观&#xff0c;大家可以去我的博客中查看&#xff1a;北天的 BLOG&#xf…...

CleanMyMac X软件下载及详细功能介绍

mac平台的知名系统清理应用CleanMyMac在经历了一段时间的测试后&#xff0c;全新设计的X正式上线。与CleanMyMac3相比&#xff0c;新版本的UI设计焕然一新&#xff0c;采用了完全不同的风格。使用Windows电脑时&#xff0c;很多人会下载各类优化软件&#xff0c;而在Mac平台中&…...

pytorch零基础实现语义分割项目(一)——数据概况及预处理

语义分割之数据加载项目列表前言数据集概况数据组织形式数据集划分数据预处理均值与方差结尾项目列表 语义分割项目&#xff08;一&#xff09;——数据概况及预处理 语义分割项目&#xff08;二&#xff09;——标签转换与数据加载 语义分割项目&#xff08;三&#xff09…...

ARM+LINUX嵌入式学习路线

嵌入式学习是一个循序渐进的过程&#xff0c;如果是希望向嵌入式软件方向发展的话&#xff0c;目前最常见的是嵌入式Linux方向&#xff0c;关注这个方向&#xff0c;大概分3个阶段&#xff1a; 1、嵌入式linux上层应用&#xff0c;包括QT的GUI开发 2、嵌入式linux系统开发 3、…...

echart在微信小程序的使用

echart在微信小程序的使用 echarts不显示在微信小程序 <!-- 微信小程序的echart的使用 --> <view class"container"><ec-canvas id"mychart-dom-bar" canvas-id"mychart-bar" ec"{{ ec }}"></ec-canvas> &l…...

51单片机最强模块化封装(5)

文章目录 前言一、创建timer文件,添加timer文件路径二、timer文件编写三、模块化测试总结前言 今天这篇文章将为大家封装定时器模块,定时器是工程项目中必不可少的,希望大家能够将定时器理解清楚并且运用自如。 一、创建timer文件,添加timer文件路径 这里的操作就不过多…...

链表学习之判断链表是否回文

链表解题技巧 额外的数据结构&#xff08;哈希表&#xff09;&#xff1b;快慢指针&#xff1b;虚拟头节点&#xff1b; 判断链表是否回文 要求&#xff1a;时间辅助度O(N)&#xff0c;空间复杂度O(1) 方法1&#xff1a;栈&#xff08;不考虑空间复杂度&#xff09; 遍历一…...

【Linux06-基础IO】4.5万字的基础IO讲解

前言 本期分享基础IO的知识&#xff0c;主要有&#xff1a; 复习C语言文件操作文件相关的系统调用文件描述符fd理解Linux下一切皆文件缓冲区文件系统软硬链接动静态库的理解和制作动静态编译 博主水平有限&#xff0c;不足之处望请斧正&#xff01; C语言文件操作 #再谈文件…...

c++协程库理解—ucontext组件实践

文章目录1.干货写在前面2.ucontext初接触3.ucontext组件到底是什么4.小试牛刀-使用ucontext组件实现线程切换5.使用ucontext实现自己的线程库6.最后一步-使用我们自己的协程库1.干货写在前面 协程是一种用户态的轻量级线程 首先我们可以看看有哪些语言已经具备协程语义&#x…...

英语基础-状语

1. 课前引语 1. 形容词使用场景 (1). 放在系动词后面作表语 The boy is handsome. (2). 放在名词前面做定语 I like this beautiful girl. (3). 放在宾语后面做补语 You make your father happy. 总结&#xff1a;形容词无论做什么&#xff0c;都离不开名词&#xff0c…...

目标检测笔记(八):自适应缩放技术Letterbox完整代码和结果展示

文章目录自适应缩放技术Letterbox介绍自适应缩放技术Letterbox流程自适应缩放Letterbox代码运行结果自适应缩放技术Letterbox介绍 由于数据集中存在多种不同和长宽比的样本图&#xff0c;传统的图片缩放方法按照固定尺寸来进行缩放会造成图片扭曲变形的问题。自适应缩放技术通…...

2023年全国最新高校辅导员精选真题及答案1

百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 一、选择题 11.李某与方某签订房屋租赁合同期间&#xff0c;李某欲购买租赁房屋&#xff…...

【Python】Python读写Excel表格

简要版&#xff0c;更多功能参考资料1。1 Excel文件保存格式基础概念此处不提&#xff0c;详见资料1。Excel的文件保存格式有两种&#xff1a; xls 和 xlsx。如果你看不到文件后缀&#xff0c;按下图设置可见。xls是Office 2003及之前版本的表格的默认保存格式。xlsx 是 Excel …...

Python每日一练(20230218)

目录​​​​​​​ 1. 旋转图像 2. 解码方法 3. 二叉树最大路径和 1. 旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在原地旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像…...

基于SSM框架的狼途汽车门店管理系统的设计与实现

基于SSM框架的狼途汽车门店管理系统的设计与实现 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、…...

视频监控流程图3

<html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"/> <link rel"stylesheet" type"text/css" href"visio.css"/> <title> 视频监控流程图 </title> <…...

Linux ARM平台开发系列讲解(CAN) 2.14.3 CANFD协议介绍

1. 概述 前面章节介绍了CAN2.0协议,CAN现在主要是用在汽车领域,随着CAN的发展, 又衍生除了CANFD协议,该协议是在CAN的基础之上进行了升级,CAN2.0的最高速率是1Mbps,有限的速率导致CAN总线上负载率变高,所以CANFD就出现了,CANFD目前最高支持10Mbps。除此之外,CANFD还拥…...

参考 | 给C盘 “搬家“

参考 | 给C盘 “搬家” 将在C盘准备 “搬家” 的 文件/文件夹 完整路径 copy 下来 e.g. 路径一 “C:\Users\你的用户名\AppData\Roaming\kingsoft” 将这个 文件/文件夹 CTRLX 剪切下来 注意: 剪切后, 不需要自己重新新建, 直接执行第三步 将这个 文件/文件夹 CTRLV 粘贴到你要…...

剑指 Offer 53 - II. 0~n-1中缺失的数字

原题链接 难度&#xff1a;easy\color{Green}{easy}easy 题目描述 一个长度为n-1的递增排序数组中的所有数字都是唯一的&#xff0c;并且每个数字都在范围0&#xff5e;n-1之内。在范围0&#xff5e;n-1内的n个数字中有且只有一个数字不在该数组中&#xff0c;请找出这个数字…...

分布式id

一、分布式系统 1.1 分布式系统的定义和应用场景 分布式系统是由多个独立的计算机节点协同工作&#xff0c;以共同完成一个任务的系统。这些节点通过网络进行通信和协调&#xff0c;共享计算和存储资源&#xff0c;从而实现对更大规模问题的处理和更高系统可用性的要求。 分…...

wordpress自动发布模块/互联网营销师考证多少钱

分享一组Rpg Marker人物行走,游戏素材图片&#xff0c;共5张图片 上面的下载地址链接是图片&#xff0c;无法直接复制哦&#xff01;下载请直接点击&#xff1a;游戏素材下载 或者复制以下链接&#xff1a;http://www.2gei.com/view/50.html...

黄色的html代码/seo下拉优化

1.下载安装qrcodejs2包 npm i qrcodejs2 2.导入 import QRCode from "qrcodejs2"; 3.html <div class"qrcode" id"qrcode"></div> //class是我的样式可以忽略&#xff0c;但是id一定要下 4.使用&#xff0c;以下是我的代码&…...

wordpress 增加css/建站公司

在写表单之前补充一点&#xff1a;网页名以及属性的值命名都不能用中文&#xff0c;尽量用英文或拼音。 html表单特写 1、表单格式 <form method"get/post" action"data.html" target"_blank/_self"> <input/> </form> 注&…...

网站建设的常用软件有哪些/seo网络培训班

前几天同一个朋友闲聊&#xff0c;他说了个很有意思的观点&#xff1a; 我们不招北大清华的。 因为大家都经过高考的折磨&#xff0c;所以心里对考上北大清华的都还是有点敬畏的&#xff0c;因此就追问了下原因。 他的回答很简单&#xff1a; 我们得承认这两所学校的人非常优秀…...

减肥药做网站营销/seo优化操作

本文使用JSON.NET这个组件 DataTable dt XXx.GetData(); var _list dt.AsEnumerable().Skip((pageindex - 1) * pagesize).Take(pagesize); 在此如果真接使用JSON.NET组件转换&#xff0c;如下代码&#xff1a; JsonConvert.SerializeObject(_list ) ; 生成的JSON串中有一些没…...

可以做哪些有趣的网站/百度搜索最多的关键词

经过一番调查&#xff0c;我发现这是因为Vue3中的event对象已经升级为全新的EventEmitter&#xff0c;与Vue2中的event对象有所不同&#xff0c;导致了这个问题的出现。如果你也遇到了同样的问题&#xff0c;不要担心&#xff0c;下面我来给大家分享一下解决方法。 &#xff0…...