一次性入门三款分布式定时任务调度框架:Quartz、ElasticJob3.0、xxl-job

分布式定时任务调度框架(文末有源码)

  • 前言
  • 1、Quartz
    • 1.1 数据库
    • 1.2 maven依赖
    • 1.3 代码实现
      • 1.3.1 创建一个job
      • 1.3.1 为job设置trigger
    • 1.4 配置文件
    • 1.5 启动、测试
      • 1.1 单机
      • 1.2 集群
  • 2、ElasticJob
    • 2.1 下载zk
    • 2.2 新建三个类型的作业
    • 2.3 配置文件
    • 2.4 启动项目,测试数据
    • 2.5 分片作业(集群测试)
      • 2.5.1 **官方的三个分片策略:**
      • 2.5.2 启动三个实例,模拟集群
      • 2.5.3 模拟集群故障
    • 2.6 数据流作业
    • 2.7 控制台console
  • 3、xxl-job
    • 1.搭建调度中心(必须要搭)
      • 1.1 创建好数据库
      • 1.2 修改application.properties文件
      • 1.3 修改logback.xml文件
      • 1.4 启动项目
      • 1.5 打包部署
    • 2.springboot项目中集成
      • 2.1 maven依赖
      • 2.2 配置文件
      • 2.3 注入config
      • 2.4 新增job
      • 2.5 简单归纳一下
    • 3.结合控制台使用
      • 3.1 配置执行管理器
      • 3.2 新增一个任务
      • 3.3 启动
    • 4.用分片任务,来验证xxl-job的集群功能
      • 4.1 修改端口
      • 4.2 新建执行器
      • 4.3 新建任务代码+任务
      • 4.4 运行一次验证
    • 5.对Quartz的优化
  • 4、结语
  • 5、附录1
  • 6、附录2

前言

本来是打算水三篇文章的,但是最后想想还是打包一起,这样后来自己看也方便一点,所以本文略长,大家可以按需目录跳转阅读。每个框架都包含了入门的代码示例,文末会贴上源码链接,大家可以下载阅读。

本文主要是为了示例,包含了 单机和集群 的代码,一些基本的概念知识就不说了,大家可以去官网详细阅读。

1、Quartz

最经典的一款框架,下面两个框架都是基于Quartz改进的。本文版本用的最新版本:2.3.0
核心理念

  • scheduler:调度器
  • job:任务本身
  • trigger:触发器

1.1 数据库

Quartz是基于数据库来做任务调度的,所以我们要先把数据库构造好,用官网给的SQL脚本。
由于脚本太长了,放在这里占位置影响阅读,附录1有完整脚本,直接copy
如果大家有源码的,在src\org\quartz\impl\jdbcjobstore这个目录下面,也可以解压maven依赖,一样可以获取到SQL脚本

创建好的就这么11张表
在这里插入图片描述

1.2 maven依赖

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-quartz</artifactId>
 </dependency>
 <dependency>
     <groupId>com.mchange</groupId>
     <artifactId>c3p0</artifactId>
     <version>0.10.0</version>
 </dependency>

我这里引入c3p0是因为会报连接错误,但是网上其他文章不用引入这个依赖,我猜测可能是版本不一样,然后某个Maven依赖冲突导致的。

1.3 代码实现

创建job的方式有两种,一种是比较古老的,用scheduler去绑定job和config,由于配置复杂,不是很推荐,推荐用spring bean的自动装配。

1.3.1 创建一个job

@DisallowConcurrentExecution注解是关键,用于集群中单个job只能被一个实例机器执行。

//禁止并发执行
@DisallowConcurrentExecution
//更新JobDataMap 副本
@PersistJobDataAfterExecution
public class ZedJob extends QuartzJobBean {
    private static final Logger logger = LoggerFactory.getLogger(ZedJob.class);

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        logger.info("我是ZedJob");
    }
}

1.3.1 为job设置trigger

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail jobDetail(){
        return JobBuilder.newJob(ZedJob.class)
                // 指定任务的名称
                .withIdentity("zedJob")
                // 任务描述
                .withDescription("任务描述:这是一个任务")
                // 每次任务执行后进行存储
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger trigger() {
        //创建触发器
        SimpleScheduleBuilder simpleScheduleBuilder1 = SimpleScheduleBuilder.repeatSecondlyForever(5);
        return TriggerBuilder.newTrigger()
                // 绑定工作任务
                .withIdentity("zedJob")
                .forJob(jobDetail())
                // 每隔 5 秒执行一次 job
                .withSchedule(simpleScheduleBuilder1)
                .build();
    }
}

这里的Schedule常用的有两种,一个是SimpleScheduleBuilder,一个是CronScheduleBuilder,写cron表达式的,大家可以按照需要选取。

1.4 配置文件

上面基本都有注释

spring:
  quartz:
    #存储方式,默认是内存memory
    job-store: jdbc
    #应用关闭时,是否等待定时任务执行完成
    wait-for-jobs-to-complete-on-shutdown: true
    properties:
      org:
        quartz:
          scheduler:
            #相同 Scheduler 名字的节点,形成一个 Quartz 集群
            instanceName: SC_Scheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
#            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            dataSource: quartz_jobs
            #是否集群部署
            isClustered: true
            # 集群检查周期,单位为毫秒,可以自定义缩短时间。当某一个节点宕机的时候,其他节点等待多久后开始执行任务
            clusterCheckinInterval: 5000
          threadPool:
            threadCount: 25 # 线程池大小。默认为 10 。
            threadPriority: 5 # 线程优先级
            class: org.quartz.simpl.SimpleThreadPool # 线程池类型
          dataSource:
            #这个名字是上面的jobStore.dataSource定义的
            quartz_jobs:
              driver: com.mysql.cj.jdbc.Driver
              URL: jdbc:mysql://172.16.72.134:3306/quartz_jobs?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8&useUnicode=true
              user: root
              password: 123456

我这里挑几个比较重要的来说一下:

  • job-store:指定存储方式,如果要部署分布式集群,必须要选择jdbc
  • instanceName:同一个集群,instanceName要一样,quartz在数据库中是用名字来区分是否是一个集群的。
  • isClustered:这是集群的开启开关
  • dataSource:选择数据库集群后,才会有这个配置
  • quartz_jobs:命名记得一致

1.5 启动、测试

1.1 单机

启动单个服务,看看打印,都是正常的。
在这里插入图片描述

1.2 集群

只修改端口,启动两个实例,测试@DisallowConcurrentExecution 并发执行,记得数据库这些配置信息要一致
可以看到,我们第二个实例中,没有任何打印
在这里插入图片描述
我们关闭第一个实例,假装宕机,看看第二个实例能否正常接续工作
在这里插入图片描述
当关闭1后,我们可以看到,示例2中检测到了1的关闭,并且有打印三句话,这三句话的意思翻译一下:

  1. 检测到集群中有一个实例失去连接或者在重启
  2. 扫描是否有其他示例可以接待挂掉的那个主机继续执行任务
  3. 找到了1个实例,去继续执行

所以由此也可以看出quartz集群的能力和容错能力。

2、ElasticJob

ElasticJob把任务命名为作业,等同于任务,job,叫法不同而已,所以下面都用作业来说

2.1 下载zk

  1. 去官网下载最新版本:下载链接

  2. 解压,进入conf 路径下,将文件 zoo_sample.cfg 修改为 zoo.cfg

    mv zoo_sample.cfg zoo.cfg
    
  3. 在zk根目录下创建目录zkData

    mkdir zkData
    
  4. 打开 zoo.cfg 文件,修改 dataDir 路径为新创建的zkData路径

    dataDir=/usr/local/zookeeper/apache-zookeeper-3.9.2-bin/zkData
    
  5. 进入bin目录,启动zk

    ./zkServer.sh start
    
  6. 运行客户端,创建命名空间

    ./zkCli.sh
    
    create /elastic-job-test
    

2.2 新建三个类型的作业

ZedJob:普通的作业
FragmentationJob:分片作业
FlowJob:数据流作业

@Component
public class ZedJob implements SimpleJob {
    private static final Logger logger = LoggerFactory.getLogger(ZedJob.class);

    @Override
    public void execute(ShardingContext shardingContext) {
        logger.info("我是影流之主 Zed");
    }
}
@Component
public class FragmentationJob implements SimpleJob {
    private static final Logger logger = LoggerFactory.getLogger(FragmentationJob.class);

    @Override
    public void execute(ShardingContext shardingContext) {
        logger.info("分片任务");
        switch (shardingContext.getShardingItem()) {
            case 0:
                logger.info("分片0:{}",shardingContext.getShardingParameter());
                break;
            case 1:
                logger.info("分片1:{}",shardingContext.getShardingParameter());
                break;
            case 2:
                logger.info("分片2:{}",shardingContext.getShardingParameter());
                break;
            default:
                break;
        }
    }
}
@Component
public class FlowJob implements DataflowJob<UserInfo> {
    private static final Logger logger = LoggerFactory.getLogger(FlowJob.class);

    @Override
    public List<UserInfo> fetchData(ShardingContext shardingContext) {
        List<UserInfo> foos = new ArrayList<>();
        double random = Math.random();
        if (random > 0.5) {
            logger.info("fetchData------ {}", random);
            UserInfo foo = new UserInfo();
            foo.setUserName("小道仙");
            foos.add(foo);
        }
        return foos;
    }

    @Override
    public void processData(ShardingContext shardingContext, List<UserInfo> list) {
        logger.info("收到流数据");
        list.forEach(i -> logger.info("name为:{}", i.getUserName()));
    }
}

2.3 配置文件

大多都有注释,大家看看就行,其中shardingTotalCount必填,等待重试的间隔也很重要。

elasticjob:
  regCenter:
    #zookeeper 的ip:port
    serverLists: 172.16.72.133:2181
    #名命空间,和前面zk里面创建的一样就行
    namespace: elastic-job-test
    base-sleep-time-milliseconds: 10000
    # 等待重试的间隔时间的最大值,这个很重要,不然项目启动会出现timeout的报错
    max-sleep-time-milliseconds: 30000
  jobs:
    #我们创建的三个任务,在这里进行配置
    zedJob:
      #定时任务的全路径名
      elasticJobClass: com.wq.elasticjob.ZedJob
      #定时任务执行的cron表达式
      cron: 0/5 * * * * ?
      #分片数量
      shardingTotalCount: 1
    fragmentationJob:
      #定时任务的全路径名
      elasticJobClass: com.wq.elasticjob.FragmentationJob
      #定时任务执行的cron表达式
      cron: 0/10 * * * * ?
      #分片数量
      shardingTotalCount: 3
      #这是分片参数,代码中获取,记得加引号,不然获取不到
      shardingItemParameters: "0=text,1=image,2=video"
    flowJob:
      #定时任务的全路径名
      elasticJobClass: com.wq.elasticjob.FlowJob
      #定时任务执行的cron表达式
      cron: 0/10 * * * * ?
      #分片数量
      shardingTotalCount: 1

2.4 启动项目,测试数据

我们先看看普通的作业,这个没可说的,看看能否正常运行就好
在这里插入图片描述
接下来重点说说分片任务,以及流数据任务。

2.5 分片作业(集群测试)

2.5.1 官方的三个分片策略:

AverageAllocationJobShardingStrategy:根据分片项平均分片
如果分片不能整除,则不能整除的多余分片将依次追加到序号小的服务器。策略举例:
假设有3台服务器,
分成9片,则每台服务器分到的分片是:1【0,1,2】,2【3,4,5】,3【6,7,8】
分成8片,则每台服务器分到的分片是:1【0,1,6】,2【2,3,7】,3【4,5】
分成10片,则每台服务器分到的分片是:1【0,1,2】,2【3,4,5】,3【6,7,8】

OdevitySortByNameJobShardingStrategy:根据作业名称哈希值的奇偶数决定按照作业服务器 IP 升序或是降序的方式分片
缺点是,一旦分片数小于作业服务器数,作业将永远分配至IP地址靠前的服务器,导致IP地址靠后的服务器空闲

RotateServerByNameJobShardingStrategy:根据作业名称轮询分片
假设有3台服务器,顺序为 【0, 1, 2】,如果作业名的哈希值根据作业分片总数取模为 1, 作业节点顺序变为 【1, 2, 0】。

2.5.2 启动三个实例,模拟集群

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回顾一下,我们分片任务的配置:shardingItemParameters: “0=text,1=image,2=video”,总数有三个,启动三个实例,刚好一个机器一个,而且参数也能打印出来,而且分片策略,默认采用的是平均分片。

2.5.3 模拟集群故障

现在我把三个集群中index为0的干掉,看看效果。
在这里插入图片描述
在这里插入图片描述
通过打印可以看到,本来三个集群一人一个,现在挂掉了一个,其中一个服务还是一个,另一个服务则是拥有了两个分片,到这里也就验证结束

2.6 数据流作业

回到我们流数据任务的代码:

    @Override
    public List<UserInfo> fetchData(ShardingContext shardingContext) {
        List<UserInfo> foos = new ArrayList<>();
        double random = Math.random();
        if (random > 0.5) {
            logger.info("fetchData------ {}", random);
            UserInfo foo = new UserInfo();
            foo.setUserName("小道仙");
            foos.add(foo);
        }
        return foos;
    }

    @Override
    public void processData(ShardingContext shardingContext, List<UserInfo> list) {
        logger.info("收到流数据");
        list.forEach(i -> logger.info("name为:{}", i.getUserName()));
    }

我们实现的DataflowJob接口,覆盖了两个方法,一个fetchData,一个processData

  • fetchData:对数据作处理
  • processData:如果fetchData方法中产生了数据(数据发生了改变),则会携带者数据进入这个方法

我们看看日志打印,当我们在fetchData中设置了userName后,就会进入processData方法,就会拿到我们设置的userName属性
在这里插入图片描述

2.7 控制台console

  1. 选择对应版本下载
    控制台官网下载:https://www.apache.org/dyn/closer.cgi/shardingsphere/elasticjob-ui-3.0.0-RC1/apache-shardingsphere-elasticjob-3.0.0-RC1-lite-ui-bin.tar.gz
  2. 解压后进入bin目录,选择start.bat双击启动
  3. 网页访问localhost:8088/,用户名/密码:root/root
  4. 按照下图三个步骤配置zk注册中心,然后就能使用了
    在这里插入图片描述

3、xxl-job

截止本文编写时候,xxl的最新Maven版本为2.4.1,所以我们就用最新的

我们把xxl-job看做两部分,一部分是搭建调度中心,一部分是代码中实现集成

1.搭建调度中心(必须要搭)

下载源码,仓库地址:
gitee地址:https://gitee.com/xuxueli0323/xxl-job/blob/master/doc/db/tables_xxl_job.sql
GitHub地址:https://github.com/xuxueli/xxl-job

1.1 创建好数据库

脚本在这个目录下面:doc/db/tables_xxl_job.sql

调度中心支持集群部署,集群情况下各节点务必连接同一个mysql实例;
如果mysql做主从,调度中心集群节点务必强制走主库;

这里给出所有数据库的作用:

  • xxl_job_lock:任务调度锁表;
  • xxl_job_group:执行器信息表,维护任务执行器信息;
  • xxl_job_info:调度扩展信息表: 用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等;
  • xxl_job_log:调度日志表: 用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等;
  • xxl_job_log_report:调度日志报表:用户存储XXL-JOB任务调度日志的报表,调度中心报表功能页面会用到;
  • xxl_job_logglue:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;
  • xxl_job_registry:执行器注册表,维护在线的执行器和调度中心机器地址信息;
  • xxl_job_user:系统用户表;

不想去找的直接文末附录二有完整的SQL脚本,直接copy

1.2 修改application.properties文件

修改server.port为自己需要的
修改spring.datasource.url,数据库配置为自己的
修改spring.mail.username和from为自己的实际邮箱地址(不修改也可以,这个就是通知用的)

1.3 修改logback.xml文件

将name=“log.path” 这个路径修改为自己的路径,并且在路径下创建xxl-job-admin.log文件,如果你不修改用默认的也行。

1.4 启动项目

浏览器访问:localhost:8088/xxl-job-admin/,默认用户名密码为admin,123456
出现下面这个界面则搭建成功
在这里插入图片描述

1.5 打包部署

生产环境下,配置好以后,打包部署到服务器即可

2.springboot项目中集成

2.1 maven依赖

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.1</version>
</dependency>

2.2 配置文件

xxl:
  job:
    admin:
      #如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册
      addresses: http://127.0.0.1:8088/xxl-job-admin
    executor:
      appname: zed-demo
      logpath:
      logretentiondays: 30
      #执行器IP:默认为空表示自动获取IP
      ip: 127.0.0.1
      #默认为9999
      port: 9999
      #优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址
      address:
    #执行器通讯TOKEN [选填]:非空时启用; 要和调度中心服务部署配置的accessToken一致
    accessToken: default_token

2.3 注入config

这个config是官方源码,内容一样,但是必须要copy进我们自己的项目里

@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;


    @Bean
    public 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();
     */

}

2.4 新增job

这里用最常用最推荐的一种写法,就是将任务绑定在方法上,@XxlJob注解标明每一个任务。当然还有绑定在Bean上的,不过这样就会写很多Bean,用方法的话,一个类就够了。

@Component
public class XxlJobFactory {
    private static Logger logger = LoggerFactory.getLogger(XxlJobFactory.class);

    @XxlJob("zedJobTest")
    public void zedJobTest(){
        logger.info("这是zedJobTest");
    }
}

2.5 简单归纳一下

我们在springBoot项目集成的时候,有几个比较关键的点,我在这里给大家总结一下,免得绕进去。

  1. 第一步搭建的调度中心,你可以理解为es job 的zookeeper一样,或者nacos这样的角色,它是一个注册中心,是整个框架的驱动核心,采用db的方式来进行服务的注册。
  2. xxl.job.admin:这个在springboot中的配置,就是配置第一步的调度中心的,地址前面一定要加http
  3. xxl.job.executor:这个是接下来要说的执行管理器,去执行任务的executor,它配置在我们的网页控制台中。这个的ip和端口是单独分开的,专门控制executor
  4. 很多配置都是空的,因为都有默认的,但是我们在注入XxlJobConfig的时候必须要用,所以空着就空着

3.结合控制台使用

3.1 配置执行管理器

新增一个执行管理器,这就是我们前面说到的,xxl.job.executor配置所控制的东西,它有一个默认的,我们不用默认的用自己的。
在这里插入图片描述
在这里插入图片描述
这个appName一定要和xxl.job.executor里面的appname一样,一般默认自动注册就好,如果自动注册不行,就手动录入,输入我们的ip和端口,这个ip和端口,也一定要和xxl.job.executor.port一致

3.2 新增一个任务

在这里插入图片描述
这里面最主要注意三个点,就是我标出来的这三个
在这里插入图片描述

  1. 执行器选择我们第二步中创建的执行器
  2. 运行模式常用Bean
  3. 然后jobHander要和代码中,注解@XxlJob中的Value一致

其他的根据自己需求改写就行

3.3 启动

在这里插入图片描述
这里选择执行一次,忽略corn表达式,只执行一次,选择下面的启动,才会走corn表达式逻辑。

执行一次这里,可以加任务参数和重新指定机器地址,由于我们执行器里面配置好了的,所以不用填写让它自动获取。
在这里插入图片描述

看看控制台打印,任务是调动成功了的。
在这里插入图片描述
然后数据库里,也可以看到我们新增的任务,还有其他表的信息
在这里插入图片描述

4.用分片任务,来验证xxl-job的集群功能

4.1 修改端口

修改springboot的端口和executor的port,启动三个实例

4.2 新建执行器

新建一个执行器fragmentatio
在这里插入图片描述
这里自动注册如果获取不到,我们就手动录入,三个不同的端口之间用逗号分隔。外面查看也是正确的。
在这里插入图片描述

4.3 新建任务代码+任务

    /**
     * 2、分片广播任务
     */
    @XxlJob("shardingJobHandler")
    public void shardingJobHandler(String param) throws Exception {
        int shardTotal = XxlJobHelper.getShardTotal();
        int index = XxlJobHelper.getShardIndex();
        logger.info("总共:{}个分片,当前的index为:{}", shardTotal, index);
    }

记得路由策略选择分片广播
在这里插入图片描述

4.4 运行一次验证

我们看看控制台打印,我这里贴一个就行了,三个实例,总共3个分片,index为0,1,2,大家可以根据分片总数和index,自己去实现分片处理逻辑,比如取模。
在这里插入图片描述

5.对Quartz的优化

xxl-job,是徐雪里基于Quartz改进来的,Quartz有下面几点不足:

  1. 调用API的的方式操作任务,不人性化;
  2. 需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
  3. 调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况下,此时调度系统的性能将大大受限于业务;
  4. quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。

XXL-JOB弥补了quartz的上述不足之处

4、结语

都看到这里了,给我点个赞和关注不过分吧,如果你只是使用分布式任务调度框架,本文的示例绝对够用,如果你们项目很庞大而且很复杂,那么还要去官网查看更详细的配置。

本文完整项目代码GitHub地址
https:https://github.com/wangqing-github/DubboAndNacos.git
ssh:git@github.com:wangqing-github/DubboAndNacos.git
有三个分支,代码都是独立的,大家可以从主干切换。
在这里插入图片描述

5、附录1

Quartz的数据库SQL脚本:

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#

DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;


CREATE TABLE QRTZ_JOB_DETAILS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
    IS_DURABLE VARCHAR(1) NOT NULL,
    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    NEXT_FIRE_TIME BIGINT(13) NULL,
    PREV_FIRE_TIME BIGINT(13) NULL,
    PRIORITY INTEGER NULL,
    TRIGGER_STATE VARCHAR(16) NOT NULL,
    TRIGGER_TYPE VARCHAR(8) NOT NULL,
    START_TIME BIGINT(13) NOT NULL,
    END_TIME BIGINT(13) NULL,
    CALENDAR_NAME VARCHAR(200) NULL,
    MISFIRE_INSTR SMALLINT(2) NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_SIMPLE_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    REPEAT_COUNT BIGINT(7) NOT NULL,
    REPEAT_INTERVAL BIGINT(12) NOT NULL,
    TIMES_TRIGGERED BIGINT(10) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CRON_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    CRON_EXPRESSION VARCHAR(200) NOT NULL,
    TIME_ZONE_ID VARCHAR(80),
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    STR_PROP_1 VARCHAR(512) NULL,
    STR_PROP_2 VARCHAR(512) NULL,
    STR_PROP_3 VARCHAR(512) NULL,
    INT_PROP_1 INT NULL,
    INT_PROP_2 INT NULL,
    LONG_PROP_1 BIGINT NULL,
    LONG_PROP_2 BIGINT NULL,
    DEC_PROP_1 NUMERIC(13,4) NULL,
    DEC_PROP_2 NUMERIC(13,4) NULL,
    BOOL_PROP_1 VARCHAR(1) NULL,
    BOOL_PROP_2 VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_BLOB_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    BLOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CALENDARS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    CALENDAR_NAME  VARCHAR(200) NOT NULL,
    CALENDAR BLOB NOT NULL,
    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP  VARCHAR(200) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_FIRED_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    ENTRY_ID VARCHAR(95) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    FIRED_TIME BIGINT(13) NOT NULL,
    SCHED_TIME BIGINT(13) NOT NULL,
    PRIORITY INTEGER NOT NULL,
    STATE VARCHAR(16) NOT NULL,
    JOB_NAME VARCHAR(200) NULL,
    JOB_GROUP VARCHAR(200) NULL,
    IS_NONCONCURRENT VARCHAR(1) NULL,
    REQUESTS_RECOVERY VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);

CREATE TABLE QRTZ_SCHEDULER_STATE
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);

CREATE TABLE QRTZ_LOCKS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME  VARCHAR(40) NOT NULL,
    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);


commit;

6、附录2

xxl的sql脚本

CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `xxl_job`;

SET NAMES utf8mb4;

CREATE TABLE `xxl_job_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_desc` varchar(255) NOT NULL,
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `author` varchar(64) DEFAULT NULL COMMENT '作者',
  `alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
  `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
  `schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
  `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
  `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
  `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
  `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
  `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
  `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
  `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
  `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '执行器主键ID',
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
  `executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
  `trigger_code` int(11) NOT NULL COMMENT '调度-结果',
  `trigger_msg` text COMMENT '调度-日志',
  `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
  `handle_code` int(11) NOT NULL COMMENT '执行-状态',
  `handle_msg` text COMMENT '执行-日志',
  `alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
  PRIMARY KEY (`id`),
  KEY `I_trigger_time` (`trigger_time`),
  KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_log_report` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
  `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
  `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
  `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_logglue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_id` int(11) NOT NULL COMMENT '任务,主键ID',
  `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
  `glue_source` mediumtext COMMENT 'GLUE源代码',
  `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_registry` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `registry_group` varchar(50) NOT NULL,
  `registry_key` varchar(255) NOT NULL,
  `registry_value` varchar(255) NOT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_group` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
  `title` varchar(12) NOT NULL COMMENT '执行器名称',
  `address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
  `address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '账号',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
  `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
  PRIMARY KEY (`id`),
  UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `xxl_job_lock` (
  `lock_name` varchar(50) NOT NULL COMMENT '锁名称',
  PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');

commit;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java微信小程序的水果销售系统详细设计和实现(源码+lw+部署文档+讲解等)

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

创客项目秀 | 基于使用 XIAO BLE Sense 和 Edge Impulse 的宠物活动跟踪器

今天为大家带来的是来自美国的创作者米顿-达斯的作品:宠物活动跟踪器.这个装置主要是为宠物主人提供关于宠物日常活动量的详尽数据&#xff0c;还能够根据宠物的独特需求&#xff0c;提供个性化的健康建议和活动指导。 项目背景 为了全面促进宠物的健康与活力&#xff0c;采用…

Python 数值计算与数值分析基础

Python 数值计算与数值分析基础 示例演示 当涉及到Python数值计算和数值分析时&#xff0c;下面是20个示例&#xff0c;涵盖了一些常见的用法&#xff1a; 1.数值积分&#xff1a; 在 Python 中&#xff0c;你可以使用 scipy.integrate 模块中的 quad 函数来进行数值积分 …

【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动、C应用函数库开发 devmem命令测试(正点原子STM32MP135文档BUG)

【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动、C应用函数库开发 devmem命令测试&#xff08;正点原子STM32MP135文档BUG&#xff09; 【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动 devmem命令测试 gitee库&#xff1a; https://gitee.com/Mike_Zho…

记一次Netty模拟压测应用开发

背景 最近需要开发一个上游端模拟数据推送&#xff0c;测试高流量下下游的业务功能处理速度&#xff0c;大致架构如下 准备工作 构造消息体&#xff0c;由于是模拟大量数据推送并没有业务逻辑&#xff0c;所以我们使用池化的directBuffer增加推送消息以及减少创建和消费buf…

13.1 Linux_网络编程_TCP/UDP

字节序 1、概述 什么是字节序&#xff1a; 字节序就是字节的存储顺序&#xff0c;分为大端字节序和小端字节序。 大端字节序&#xff1a;低地址存高位&#xff08;网络&#xff09;小端字节序&#xff1a;低地址存低位&#xff08;主机&#xff09; 检验主机字节序模式&…

Java @RequestPart注解:同时实现文件上传与JSON对象传参

RequestPart注解&#xff1a;用于处理multipart/form-data请求的一部分&#xff0c;通常用于文件上传或者处理表单中的字段。 java后端举例&#xff1a; PostMapping("/fileTest")public AjaxResult fileTest(RequestPart("file") MultipartFile file,Req…

【时间之外】IT人求职和创业应知【10】

认知决定你的赚钱能力。以下是今天可能影响你求职和创业的热点新闻: 今日关键字:SFISF【互换便利】 1. 央行推出股票回购增持再贷款,科技股全线爆发 新闻概要: 2024年10月18日,央行等三部门联合发布《关于设立股票回购增持再贷款有关事宜的通知》,同时表示年底有进一步…

基于GeoScene Pro的开源数据治理与二维制图规范化处理智能工具箱

内容导读 本文描述的是一个基于GeoScene Pro4.0/ArcGIS3.1 Pro平台的开源数据治理与二维制图规范化处理智能工具箱(免费试用&#xff0c;文末有获取方式)&#xff0c;旨在解决GIS应用中数据转换、检查、治理和制图数据规范化处理方面的问题。 工具箱结合了Geoscene/ArcGIS Pr…

Asp.net Core SignalR 跨域设置(Furion)

前端VUE2.0/3.0 后端NET8.0/NET6.0 框架Furion 前端安装SignalR通信库&#xff0c;下面任意一条安装指令都可以&#xff0c;根据项目自行选择 npm install microsoft/signalr yarn add microsoft/signalr前端使用 <script> import { HubConnectionBuilder } from micr…

[Halcon矩阵] 通过手眼标定矩阵计算相机旋转角度

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

SpringBoot教程(三十二) | SpringBoot集成Skywalking链路跟踪

SpringBoot教程&#xff08;三十二&#xff09; | SpringBoot集成Skywalking链路跟踪 一、Skywalking是什么&#xff1f;二、Skywalking与JDK版本的对应关系三、Skywalking下载四、Skywalking 数据存储五、Skywalking 的启动六、部署探针前提&#xff1a; Agents 8.9.0 放入 项…

C#从零开始学习(用unity探索C#)(unity Lab1)

初次使用Unity 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp Unity的下载与安装 从 unity官网下载Unity Hub Unity的使用 安装后,注册账号,下载unity版本,然后创建3d项目 设置窗口界面布局 3D对象的创建 点击对象,然后点击Move Guzmo,就可以拖动…

云服务解决方案,针对小程序、网页、HTML5等轻量化视频解决方案

无论是社交媒体上的短视频分享&#xff0c;还是企业官网中的产品展示&#xff0c;亦或是教育平台上的互动课程&#xff0c;高质量、易制作的视频内容正以前所未有的速度改变着我们的生活方式和工作模式。然而&#xff0c;面对多样化的发布平台和日益增长的个性化需求&#xff0…

Python从0到100(六十五):Python OpenCV-图像运颜色转换及几何变换

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

.net 根据html的input type=“week“控件的值获取星期一和星期日的日期

初始化 "week" 控件值&#xff1a; //MVC部分 public ActionResult WeeklyList() {int weekNo new GregorianCalendar().GetWeekOfYear(System.DateTime.Now, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday);string DefaultWeek DateTime.No…

ssm医院交互系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 摘要 I Abstract II 1绪论 1 1.1研究背景与意义 1 1.1.1研究背景 1 1.1.2研究意义 1 1.2国内外研究…

python+大数据+基于spark的短视频推荐系统【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

Mybatis框架 day1018

ok了家人们书接上文&#xff0c;我们继续学习mybatis框架 五.数据输出 5.7 属性和字段的映射 5.7.1 别名映射 将数据库表的字段别名设置成和实体类属性一致。 <!-- 给每一个字段设置一个别名&#xff0c;让别名和Java实体类中 属性名一致 --> <select id"fi…

赋能特大城市水务数据安全高速运算,深圳计算科学研究院YashanDB数据库系统斩获“鼎新杯”二等奖

第三届“鼎新杯”数字化转型应用优秀案例评选结果日前正式公布&#xff0c;深圳计算科学研究院联合深圳市环境水务集团有限公司申报的《深圳环境水务国产数据库YashanDB&#xff0c;赋能特大城市水务数据安全高速运转》案例&#xff0c;经过5个多月的评审&#xff0c;从4000申报…