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

SpringBoot整合Quartz示例

数据表  加不加无所谓,如果需要重启服务器后重新执行所有JOB就把sql加上

如果不加表  将application.properties中的quartz数据库配置去掉 

自己执行自己的逻辑来就好,大不了每次启动之后重新加载自己的逻辑

链接:https://pan.baidu.com/s/1KqOPYMfI4eHcEMxt5BmtYg 
提取码:o9ql 
--来自百度网盘超级会员V4的分享

SpringBoot工程

pom依赖

 <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.26</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></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>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-devtools</artifactId>-->
<!--        </dependency>--><!--解决加了@ConfigurationProperties注解 类上的提示--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</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></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><image><builder>paketobuildpacks/builder-jammy-base:latest</builder></image><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>

application.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/job3?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=123456
#
##
#mybatis-plus.configuration.map-underscore-to-camel-case=true
#
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#
#
#mybatis-plus.global-config.db-config.table-prefix=tbl_
#
#
#mybatis-plus.global-config.db-config.id-type=auto# 定时任务Quartz的数据源配置
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.URL=jdbc:mysql://localhost:3306/job3?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.driver=com.mysql.cj.jdbc.Driver
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.maxConnections=5
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.username=root
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.password=123456
spring.quartz.properties.org.quartz.dataSource.globalJobDataSource.provider=hikaricp# Quartz调度器配置
spring.quartz.properties.org.quartz.scheduler.instanceName=globalScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.scheduler.type=com.alibaba.druid.pool.DruidDataSource# Quartz作业存储配置
spring.quartz.properties.org.quartz.jobStore.dataSource=globalJobDataSource
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=100
spring.quartz.properties.org.quartz.jobStore.isClustered=true# Quartz线程池配置
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=10
spring.quartz.properties.org.quartz.threadPool.threadPriority=5

包结构

实体类

package com.example.springbootquartz.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;/*** @author hrui* @date 2023/11/16 22:57*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class JobInfo {/*** 任务名称*/private String jobName;/*** 任务组*/private String jobGroup;/*** 触发器名称*/private String triggerName;/*** 触发器组*/private String triggerGroup;/*** cron表达式*/private String cron;/*** 类名*/private String className;/*** 状态*/private String status;/*** 下一次执行时间*/private String nextTime;/*** 上一次执行时间*/private String prevTime;/*** 配置信息(data)*/private String config;}
package com.example.springbootquartz.job;import com.alibaba.fastjson.JSONObject;
import com.example.springbootquartz.pojo.JobInfo;
import org.quartz.*;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;/*** @author hrui* @date 2023/11/16 23:10*/
@Component
public class SchedulerManage {@Autowiredprivate Scheduler scheduler;/*** 添加任务*/@SuppressWarnings("unchecked")public void addJob(JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {Objects.requireNonNull(jobInfo, "任务信息不能为空");// 生成job keyJobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());// 当前任务不存在才进行添加if (!scheduler.checkExists(jobKey)) {Class<Job> jobClass = (Class<Job>)Class.forName(jobInfo.getClassName());// 任务明细JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup()).withDescription(jobInfo.getJobName()).build();// 配置信息jobDetail.getJobDataMap().put("config", jobInfo.getConfig());// 定义触发器TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());// 设置任务的触发机制Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCron()).withMisfireHandlingInstructionDoNothing()).build();scheduler.scheduleJob(jobDetail, trigger);} else {throw new SchedulerException(jobInfo.getJobName() + "任务已存在,无需重复添加");}}/*** 任务暂停*/public void pauseJob(String jobGroup, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (scheduler.checkExists(jobKey)) {scheduler.pauseJob(jobKey);}}/*** 继续任务*/public void continueJob(String jobGroup, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (scheduler.checkExists(jobKey)) {scheduler.resumeJob(jobKey);}}/*** 删除任务*/public boolean deleteJob(String jobGroup, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (scheduler.checkExists(jobKey)) {// 这里还需要先删除trigger相关//TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());//scheduler.getTrigger()//scheduler.rescheduleJob()return scheduler.deleteJob(jobKey);//不需要删除trigger 一个job可以有多个trigger 删除job同时源码底层会删除对应trigger}return false;}/*** 获取任务信息*/public JobInfo getJobInfo(String jobGroup, String jobName) throws SchedulerException {JobKey jobKey = JobKey.jobKey(jobName, jobGroup);if (!scheduler.checkExists(jobKey)) {return null;}List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);if (Objects.isNull(triggers)) {throw new SchedulerException("未获取到触发器信息");}TriggerKey triggerKey = triggers.get(0).getKey();Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);JobDetail jobDetail = scheduler.getJobDetail(jobKey);JobInfo jobInfo = new JobInfo();jobInfo.setJobName(jobGroup);jobInfo.setJobGroup(jobName);jobInfo.setTriggerName(triggerKey.getName());jobInfo.setTriggerGroup(triggerKey.getGroup());jobInfo.setClassName(jobDetail.getJobClass().getName());jobInfo.setStatus(triggerState.toString());if (Objects.nonNull(jobDetail.getJobDataMap())) {jobInfo.setConfig(JSONObject.toJSONString(jobDetail.getJobDataMap()));}CronTrigger theTrigger = (CronTrigger) triggers.get(0);jobInfo.setCron(theTrigger.getCronExpression());return jobInfo;}}

package com.example.springbootquartz.job;import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.quartz.QuartzJobBean;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;/*** @author hrui* @date 2023/11/16 22:58*/
@DisallowConcurrentExecution//避免并发执行
@PersistJobDataAfterExecution//Job状态
public class QuartzJob1 extends QuartzJobBean {@Overrideprotected void executeInternal(JobExecutionContext context) {System.out.println("QuartzJob1正在执行..."+getTime());}private String getTime(){DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS");return dateFormat.format(new Date());}}

控制器

package com.example.springbootquartz.controller;import com.example.springbootquartz.job.SchedulerManage;
import com.example.springbootquartz.pojo.JobInfo;
import org.quartz.*;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;/*** @author hrui* @date 2023/11/16 23:13*/
@RestController
@RequestMapping("/job")
public class QuartzController {@Autowiredprivate SchedulerManage schedulerManage;@Autowiredprivate Scheduler scheduler;//StdScheduler@Autowiredprivate SchedulerFactoryBean SchedulerFactoryBean;/*** 查询所有的任务*/@RequestMapping("/all")public List<JobInfo> list() throws SchedulerException {List<JobInfo> jobInfos = new ArrayList<>();List<String> triggerGroupNames = scheduler.getTriggerGroupNames();for (String triggerGroupName : triggerGroupNames) {Set<TriggerKey> triggerKeySet = scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));for (TriggerKey triggerKey : triggerKeySet) {Trigger trigger = scheduler.getTrigger(triggerKey);JobKey jobKey = trigger.getJobKey();JobInfo jobInfo = schedulerManage.getJobInfo(jobKey.getGroup(), jobKey.getName());jobInfos.add(jobInfo);}}return jobInfos;}/*** 添加任务*/@PostMapping("/add")public JobInfo addJob(@RequestBody JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {schedulerManage.addJob(jobInfo);return jobInfo;}/*** 暂停任务*/@RequestMapping("/pause")public void pauseJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)throws SchedulerException {schedulerManage.pauseJob(jobGroup, jobName);}/*** 继续任务*/@RequestMapping("/continue")public void continueJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)throws SchedulerException {schedulerManage.continueJob(jobGroup, jobName);}/*** 删除任务*/@RequestMapping("/delete")public boolean deleteJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName)throws SchedulerException {return schedulerManage.deleteJob(jobGroup, jobName);}}

{

    "jobName":"job1",

    "jobGroup":"group1",

    "triggerName":"trigger1",

    "triggerGroup":"tGroup1",

    "cron":"*/5 * * * * ?",

    "className":"com.example.springbootquartz.job.QuartzJob1"

}

相关文章:

SpringBoot整合Quartz示例

数据表 加不加无所谓,如果需要重启服务器后重新执行所有JOB就把sql加上 如果不加表 将application.properties中的quartz数据库配置去掉 自己执行自己的逻辑来就好,大不了每次启动之后重新加载自己的逻辑 链接&#xff1a;https://pan.baidu.com/s/1KqOPYMfI4eHcEMxt5Bmt…...

物联网AI MicroPython学习之语法 I2C总线

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; I2C 介绍 模块功能: I2C Master设备驱动 接口说明 I2C - 构建硬件I2C对象 函数原型&#xff1a;I2C(id, scl, sda, freq)参数说明&#xff1a; 参数类型必选参数&#xff1f;说明idintYI2C外设&#xff…...

RocketMQ的适用场景有哪些?

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…...

ubuntu启动转圈,无法进入登录界面

安装卸载搜狗拼音输入法相关东西后出现启动转圈问题 当前使用的是lightdm,按网上说去切换成gdm3 &#xff08;1&#xff09;要在刚进入系统没显示圈圈和ubuntu时长按shift进入gurb。 &#xff08;2&#xff09;选择Ubuntu高级选项&#xff0c;enter &#xff08;3&#xff09…...

MATLAB 机械臂逆运动学进行轨迹控制建模

系列文章目录 文章目录 系列文章目录前言一、模型概览1.1 Target Pose Generation 目标姿势生成1.2 Inverse Kinematics 逆运动学1.3 Manipulator Dynamics 机械手动力学1.4 Pose Measurement 姿势测量 二、机械手定义三、生成航点四、模型设置五、模拟机械手运动六、将结果可视…...

【计算机组成原理】定点加法、减法运算

系列文章目录 绘制出纯整数(1字节)和纯小数的数轴 将十进制数20.59375&#xff0c;转换成754标准的32位浮点数的二进制存储格式 用双符号位补码求 x 0.1010011, y -0.1001010, 分别求出 x y, x - y&#xff0c;并判溢出...

scp 跨服务器传输命令,把一个服务器上的文件复制传到当前服务器目录下

要将一个服务器上的文件复制到当前服务器的目录下&#xff0c;可以使用 scp 命令进行跨服务器传输。以下是具体的命令格式&#xff1a; 复制 scp usernamesource_server:/path/to/source_file destination_directory username: 远程服务器的用户名。 source_server: 远程服务…...

【python基础】用户输入和while循环详解

文章目录 一. 函数input()的工作原理1. 编写清晰的程序2. 使用int()来获取数值输入3. 求模运算符 二. while循环简介1. 使用while循环2. 让用户选择何时退出3. 使用标志4. 使用break退出循环5. 在循环中使用continue 三. 使用while循环处理列表和字典1. 在列表之间移动元素2. 删…...

k8s-部署Redis-cluster(TLS)

helm pull bitnami/redis-cluster v8.3.8拉取源码生成证书 git clone https://github.com/redis/redis.git #文档 https://redis.io/docs/management/security/encryption/#getting-started生成你的TLS证书用官网的工具生成 1 Run ./utils/gen-test-certs.sh 生成根CA和服务…...

计算机毕业设计选题推荐-幼儿园管理微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

ElasticStack日志分析平台-ES 集群、Kibana与Kafka

一、Elasticsearch 1、介绍&#xff1a; Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;Logstash 和 Beats 收集的数据可以存储在 Elasticsearch 中进行搜索和分析。 Elasticsearch为所有类型的数据提供近乎实时的搜索和分析&#xff1a;一旦数据被索引&#…...

微机原理_10

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1,将二进制数110110.01转换为十六进制为(&#xff09; A. 66.1H B. 36.4H C. 66.4 D. 36.2 2,一台计算机的字长是4个字节,含义是(&#xff09; A.能处理的最大…...

(SpringBoot)第八章:SpringMVC程序开发

文章目录 一:Spring MVC概述(1)什么是Spring MVC(2)什么是MVC(3)Spring MVC和SpringBoot(4)如何学习Spring MVC二:Spring MVC创建和连接(1)Spring MVC项目创建(2)@RequestMapping注解三:Spring MVC处理参数(1)传递简单参数(2)传递对象(3)@RequestParam:重…...

openssl + 3DES开发实例(linux)

文章目录 一、3DES介绍3DES 的特点&#xff1a;3DES 加密的步骤&#xff1a;3DES 的应用场景&#xff1a; 二、3DES原理1. DES 原理回顾&#xff1a;2. 3DES 原理&#xff1a;3. 3DES 的加密流程&#xff1a; 三、openssl 3DES开发实例 一、3DES介绍 3DES&#xff08;Triple …...

遵循开源软件安全路线图

毫无疑问&#xff0c;开源软件对于满足联邦任务所需的开发和创新至关重要&#xff0c;因此其安全性至关重要。 OSS&#xff08;运营支持系统&#xff09; 支持联邦政府内的每个关键基础设施部门。 联邦政府认识到这一点&#xff0c;并正在采取措施优先考虑 OSS 安全&#xff…...

294_C++_

1、全部大致解析: struct alarminfo_t {unsigned int alarmid;INTF_ALARM_INFO_S pAlarm; };typedef enum{INTF_IO_ALARM_E= 0, //I/O探头告警开始INTF_MOTION_ALARM_E, //移动侦测告警开始INTF_AI_ALARM_E,...

【计算机网络笔记】网络地址转换(NAT)

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…...

【flink理论】动态表:关系查询处理流的思路:连续查询、状态维护;表转换为流需要编码编码

文章目录 一. 使用关系查询处理流的讨论二. 动态表 & 连续查询(Continuous Query)三. 在流上定义表1. 连续查询2. 查询限制2.1. 维护状态2.2. 计算更新 四. 表到流的转换1. Append-only 流2. Retract 流3. Upsert 流 本文主要讨论了&#xff1a; 讨论通过关系查询处理无界流…...

2023年09月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 以下选项中,不是tkinter变量类型的是?( ) A: IntVar() B: StringVar() C: DoubleVar() D: FloatVar() 答案:D tkinter 无 FloatVar()变量类型。 第2题 关于tkinter,以下说…...

Ubuntu16.04上安装Docker

Ubuntu16.04上安装Docker 更新 apt 包索引: sudo apt-get update安装依赖包,以便使用 HTTPS 仓库 sudo apt-get install apt-transport-https ca-certificates curl software-properties-common添加 Docker GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...