Quartz任务调度框架介绍和使用

一、Quartz介绍

Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:

1.持久性作业 - 就是保持调度定时的状态;

2.作业管理 - 对调度作业进行有效的管理;

Quartz是一个强大任务调度框架,可以用来干嘛?

简单来说就是实现“计划(或定时)任务”的系统,例如:订单下单后未付款,15分钟后自动撤消订单,并自动解锁锁定的商品;一个OA系统需要在每周五9点自动生成数据报表;或者想每月10号自动还款;又或者每周给暗恋的女生定时发送邮件等等。

二、Quartz的核心概念

三大核心类 JObDetail(作业类),Trigger(触发器),Scheduler(调度器)。Trigger指定JObDetail什么时候发布任务。

1,任务job

job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。

Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。

Job:实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。

2,触发器Trigger

Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。

Trigger主要包含两种:SimpleTrigger和CronTriggerr。

3,调度器Scheduler

Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。

三、Quartz的几个常用API

Scheduler :用于与调度程序交互的主程序接口。

Job :预先定义的希望在未来时间被调度程序执行的任务类,自定义。

JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。

JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。

Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。

JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如:任务名,组名等,这个声明的实例将作为一个实例执行的任务。

TriggerBuilder :触发器创建器,用于创建触发器trigger实例。

JobListener,TriggerListener,SchedulerListener监听器,用于对组件的监听。

四、Quartz的简单使用

运行程序,可以看到程序每隔1s会打印出内容,且在12s后程序结束。

创建项目并加入依赖,参考:【普通的IDEA maven java项目demo(hello word)-1.8】待更新CSDN链接

<dependency>

    <groupId>org.quartz-scheduler</groupId>

    <artifactId>quartz</artifactId>

    <version>2.3.2</version>

</dependency>

 

新建一个能够打印任意内容的Job:

import org.quartz.Job;

import org.quartz.JobExecutionContext;

 

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Random;

 

public class PrintWordsJob implements Job {

    @Override

    public void execute(JobExecutionContext jobExecutionContext) {

        String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss:SSS").format(new Date());

        System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));

    }

}

 

创建Schedule,执行任务:

import org.quartz.*;

import org.quartz.impl.StdSchedulerFactory;

 

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.concurrent.TimeUnit;

 

public class Demo {

 

    public static void main(String[] args) throws SchedulerException, InterruptedException {

 

        // 1、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)

        JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class)

                .withIdentity("job1", "group1").build();

 

        // 2、构建Trigger实例,每隔1s执行一次

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")

                .startNow()// 立即生效

                .withSchedule(SimpleScheduleBuilder.simpleSchedule()

                        .withIntervalInSeconds(1)// 每隔1s执行一次

                        .repeatForever()).build();// 一直执行

 

        // 3、创建调度器Scheduler并执行

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();

        scheduler.scheduleJob(jobDetail, trigger);

        System.out.println("--------scheduler start ! ------------");

        System.out.println("at:" + new SimpleDateFormat("yy-MM-dd HH-mm-ss:SSS").format(new Date()) + ", prints: Hello scheduler");

        scheduler.start();

 

        // 睡眠12秒

        TimeUnit.MILLISECONDS.sleep(12000);

        scheduler.shutdown();

        System.out.println("at:" + new SimpleDateFormat("yy-MM-dd HH-mm-ss:SSS").format(new Date()) + ", prints: Hello scheduler");

        System.out.println("--------scheduler shutdown ! ------------");

    }

}

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 00-05-01:123, prints: Hello scheduler

PrintWordsJob start at:23-08-22 00-05-01:129, prints: Hello Job-69

PrintWordsJob start at:23-08-22 00-05-02:052, prints: Hello Job-68

PrintWordsJob start at:23-08-22 00-05-03:057, prints: Hello Job-93

PrintWordsJob start at:23-08-22 00-05-04:061, prints: Hello Job-32

PrintWordsJob start at:23-08-22 00-05-05:057, prints: Hello Job-14

PrintWordsJob start at:23-08-22 00-05-06:051, prints: Hello Job-55

PrintWordsJob start at:23-08-22 00-05-07:058, prints: Hello Job-30

PrintWordsJob start at:23-08-22 00-05-08:048, prints: Hello Job-82

PrintWordsJob start at:23-08-22 00-05-09:058, prints: Hello Job-28

PrintWordsJob start at:23-08-22 00-05-10:059, prints: Hello Job-97

PrintWordsJob start at:23-08-22 00-05-11:053, prints: Hello Job-88

PrintWordsJob start at:23-08-22 00-05-12:048, prints: Hello Job-18

PrintWordsJob start at:23-08-22 00-05-13:057, prints: Hello Job-93

at:23-08-22 00-05-13:135, prints: Hello scheduler

--------scheduler shutdown ! ------------

五、Quartz核心详解

1.Job和JobDetail

Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。

JobDetail用来绑定Job,为Job实例提供许多属性:name、group、jobClass、jobDataMap

JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

为什么设计成JobDetail + Job,不直接使用Job?

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。 这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

2.Trigger、SimpleTrigger、CronTrigger

Trigger

Trigger是Quartz的触发器,会去通知Scheduler何时去执行对应Job。

new Trigger().startAt():表示触发器首次被触发的时间;

new Trigger().endAt():表示触发器结束触发的时间;

SimpleTrigger

  SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。

将下述代码替换上述【Quartz的简单使用】代码的 // 2、构建Trigger实例,每隔1s执行一次 内容

程序运行5s后开始执行Job,执行Job 5s后,再延时2s结束程序:

// 2、构建Trigger实例,每隔1s执行一次

        Date startDate = new Date();

        startDate.setTime(startDate.getTime() + 5000);

 

        Date endDate = new Date();

        endDate.setTime(startDate.getTime() + 5000);

 

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")

                .usingJobData("trigger1", "这是jobDetail1的trigger")

                .startNow()//立即生效

                .startAt(startDate)

                .endAt(endDate)

                .withSchedule(SimpleScheduleBuilder.simpleSchedule()

                        .withIntervalInSeconds(1)// 每隔1s执行一次

                        .repeatForever()).build();// 一直执行

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 00-08-34:658, prints: Hello scheduler

PrintWordsJob start at:23-08-22 00-08-39:573, prints: Hello Job-81

PrintWordsJob start at:23-08-22 00-08-40:553, prints: Hello Job-63

PrintWordsJob start at:23-08-22 00-08-41:560, prints: Hello Job-87

PrintWordsJob start at:23-08-22 00-08-42:562, prints: Hello Job-25

PrintWordsJob start at:23-08-22 00-08-43:554, prints: Hello Job-65

at:23-08-22 00-08-46:666, prints: Hello scheduler

--------scheduler shutdown ! ------------

CronTrigger

  CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的,了解Cron表达式可参考:【cron表达式 详解】cron表达式 详解_linux cron表达式_西晋的no1的博客-CSDN博客

在线生成corn表达式: 在线Cron表达式生成器

将下述代码替换上述【Quartz的简单使用】代码的 // 2、构建Trigger实例,每隔1s执行一次 内容

从0秒开始,每5秒执行一次定时任务

        // 2.触发器

        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行

                .usingJobData("trigger1", "这是jobDetail1的trigger")

                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))//表示每次0秒时候执行。

                .build();

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 00-21-35:870, prints: Hello scheduler

PrintWordsJob start at:23-08-22 00-21-35:877, prints: Hello Job-39

PrintWordsJob start at:23-08-22 00-21-40:001, prints: Hello Job-68

PrintWordsJob start at:23-08-22 00-21-45:002, prints: Hello Job-8

at:23-08-22 00-21-47:873, prints: Hello scheduler

--------scheduler shutdown ! ------------

六、JobListener

创建MyJobListener实现JobListener接口

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.quartz.JobListener;

 

public class MyJobListener implements JobListener {

 

 

    public String getName() {

        return this.getClass().getSimpleName();

    }

 

    //Scheduler在jobDetail将要被执行时调用这个方法(执行前)

    public void jobToBeExecuted(JobExecutionContext context) {

        String jobName = context.getJobDetail().getKey().getName();

        System.out.println("我的job名1:" + jobName);

    }

 

    //Scheduler在jobDetail即将被执行,但又被TriggerListermer 否定时会调用该方法

    public void jobExecutionVetoed(JobExecutionContext context) {

        String jobName = context.getJobDetail().getKey().getName();

        System.out.println("我的job名2:" + jobName);

    }

 

    //Scheduler在jobDetail即将被执行之后调用这个方法。(执行后)

    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {

        String jobName = context.getJobDetail().getKey().getName();

        System.out.println("我的job名3:" + jobName);

    }

}

在scheduler创建后加入监听即可生效

scheduler.getListenerManager().addJobListener(new MyJobListener());

将下述蓝色代码放于上述【Quartz的简单使用】对应位置

// 3、创建调度器Scheduler并执行

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.getListenerManager().addJobListener(new MyJobListener());

scheduler.scheduleJob(jobDetail, trigger);

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 00-28-12:174, prints: Hello scheduler

我的job名1:job1

PrintWordsJob start at:23-08-22 00-28-12:179, prints: Hello Job-7

我的job名3:job1

我的job名1:job1

PrintWordsJob start at:23-08-22 00-28-13:112, prints: Hello Job-39

我的job名3:job1

我的job名1:job1

PrintWordsJob start at:23-08-22 00-28-23:111, prints: Hello Job-0

我的job名3:job1

我的job名1:job1

PrintWordsJob start at:23-08-22 00-28-24:115, prints: Hello Job-12

我的job名3:job1

at:23-08-22 00-28-24:179, prints: Hello scheduler

--------scheduler shutdown ! ------------

七、TriggerListener

任务调度过程中,与触发器Trigger相关的事件包括:触发器触发,触发器未正常触发,触发器完成等。

import org.quartz.JobExecutionContext;

import org.quartz.Trigger;

import org.quartz.TriggerListener;

 

public class MyTriggerListener implements TriggerListener {

    //用于获取触发器的名称

    public String getName() {//获取默认类名

        return this.getClass().getSimpleName();

    }

 

    //当与监听器相关联的trigger被触发,job上的execute()方法将被执行时,Scheduler就调用该方法

    public void triggerFired(Trigger trigger, JobExecutionContext context) {

        System.out.println("triggerFired");

    }

 

    //在Trigger触发后,job将要被执行时由Scheduler调用这个方法。

    //TriggerListener给一个选择去否决job的执行。如方法返回true,job此次将不会为trigger触发执行。false,放行。

    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {

        System.out.println("vetoJobExecution");

        return false;

    }

 

    //Scheduler 调用这个方法是在trigger错过时触发。

    public void triggerMisfired(Trigger trigger) {

        System.out.println("triggerMisfired");

    }

 

    //triggerComplete:trigger被触发并且完成了job的执行时,Scheduler调用这个方法。

    public void triggerComplete(Trigger trigger, JobExecutionContext context,

                                Trigger.CompletedExecutionInstruction triggerInstructionCode) {

        System.out.println("triggerComplete");

    }

 

}

将下述蓝色代码放于上述【Quartz的简单使用】对应位置

// 3、创建调度器Scheduler并执行

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.getListenerManager().addTriggerListener(new MyTriggerListener());

scheduler.scheduleJob(jobDetail, trigger);

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 00-34-56:592, prints: Hello scheduler

triggerFired

vetoJobExecution

PrintWordsJob start at:23-08-22 00-34-56:601, prints: Hello Job-69

triggerComplete

triggerFired

vetoJobExecution

PrintWordsJob start at:23-08-22 00-35-07:530, prints: Hello Job-13

triggerComplete

triggerFired

vetoJobExecution

PrintWordsJob start at:23-08-22 00-35-08:535, prints: Hello Job-21

triggerComplete

at:23-08-22 00-35-08:597, prints: Hello scheduler

--------scheduler shutdown ! ------------

八、SchedulerListener

SchedulerListener会在scheduler的生命周期中关键事件发生时被调用,与Scheduler有关事件;增加或者删除一个 job/trigger,关闭scheduler等。

import org.quartz.*;

 

public class MySchedulerListener implements SchedulerListener {

 

    //用于部署JobDetail 的时候调用

    public void jobScheduled(Trigger trigger) {

        String name = trigger.getKey().getName();

        System.out.println("获取触发器名称:" + name);

    }

 

    //卸载JobDetail 的时候调用

    public void jobUnscheduled(TriggerKey triggerKey) {

        System.out.println(triggerKey.getName());

    }

 

    //当trigger来到再也不会触发的时候调用这个方法

    public void triggerFinalized(Trigger trigger) {

        String name = trigger.getKey().getName();

        System.out.println("获取触发器名称:" + name);

    }

 

    //当trigger 被暂停时候调用

    public void triggerPaused(TriggerKey triggerKey) {

        System.out.println("被暂停1");

    }

 

    //当trigger组  被暂停时候调用

    public void triggersPaused(String triggerGroup) {

        System.out.println("被暂停2");

    }

 

    ///当trigger从  被暂停 到恢复 时候 调用

    public void triggerResumed(TriggerKey triggerKey) {

        System.out.println("恢复");

    }

 

    ///当trigger组从  被暂停 到恢复 时候 调用

    public void triggersResumed(String triggerGroup) {

        System.out.println("恢复");

    }

 

    //添加工作任务调用

    public void jobAdded(JobDetail jobDetail) {

        System.out.println("添加工作任务");

 

    }

 

    //删除工作任务

    public void jobDeleted(JobKey jobKey) {

        System.out.println("删除工作任务");

 

    }

 

    public void jobPaused(JobKey jobKey) {

        // TODO Auto-generated method stub

 

    }

 

    public void jobsPaused(String jobGroup) {

        // TODO Auto-generated method stub

 

    }

 

    public void jobResumed(JobKey jobKey) {

        // TODO Auto-generated method stub

 

    }

 

    public void jobsResumed(String jobGroup) {

        // TODO Auto-generated method stub

 

    }

 

    //scheduler产生Error调用

    public void schedulerError(String msg, SchedulerException cause) {

        // TODO Auto-generated method stub

 

    }

 

    //scheduler被挂起时候调用

    public void schedulerInStandbyMode() {

        // TODO Auto-generated method stub

 

    }

 

    //scheduler开启的时候调用

    public void schedulerStarted() {

        System.out.println("scheduler 开启 的时候调用");

 

    }

 

    //scheduler 正在开启的时候调用 ing.....

    public void schedulerStarting() {

        System.out.println("scheduler 正在开启的时候调用 ing.....");

 

    }

 

    // scheduler关闭 的时候调用

    public void schedulerShutdown() {

        System.out.println("scheduler关闭 的时候调用");

 

    }

 

    //scheduler 正在关闭的时候调用 ing.....

    public void schedulerShuttingdown() {

        System.out.println("//scheduler 正在关闭的时候调用 ing.....");

 

    }

 

    //scheduler 数据被清除了的时候调用

    public void schedulingDataCleared() {

        System.out.println("//scheduler 数据被清除了的时候调用");

 

    }

 

}

将下述蓝色代码放于上述【Quartz的简单使用】对应位置

// 3、创建调度器Scheduler并执行

Scheduler scheduler = new StdSchedulerFactory().getScheduler();

scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());

scheduler.scheduleJob(jobDetail, trigger);

运行结果(注意看时间):

添加工作任务

获取触发器名称:trigger1

--------scheduler start ! ------------

at:23-08-22 00-37-43:391, prints: Hello scheduler

scheduler 正在开启的时候调用 ing.....

scheduler 开启 的时候调用

PrintWordsJob start at:23-08-22 00-37-43:395, prints: Hello Job-74

PrintWordsJob start at:23-08-22 00-37-44:294, prints: Hello Job-62

PrintWordsJob start at:23-08-22 00-37-45:301, prints: Hello Job-84

PrintWordsJob start at:23-08-22 00-37-46:292, prints: Hello Job-19

PrintWordsJob start at:23-08-22 00-37-47:301, prints: Hello Job-82

PrintWordsJob start at:23-08-22 00-37-48:288, prints: Hello Job-42

PrintWordsJob start at:23-08-22 00-37-49:296, prints: Hello Job-19

PrintWordsJob start at:23-08-22 00-37-50:298, prints: Hello Job-4

PrintWordsJob start at:23-08-22 00-37-51:290, prints: Hello Job-10

PrintWordsJob start at:23-08-22 00-37-52:294, prints: Hello Job-78

PrintWordsJob start at:23-08-22 00-37-53:292, prints: Hello Job-42

PrintWordsJob start at:23-08-22 00-37-54:298, prints: Hello Job-49

PrintWordsJob start at:23-08-22 00-37-55:291, prints: Hello Job-13

//scheduler 正在关闭的时候调用 ing.....

scheduler关闭 的时候调用

at:23-08-22 00-37-55:397, prints: Hello scheduler

--------scheduler shutdown ! ------------

九、定时任务参数传递问题

将下述蓝色代码放于上述【Quartz的简单使用】1和2之间的位置

// 1、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)

JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class)

         .withIdentity("job1", "group1").build();

// 传参

JobDataMap jobDataMap=jobDetail.getJobDataMap();

jobDataMap.put("name","传参test");

jobDataMap.put("age",11);

jobDataMap.put("sex","男");

 

// 2、构建Trigger实例,每隔1s执行一次

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")

        .startNow()// 立即生效

        .withSchedule(SimpleScheduleBuilder.simpleSchedule()

                .withIntervalInSeconds(1)// 每隔1s执行一次

                .repeatForever()).build();// 一直执行

同时更新PrintWordsJob.java文件中的代码为以下内容:

import org.quartz.Job;

import org.quartz.JobDataMap;

import org.quartz.JobExecutionContext;

 

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Random;

 

public class PrintWordsJob implements Job {

    @Override

    public void execute(JobExecutionContext jobExecutionContext) {

        String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss:SSS").format(new Date());

        System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();

        System.out.println(jobDataMap.get("name").toString() + ":" + jobDataMap.get("age").toString() +":"+ jobDataMap.get("sex").toString());

    }

}

运行结果(注意看时间):

--------scheduler start ! ------------

at:23-08-22 01-00-24:165, prints: Hello scheduler

PrintWordsJob start at:23-08-22 01-00-24:176, prints: Hello Job-6

传参test:11:男

PrintWordsJob start at:23-08-22 01-00-25:114, prints: Hello Job-70

传参test:11:男

PrintWordsJob start at:23-08-22 01-00-26:106, prints: Hello Job-54

传参test:11:男

PrintWordsJob start at:23-08-22 01-00-36:104, prints: Hello Job-73

传参test:11:男

at:23-08-22 01-00-36:181, prints: Hello scheduler

--------scheduler shutdown ! ------------

参考资料:

1. https://blog.csdn.net/faramita_of_mine/article/details/123142384?ops_request_misc=&request_id=&biz_id=102&utm_term=quartz&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-6-123142384.142^v93^chatgptT3_2&spm=1018.2226.3001.4187

2. https://blog.csdn.net/yoonbongchi/article/details/110579024?ops_request_misc=&request_id=&biz_id=102&utm_term=quartz&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-110579024.142^v93^chatgptT3_2&spm=1018.2226.3001.4187

 

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

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

相关文章

PDF怎么转Word?8 个最佳 PDF 转 Word 转换器

PDF 转 Word 转换工具只是一个特殊程序&#xff0c;可以将 PDF&#xff08;本机和/或扫描&#xff09;转换为 Microsoft Office Word 格式。将 PDF 导出到 Word 的主要原因之一是满足可编辑文档的需求&#xff0c;尽管还有其他原因。 由于缺少 PDF 阅读器&#xff0c;您可以选…

AutoDev 1.1.3 登场,个性化 AI 辅助:私有化大模型、自主设计 prompt、定义独特规则...

在过去的半个月里&#xff0c;我们为开源辅助编程工具 AutoDev 添加了更强大的自定义能力&#xff0c;现在你可以&#xff1a; 使用自己部署的开源大模型自己配置 Intellij IDEA 中的行为自定义开发过程中的规范 当然了&#xff0c;如果您自身拥有开发能力的话&#xff0c;建议…

fastgpt构建镜像

1.把client目录复制到服务器 .next和node_modules文件夹不用上传到服务器 在服务器目录运行 docker build -t fastgpt:1.0.3 . 构建服务 再运行 docker ps 就可以看到容器了

数据结构(2)

冒泡排序&#xff1a; 1.比较相邻的两个元素。如果前一个元素比后一个元素大&#xff0c;则交换两者位置。 2.对每一对相邻元素做相同工作&#xff0c;从第一对元素到最后一对元素&#xff0c;最后的一个元素就是最大的元素。 for(int ia.length-1;i>0;i--){for (int j 0…

VS2019+Qt5.15.2 编译 QtWebEngine(带音视频解码)

前言 QtWebEngine 是 Qt 框架的一部分&#xff0c;用于构建现代 Web 浏览器功能。本篇教程将向您展示如何在 Visual Studio 2019 中编译 QtWebEngine 5.15.2 源码&#xff0c;并配置以支持音视频解码功能。 准备工作 1、源码下载 2、源码修改&#xff0c;参考Qt Code Review…

微信小程序纯前端从阿里云OSS下载json数据-完整版

起因 因为云开发开始收费(貌似很久了),准备改造在以前的小程序,数据转到oss上,小程序使用原生,不算专业领域, 所以先百度.... 网上的教程真的是千篇一律,大部分开局就是require(ali-oss); 好点的npm install ali-oss --save开局,拼凑操作到最后发现要用云开发,因为云…

HTTPS代理搭建技巧分享

今天我们来分享一下如何搭建一个能够实现中间人 检测和防护的HTTPS代理。保护我们的网络通信安全是至关重要的&#xff0c;让我们一起学习如何构建一个安全可靠的HTTPS代理吧&#xff01; 什么是中间人 &#xff1f; 首先&#xff0c;让我们来了解一下什么是中间人 。中间人 是…

RK3399平台开发系列讲解(内核调试篇)内核中内存泄漏的调试

🚀返回专栏总目录 文章目录 一、Linux 内核内存泄漏二、如何观测内核内存泄漏?三、kmemleak 工具沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 内核内存泄漏往往都会是很严重的问题,那么,我们该如何判断内存泄漏是否是内核导致的呢? 一、Linux 内核内存泄漏 …

GPT-3.5——从 人工智障 到 大人工智障

有人说&#xff0c;GPT是从人工智障到人工智能的蜕变&#xff0c;但是。。。 我认为&#xff0c;GPT是从 人工智障 到 大人工智障 的退化。。。 从 人工智障 到 大人工智障 GPT-3.5学术介绍No.1---- 西红柿炒钢丝球基本信息详细制作方法材料步骤 幕后花絮 No.2---- 顶尖数学家…

【数据分析入门】Jupyter Notebook

目录 一、保存/加载二、适用多种编程语言三、编写代码与文本3.1 编辑单元格3.2 插入单元格3.3 运行单元格3.4 查看单元格 四、Widgets五、帮助 Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。 …

自动驾驶合成数据科普一:不做真实数据的“颠覆者”,做“杠杆”

前言&#xff1a; 在7月底的一篇文章中&#xff0c;九章智驾提到&#xff0c;数据闭环能力是自动驾驶下半场的“入场券”&#xff0c;这一观点在行业内引起了广泛共鸣。 在数据闭环体系中&#xff0c;仿真技术无疑是非常关键的一环。仿真的起点是数据&#xff0c;而数据又分为真…

基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 3 Paramter标签页介绍

这页是参数设置的界面,那首先要知道什么是参数,参数就是算法中的系数这些可以更改的变量,接下来就是要学习如何创建参数,如下图: 打开模型资源管理器 选择model Workspace标签,点击上边工具栏里的创建参数的按钮(红色箭头指向的按钮),添加一个新的参数K,值设置为4,数…

linux部署clickhouse(单机)

一、下载安装 1.1、下载地址 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区阿里巴巴开源镜像站&#xff0c;免费提供Linux镜像下载服务&#xff0c;拥有Ubuntu、CentOS、Deepin、MongoDB、Apache、Maven、Composer等多种开源软件镜像源&#xff0c;此外还提供域名解析DNS、…

opencv进阶14-Harris角点检测-cv2.cornerHarris

类似于人的眼睛和大脑&#xff0c;OpenCV可以检测图像的主要特征并将这 些特征提取到所谓的图像描述符中。然后&#xff0c;可以将这些特征作为数据 库&#xff0c;支持基于图像的搜索。此外&#xff0c;我们可以使用关键点将图像拼接起 来&#xff0c;组成更大的图像。&#x…

软件开发bug问题跟踪与管理

一、Redmine 项目管理和缺陷跟踪工具 官网&#xff1a;https://www.redmine.org/ Redmine 是一个开源的、基于 Web 的项目管理和缺陷跟踪工具。它用日历和甘特图辅助项目及进度可视化显示&#xff0c;同时它又支持多项目管理。Redmine 是一个自由开源软件解决方案&#xff0c;…

通过DBeaver 给Postgre SQL表 设置主键自增

1.创建表 CREATE TABLE public.company ( id int4 NOT NULL , name text NOT NULL, age int4 NOT NULL, address bpchar(50) NULL, salary float4 NULL, join_date date NULL, CONSTRAINT company_pkey PRIMARY KEY (id) ); 2.插入数据&#xff08;不传入id&#xff…

机器学习:什么是分类/回归/聚类/降维/决策

目录 学习模式分为三大类&#xff1a;监督&#xff0c;无监督&#xff0c;强化学习 监督学习基本问题 分类问题 回归问题 无监督学习基本问题 聚类问题 降维问题 强化学习基本问题 决策问题 如何选择合适的算法 我们将涵盖目前「五大」最常见机器学习任务&#xff1a…

Android学习之路(7) Frament

Fragment 表示应用界面中可重复使用的一部分。fragment 定义和管理自己的布局&#xff0c;具有自己的生命周期&#xff0c;并且可以处理自己的输入事件。fragment 不能独立存在。它们必须由 activity 或其他 fragment 托管。fragment 的视图层次结构会成为宿主的视图层次结构的…

人事变动?前沃尔沃汽车大中华区总裁钦培吉将加盟吉利

根据消息&#xff0c;吉利控股集团高级副总裁杨学良在今天上午通过微博宣布&#xff0c;前沃尔沃汽车大中华区总裁钦培吉将加盟吉利。钦培吉将担任吉利汽车集团销售公司副总经理&#xff0c;并负责集团渠道发展委员会的主任一职&#xff0c;向吉利汽车集团的高级副总裁林杰报告…

0006Java程序设计-jsp婚恋交友网设计与实现

摘 要 在线交友是互联网发展的必然产物&#xff0c;它改变了人们的网络交往形态&#xff0c;使得人们的即时通信变得更加的直观和亲切&#xff0c;并且具有良好的发展趋势。 婚恋交友网站我们使用 Microsoft公司的JSP开发工具&#xff0c;利用其提供的各种面向对象的开发工具…