Spring Boot 中实现定时任务(quartz)功能实战

在这里插入图片描述

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。
🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。
🎉欢迎 👍点赞✍评论⭐收藏

🔎 SpringBoot 领域知识 🔎

链接专栏
SpringBoot 专业知识学习一SpringBoot专栏
SpringBoot 专业知识学习二SpringBoot专栏
SpringBoot 专业知识学习三SpringBoot专栏
SpringBoot 专业知识学习四SpringBoot专栏
SpringBoot 专业知识学习五SpringBoot专栏
SpringBoot 专业知识学习六SpringBoot专栏
SpringBoot 专业知识学习七SpringBoot专栏
SpringBoot 专业知识学习八SpringBoot专栏
SpringBoot 专业知识学习九SpringBoot专栏
SpringBoot 专业知识学习十SpringBoot专栏

在这里插入图片描述

本文将详细介绍如何在 Spring Boot 中实现定时任务,并涵盖了控制层、服务层、数据访问层、XML和YAML配置的使用方式。我们将从数据库创建表开始,一步一步地实现这些功能,并提供注意事项。最后,我们将总结整个过程。

在 Spring Boot 中实现定时任务功能


1. 创建数据库表

为了实现定时任务的功能,首先需要创建一个数据库表。我们可以创建一个名为 task 的表,包含以下四个字段:

  • id:自增ID
  • name :定时任务的名称
  • description :定时任务描述
  • dueDate :定时任务结束执行的时间
  • completed:定时任务是否完成

创建执行定时任务的数据库表可以按照以下 SQL 语句来进行:

CREATE TABLE `task` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`description` varchar(255) DEFAULT NULL,`dueDate` datetime DEFAULT NULL,`completed` boolean DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

该表包含了 idnamedescriptiondueDatecompleted 五个字段。其中,id 为自增主键,name 表示定时任务的名称,description 表示定时任务描述,dueDate 表示定时任务结束执行的时间,completed 表示定时任务是否完成。可以根据实际需求修改表结构。


2. 添加依赖

pom.xml 文件中添加定时任务依赖 spring-boot-starter-quartz

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>demo</artifactId><version>1.0.0</version><properties><java.version>11</java.version><spring.boot.version>2.6.1</spring.boot.version></properties><dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${spring.boot.version}</version></dependency><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency><!-- Spring Boot Starter Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>${spring.boot.version}</version></dependency><!-- Spring Boot Starter Quartz --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>${spring.boot.version}</version></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!-- Other dependencies --><!-- ... --></dependencies><build><plugins><!-- Maven Compiler Plugin --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin></plugins></build></project>

这样我们就可以使用 Quartz 框架来实现定时任务。


3. 创建定时任务实体类和 DAO 层

3.1 首先创建一个Task实体类,用于表示定时任务的属性。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDateTime;@Entity
public class Task {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String description;private LocalDateTime dueDate;private boolean completed;// 构造函数、Getter 和 Setter 方法public Task() {}public Task(String name, String description, LocalDateTime dueDate) {this.name = name;this.description = description;this.dueDate = dueDate;this.completed = false;}// Getter 和 Setter 方法省略...// 其他属性和方法省略...
}

在这个示例中,Task 实体类有以下属性:

  • id:任务的唯一标识符,使用自动生成的递增值。
  • name:任务的名称。
  • description:任务的描述。
  • dueDate:任务的截止日期。
  • completed:任务是否已完成的标志。

注意,在这个示例中,使用了 Java 8 的 LocalDateTime 类型来表示日期和时间。您可以根据具体需求选择适合的日期时间类型。

请根据您的具体需求修改属性、构造函数和方法。接下来,您可以创建一个与数据库进行交互的 DAO 层。

3.2 创建一个 TaskDao 接口

定义对定时任务的基本增删改查方法,如 addTaskdeleteTaskupdateTaskfindTaskById 等。

import java.time.LocalDateTime;
import java.util.List;public interface TaskDao {void addTask(Task task);void deleteTask(long taskId);void updateTask(long taskId, String name, String description, LocalDateTime dueDate, boolean completed);Task findTaskById(long taskId);List<Task> findTasks();
}

在这个示例中,TaskDao 定义了如下基本操作:

  • addTask:添加一个新的任务。
  • deleteTask:删除指定的任务。
  • updateTask:更新任务的名称、描述、截止日期和完成状态。
  • findTaskById:根据任务 ID 查找任务。
  • findTasks:获取当前所有的任务列表。

可以根据具体需求添加、修改或删除方法。但是,通常来说,一个 DAO 接口需要定义基本的 CRUD 操作,即增加、删除、更新、查询。我们建议您采用命名规范,例如按照方法名构造 SQL 语句,或者使用注解进行映射。另外,为了管理和维护代码,我们建议您将实现代码放在另外的类中,例如命名为 TaskDaoImpl


4. 创建 Service 层

4.1 在 TaskService 类中实现定时任务的操作方法,包括添加、删除、修改和查询方法等。
4.2 在方法中,可以通过调用 TaskDao 中的方法来完成对数据库的操作,如创建新任务、删除任务、修改任务等。
4.3 可以使用 @Autowired 注解将 TaskDao注入到 TaskService中,方便调用。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;@Service
public class TaskService {private final TaskDao taskDao;@Autowiredpublic TaskService(TaskDao taskDao) {this.taskDao = taskDao;}public void addTask(String name, String description, LocalDateTime dueDate) {Task task = new Task(name, description, dueDate);taskDao.addTask(task);}public void deleteTask(long taskId) {taskDao.deleteTask(taskId);}public void updateTask(long taskId, String name, String description, LocalDateTime dueDate, boolean completed) {Task existingTask = taskDao.findTaskById(taskId);if (existingTask != null) {existingTask.setName(name);existingTask.setDescription(description);existingTask.setDueDate(dueDate);existingTask.setCompleted(completed);taskDao.updateTask(existingTask);} else {throw new IllegalArgumentException("Task not found with ID: " + taskId);}}public Task findTaskById(long taskId) {return taskDao.findTaskById(taskId);}public List<Task> findTasks() {return taskDao.findTasks();}
}

在这个示例中,TaskService 类使用了依赖注入将 TaskDao 对象注入进来,并实现了以下操作方法:

  • addTask:创建一个新的任务,并调用 TaskDaoaddTask 方法将其添加到数据库中。
  • deleteTask:删除指定 ID 的任务,并调用 TaskDaodeleteTask 方法进行删除操作。
  • updateTask:根据指定 ID 更新任务的属性,并调用 TaskDaoupdateTask 方法进行更新操作。
  • findTaskById:根据指定 ID 查找并返回任务对象。
  • findTasks:获取当前所有的任务列表。

请根据您的具体需求修改代码,并确保将适当的错误处理和验证逻辑添加到每个方法中。此外,确保适当地处理依赖注入,以使 TaskDao 正确地注入到 TaskService 类中。

请注意,在这个示例中,使用了 Spring 的 @Service@Autowired 注解来实现依赖注入和服务的声明。如果您没有使用 Spring 或其他类似的框架,您可以手动创建和管理相关对象的实例。


5. 创建 Controller 层

5.1 在 TaskController 类中定义定时任务的 API 接口,使用 RESTful 风格。
5.2 可以使用 @Autowired 注解将 TaskService 注入到 TaskController 中,方便调用 TaskService 中的方法。
5.3 实现增删改查等控制器方法,通过 HTTP 请求来调用相应的方法。

当您在 Controller 层中创建的时候,可以考虑如下代码示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;
import java.util.List;@RestController
@RequestMapping("/tasks")
public class TaskController {private final TaskService taskService;@Autowiredpublic TaskController(TaskService taskService) {this.taskService = taskService;}@PostMappingpublic ResponseEntity<Task> addTask(@RequestBody TaskRequest taskRequest) {taskService.addTask(taskRequest.getName(), taskRequest.getDescription(), taskRequest.getDueDate());return new ResponseEntity<>(HttpStatus.CREATED);}@DeleteMapping("/{taskId}")public ResponseEntity<Task> deleteTask(@PathVariable long taskId) {taskService.deleteTask(taskId);return new ResponseEntity<>(HttpStatus.NO_CONTENT);}@PutMapping("/{taskId}")public ResponseEntity<Task> updateTask(@PathVariable long taskId, @RequestBody TaskRequest taskRequest) {taskService.updateTask(taskId, taskRequest.getName(), taskRequest.getDescription(), taskRequest.getDueDate(), taskRequest.isCompleted());return new ResponseEntity<>(HttpStatus.OK);}@GetMapping("/{taskId}")public ResponseEntity<Task> findTaskById(@PathVariable long taskId) {Task task = taskService.findTaskById(taskId);if (task != null) {return new ResponseEntity<>(task, HttpStatus.OK);} else {return new ResponseEntity<>(HttpStatus.NOT_FOUND);}}@GetMappingpublic ResponseEntity<List<Task>> findTasks() {List<Task> tasks = taskService.findTasks();return new ResponseEntity<>(tasks, HttpStatus.OK);}
}

在这个示例中,TaskController 类使用了 Spring 的 MVC 注解来定义不同的 HTTP 请求处理方法:

  • @RestController:声明这是一个 RESTful 控制器。
  • @RequestMapping("/tasks"):指定该控制器处理的 URL 前缀。
  • @PostMapping:处理 HTTP POST 请求,并调用 addTask 方法创建任务。
  • @DeleteMapping("/{taskId}"):处理 HTTP DELETE 请求,并调用 deleteTask 方法删除指定 ID 的任务。
  • @PutMapping("/{taskId}"):处理 HTTP PUT 请求,并调用 updateTask 方法更新指定 ID 的任务。
  • @GetMapping("/{taskId}"):处理 HTTP GET 请求,并调用 findTaskById 方法获取指定 ID 的任务。
  • @GetMapping:处理 HTTP GET 请求,并调用 findTasks 方法获取所有任务列表。

请根据您的具体需求修改代码,并确保将适当的错误处理和验证逻辑添加到每个方法中。此外,确保适当地处理依赖注入,以使 TaskService 正确地注入到 TaskController 类中。

在这个示例中,TaskRequest 是一个用于接收客户端请求的数据传输对象(DTO),根据您的需求,您可以根据实际情况创建适合自己的 DTO 类来接收和传递数据。

请注意,在这个示例中,使用了 Spring 的注解来简化了 RESTful API 的开发,如果您不使用 Spring 框架,可以根据自己所用框架的要求来编写 Controller 层的代码。


6. 创建定时任务工具类

创建一个 QuartzUtil 工具类,用于创建定时任务实例。

使用 JobBuilderTriggerBuilder 等工具类,设置定时任务的属性,如任务名称、任务组名、任务类、触发器类型、触发器名称、触发器组名等。

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;public class QuartzUtil {private static Scheduler scheduler;static {try {scheduler = new StdSchedulerFactory().getScheduler();scheduler.start();} catch (SchedulerException e) {e.printStackTrace();}}public static void addJob(String jobId, String jobGroup, String triggerId, String triggerGroup, Class<? extends Job> jobClass, String cronExpression) throws SchedulerException {JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobId, jobGroup).build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerId, triggerGroup).withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).build();scheduler.scheduleJob(jobDetail, trigger);}public static void deleteJob(String jobId, String jobGroup) throws SchedulerException {JobKey jobKey = new JobKey(jobId, jobGroup);scheduler.deleteJob(jobKey);}public static void pauseJob(String jobId, String jobGroup) throws SchedulerException {JobKey jobKey = new JobKey(jobId, jobGroup);scheduler.pauseJob(jobKey);}public static void resumeJob(String jobId, String jobGroup) throws SchedulerException {JobKey jobKey = new JobKey(jobId, jobGroup);scheduler.resumeJob(jobKey);}public static void shutdown() throws SchedulerException {scheduler.shutdown();}}

使用示例:

public class TestJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("执行定时任务...");}}public class Main {public static void main(String[] args) {try {// 添加一个每分钟执行一次的定时任务QuartzUtil.addJob("job1", "jobGroup", "trigger1", "triggerGroup", TestJob.class, "0 * * * * ?");Thread.sleep(10000);// 暂停定时任务QuartzUtil.pauseJob("job1", "jobGroup");Thread.sleep(10000);// 恢复定时任务QuartzUtil.resumeJob("job1", "jobGroup");Thread.sleep(10000);// 删除定时任务QuartzUtil.deleteJob("job1", "jobGroup");// 停止定时任务调度器QuartzUtil.shutdown();} catch (Exception e) {e.printStackTrace();}}}

需要注意的是,上述示例仅为基础示例,具体使用中还需要根据实际情况进行调整。定时任务的配置可以参考 Quartz 官方文档,这里不再赘述。


7. 创建定时任务类
7.1 创建一个 TaskJob 类,实现 Quartz 框架的 Job 接口,实现需要执行的任务逻辑。
7.2 在 TaskJob 类中,通过重写 execute方法来实现具体的任务逻辑。

可以在 TaskJob 类中重写 execute 方法来实现具体的任务逻辑。以下是一个示例:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;public class TaskJob implements Job {public void execute(JobExecutionContext context) throws JobExecutionException {// 获取任务参数JobDataMap dataMap = context.getJobDetail().getJobDataMap();String taskName = dataMap.getString("taskName");// 需要执行的任务逻辑System.out.println("执行任务:" + taskName);// 任务完成后的操作System.out.println("任务执行完成");}
}

在上述示例中,我们通过 JobDataMap 获取了任务的参数,例如 taskName。在 execute 方法中可以编写任意复杂的任务逻辑,您可以根据实际需求进行相应的操作,例如发送电子邮件、生成报告等。最后,您还可以在任务执行完成后进行适当的清理操作或记录完成状态。请根据您的具体需求在 execute 方法中编写任务逻辑。


8. 配置定时任务

application.yml 文件中添加定时任务的配置:

spring:quartz:job-store-type: jdbcjdbc:initialize-schema: always

这样就可以从数据库中读取定时任务的配置信息,并在启动时创建相应的数据库表。


9. 测试

在启动 Spring Boot 项目后,通过浏览器访问 http://localhost:8080/task 来测试新增定时任务的功能是否生效。


10. 实现总结

通过以上步骤,我们成功地在 Spring Boot 中实现了定时任务的功能。使用 Spring Boot Starter Quartz 提供的依赖,我们可以方便地创建和管理定时任务。通过创建数据库表、编写实体类、DAO 层、Service 层和 Controller 层,我们实现了定时任务的增删改查功能。

需要注意的是,定时任务的时间格式是 cron 表达式,需要熟悉 cron 表达式的语法规则。同时,在测试时要注意定时任务是否已经失效,否则会影响测试结果。

总的来说,Spring Boot 提供了简单、便捷的方式来实现定时任务。通过合理地使用 Spring Boot 中的各个组件,我们可以快速地开发定时任务功能,并为我们的项目提供定时任务的支持。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑锁屏时间怎么设置?跟着这篇教程轻松搞定

在现代社会&#xff0c;我们使用电脑的时间越来越长&#xff0c;为了保护个人隐私和确保信息安全&#xff0c;设置电脑锁屏时间成为一项重要的操作。可是电脑锁屏时间怎么设置呢&#xff1f;本文将介绍三种常见的方法&#xff0c;详细解释如何设置电脑的锁屏时间&#xff0c;以…

TDengine 如何进行数据建模

小 T 导读&#xff1a;在使用 TDengine 的时候&#xff0c;通过官网的技术文档可以学习到建库&#xff08;database&#xff09;、建表&#xff08;table&#xff09;的各种 SQL 语句&#xff0c;但是一旦要跟自己的具体业务场景结合&#xff0c;经验不足的朋友可能会不知道到底…

指针及其应用

1.定义 指针&#xff1a;也是一个变量&#xff0c;存放所指变量的地址&#xff0c;根据变量定义的不同&#xff0c;指针指向的类型也不同 注意&#xff1a;*是与前面类型一体的 int main(void) {int* p; //等价于int *p;//为了区分变量&#xff0c;C语言中一般将*放置于变量…

.NET 8.0 发布到 IIS

如何在IIS&#xff08;Internet信息服务&#xff09;上发布ASP.NET Core 8&#xff1f; 在本文中&#xff0c;我假设您的 Windows Server IIS 上已经有一个应用程序池。 按照步骤了解在 IIS 环境下发布 ASP.NET Core 8 应用程序的技巧。 您需要设置代码以支持 IIS 并将项目配…

智算让大模型触手可及

本文整理自2023年 12 月 20 日举办的「2023 百度云智大会智算大会」主论坛&#xff0c;百度智能云 AI 与大数据平台总经理忻舟的主题演讲《智算让大模型触手可及》。 在之前极客公园举办的创新大会上&#xff0c;百度集团董事长兼 CEO 李彦宏先生提到&#xff1a;卷 AI 原生应用…

【Linux】各目录说明

【常见目录说明】 目录 /bin 存放二进制可执行文件(ls,cat,mkdir等)&#xff0c;常用命令一般都在这里。 /etc 存放系统管理和配置文件 /home 存放所有用户文件的根目录&#xff0c;是用户主目录的基点&#xff0c;比如用户user的主目录就是/home/user&#xff0c;可以…

智能助手的巅峰对决:ChatGPT对阵文心一言

在人工智能的世界里&#xff0c;ChatGPT与文心一言都是备受瞩目的明星产品。它们凭借先进的技术和强大的性能&#xff0c;吸引了大量用户的关注。但究竟哪一个在智能回复、语言准确性、知识库丰富度等方面更胜一筹呢&#xff1f;下面就让我们一探究竟。 首先来谈谈智能回复能力…

数据结构-排序

这篇文章主要记录各种排序算法的思想及实现代码&#xff0c;最后对各种算法的性能进行了对比。 目录 排序的概念及其运用 排序的概念 排序运用 常见的排序算法 常见排序算法的实现 插入排序 基本思想 直接插入排序 希尔排序 选择排序 基本思想 直接选择排序 堆排序…

C++设计模式-- 2.代理模式 和 外观模式

文章目录 代理模式外观模式角色和职责代码演示一&#xff1a;代码演示二&#xff1a;外观模式适用场景 代理模式 代理模式的定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个对象不适合 或不能直接引用另一个对象&#xff0c;而代…

数据结构与算法:快速排序

数据结构与算法&#xff1a;快速排序 快速排序荷兰国旗问题霍尔版本递归优化小区间优化 PartSort优化三数取中 挖坑法前后指针法 非递归法 快速排序 荷兰国旗问题 想要理解快速排序&#xff0c;就先理解这个问题&#xff1a; [LeetCode75.颜色分类] 荷兰国旗是由红白蓝三色组…

10.云原生之在线开发调试

云原生专栏大纲 文章目录 vscode-server介绍VSCode Server 和云开发结合vscode-server安装code-server安装插件在线安装插件离线安装插件安装中文插件 配置开发环境在容器中安装开放环境Dockerfile制作镜像 git拉取项目 vscode-server介绍 VSCode Server&#xff08;Visual S…

动态内存面试的经典题目

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

网络安全中的“三高一弱”和“两高一弱”是什么?

大家在一些网络安全检查中&#xff0c;可能经常会遇到“三高一弱”这个说法。那么&#xff0c;三高一弱指的是什么呢&#xff1f; 三高&#xff1a;高危漏洞、高危端口、高风险外连 一弱&#xff1a;弱口令 一共是4个网络安全风险&#xff0c;其中的“高危漏洞、高危端口、弱…

电脑怎么录制屏幕?看这一篇就够了

在数字时代&#xff0c;电脑屏幕录制已经成为人们日常生活中一个越来越重要的工具。无论是录制在线课程、游戏精彩时刻&#xff0c;还是远程会议、软件演示&#xff0c;屏幕录制都可以帮助我们更好地保存和分享这些信息。可是您知道电脑怎么录制屏幕吗&#xff1f;本文将介绍两…

旧电脑追加内存条

内存条基本知识 DDR4 2666 DDR&#xff08;Double Data Rate&#xff09;双倍速率 4 第四代 2666 内存主频2666MHz 内存时序 内存的延迟时间 传输带宽 MB/s 内存和CPU之间的传输速度 针脚数 数字-PIn 288-PIN就是288个针脚 选购内存条 …

【国产mcu填坑篇】华大单片机(小华半导体)一、SPI的DMA应用(发送主机)HC32L136

最近需要用华大的hc32l136的硬件SPIDMA传输&#xff0c;瞎写很久没调好&#xff0c;看参考手册&#xff0c;瞎碰一天搞通了。。。 先说下我之前犯的错误&#xff0c;也是最宝贵的经验&#xff0c;供参考 没多看参考手册直接写&#xff08;即使有点烂仍然提供了最高的参考价值。…

iis配置asp网站

1.安装IIS的ASP win7和win10都是一样的 下安装IIS时ASP一般被默认不选中的状态&#xff0c;因此需要打开IIS检查功能视图栏中是否存在ASP选项&#xff0c;若没有则需要从控制面板->程序和 功能->打开或关闭Windows功能->Internet信息服务->万维网服务->应用程序…

数环通更新动态|新增连接器抖店自建、叮当OKR、千易ERP、货拉拉

更新快速预览 新增连接器4个 抖店自建 叮当OKR 千易ERP 货拉拉 应用更新2个 百度统计&#xff08;2&#xff09; 旺店通&#xff08;1&#xff09; 应用连接器 新增连接器 1.抖店自建 抖店是抖音官方打造的电商商家实现一站式经营平台&#xff0c;为商家提供全链路服务&#xf…

Selenium定位元素的方法css和xpath的区别

selenium是一种自动化测试工具&#xff0c;它可以通过不同的定位方式来识别网页上的元素&#xff0c;如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式&#xff0c;它们都可以通过元素的属性或者层级关系来定位元素&#…

MacOS环境下Kali Linux安装及使用指导

Kali Linux是一个开源的、基于Debian的Linux发行版&#xff0c;面向各种信息安全任务&#xff0c;如渗透测试、安全研究、计算机取证和逆向工程&#xff0c;是最先进的渗透测试发行版&#xff0c;它的前身是BackTrack。 1. 我们为什么要用Kali Linux 由于Kali Linux具有以下特…