范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

SpringBootQuartz实现动态定时任务(非数据库模式)

  在日常工作中,经常会遇到一些定时任务,比如定时发邮件、异构数据库同步数据等。目前比较常用的是SpringBoot+Quartz实现动态定时任务的Web项目,这种模式通常需要建立定时任务相关的表。本例为SpringBoot+Quartz实现动态定时任务的非Web项目,可以根据项目启动的参数来决定执行配置文件中的某些任务,并且所有的任务都配置在配置文件中,从而避免建数据库的麻烦。
  一、流程说明:
  程序启动时注册QuartzConfig配置类(该配置类将读取quartz.properties中的配置、任务信息、初始化调度器、job实例工厂等),然后通过CommandLineRunner的实现类,重写其run()方法,该方法根据启动传入的参数判断哪些配置任务信息需要进行执行,并调用QuartzManager工具类启动相应任务。
  二、代码实例:
  1.引入相关依赖                         org.springframework.boot             spring-boot-starter                                         org.springframework.boot             spring-boot-starter-quartz                                        org.projectlombok             lombok             provided		                                        cn.hutool             hutool-all             5.1.0                                        org.springframework.boot             spring-boot-starter-test             test                                                                org.springframework.boot                 spring-boot-maven-plugin                                                       true                                            
  2.【必须】quartz框架配置文件quartz.properties,主要配置quartz线程池、任务列表等
  说明:由于本例采用非Web项目,故application.yml配置文件可以不配。实际业务中可以配置些动态数据源,实现定时任务的业务逻辑 #[非必须]设置调度器实例名称,默认QuartzScheduler org.quartz.scheduler.instanceName=quartz-scheduler #[非必须]设置调度器实例ID,默认值NON_CLUSTERED org.quartz.scheduler.instanceId=AUTO  #[必须]设置线程池实现类(一般使用SimpleThreadPool定长线程池) org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool #[必须]设置线程数(无默认值,一般设置为1-100的整数) org.quartz.threadPool.threadCount=5 #[非必须]设置线程的优先级(最大为9,最小为1,默认为5) org.quartz.threadPool.threadPriority=5 #[非必须]设置是否为守护线程(默认为true) org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true #[非必须]线程前缀(默认为调度器实例名称_Worker) org.quartz.threadPool.threadNamePrefix=quartz-scheduler-thread  #[非必须]设置schedule相关信息存储方法(默认存储在内存中) org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore #[非必须]最大能忍受的触发超时时间(默认为60秒) org.quartz.jobStore.misfireThreshold=60000  ##################################配置定时任务################################## #jobName:任务名称,建议英文或任务描述拼音码首拼[必须] #jobDesc:任务中文描述[必须] #classMethod:任务执行的方法[必须] #jobCron:任务的Cron表达式[必须] #第1个定时任务 springboot.quartz.scheduledJobs[0].jobName=job1 springboot.quartz.scheduledJobs[0].jobDesc=测试任务1 springboot.quartz.scheduledJobs[0].classMethod=com.wwu.jobs.FirstJob springboot.quartz.scheduledJobs[0].jobCron=0/10 * * * * ?  #第2个定时任务 springboot.quartz.scheduledJobs[1].jobName=job2 springboot.quartz.scheduledJobs[1].jobDesc=测试任务2 springboot.quartz.scheduledJobs[1].classMethod=com.wwu.jobs.SecondJob springboot.quartz.scheduledJobs[1].jobCron=0/15 * * * * ?  #第3个定时任务 springboot.quartz.scheduledJobs[2].jobName=job3 springboot.quartz.scheduledJobs[2].jobDesc=测试任务3 springboot.quartz.scheduledJobs[2].classMethod=com.wwu.jobs.ThirdJob springboot.quartz.scheduledJobs[2].jobCron=0 05 19 ? * 2
  3.【非必须】slf4j日志分级切割配置文件logback-spring.xml<?xml version="1.0" encoding="UTF-8"?>                                                                                                                       ${sysLog.pattern}                                                                          INFO                          ACCEPT                          DENY                           ${sysLog.logDir}/${sysLog.logName}_info.txt                                            ${sysLog.logDir}/${sysLog.logName}_info_%d{yyyyMMdd}_%i.txt                          ${sysLog.maxHistory}                                           ${sysLog.maxFileSize}                                                     ${sysLog.fileCharset}             ${sysLog.pattern}                                                                     WARN                           ${sysLog.logDir}/${sysLog.logName}_error.txt                                            ${sysLog.logDir}/${sysLog.logName}_error_%d{yyyyMMdd}_%i.txt                          ${maxHistory}                                           ${sysLog.maxFileSize}                                                     ${sysLog.fileCharset}             ${sysLog.pattern}                                           0                  ${sysLog.queueSize}                            0         ${sysLog.queueSize}                                                                                                 
  4.创建任务实体类ScheduledJob.java,在初始化任务列表时创建任务明细(JobDetail)及触发器(Trigger)package com.wwu.entity;  import lombok.Data;  /**  * @description: 任务实体类  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 16:53  */ @Data public class ScheduledJob {     /** 任务ID */     private String jobId;     /** 任务名称 */     private String jobName;     /** 任务描述 */     private String jobDesc;     /** 任务表达式 */     private String jobCron;     /** 任务表达式中文 */     private String jobCronZh;     /**  任务分组编码*/     private String jobGroup;     /** 任务分组名称 */     private String jobGroupName;     /** 执行方法 */     private String classMethod;     /** 任务执行状态(Y,执行成功;N,执行失败;空,未执行) */     private String jobStatus;     /** 任务可用状态(Y:可用;N:不可用) */     private String enabledFlag;     /** 下次执行时间 */     private String nextExecTime; }
  5.创建quartz配置类quartzConfig.java,主要用来配置线程池、调度器、job实例工厂等package com.wwu.config;  import com.wwu.entity.ScheduledJob; import lombok.Data; import org.quartz.Scheduler; import org.quartz.spi.JobFactory; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import javax.annotation.Resource; import java.io.IOException; import java.util.List; import java.util.Properties;  /**  * @description: quartz配置类,配置线程池、调度器、job实例工厂等  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 18:08  */ @Data @Configuration @PropertySource("classpath:quartz.properties") @ConfigurationProperties(prefix = "springboot.quartz") public class QuartzConfig {     /** 注入quartz.properties配置文件中的任务 */     private List scheduledJobs;     @Resource     private JobFactory jobFactory;      /**      * @description: SchedulerFactoryBean工厂      * @return org.springframework.scheduling.quartz.SchedulerFactoryBean      * @author 一蓑烟雨      * @date 2023/4/16 18:10     */     @Bean     public SchedulerFactoryBean schedulerFactoryBean() {         //创建 SchedulerFactoryBean 实例         SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();         try {             //设置是否覆盖已存在的job,为True表示有相同名称和分组的触发器和任务存在时则替换             schedulerFactoryBean.setOverwriteExistingJobs(true);             //设置是否自动启动Scheduler             schedulerFactoryBean.setAutoStartup(true);             //设置quartz属性             schedulerFactoryBean.setQuartzProperties(quartzProperties());             //设置任务调度器             schedulerFactoryBean.setJobFactory(jobFactory);         } catch (Exception e) {             e.printStackTrace();         }         return schedulerFactoryBean;     }      /**      * @description: 读取quartz配置文件中配置相关属性      * @return java.util.Properties      * @author 一蓑烟雨      * @date 2023/4/17 17:18      */     @Bean     public Properties quartzProperties() throws IOException {         PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();         propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));         //在quartz.properties中的属性被读取并注入后再初始化对象         propertiesFactoryBean.afterPropertiesSet();         return propertiesFactoryBean.getObject();     }     /**      * @description: 初始化schedule任务调度器      * @return org.quartz.Scheduler      * @author 一蓑烟雨      * @date 2023/4/16 18:12     */     @Bean     public Scheduler scheduler() {         return schedulerFactoryBean().getScheduler();     } }
  6.创建job实例工厂JobFactory.javapackage com.wwu.config;  import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.scheduling.quartz.AdaptableJobFactory; import org.springframework.stereotype.Component; import javax.annotation.Resource;  /**  * @description: 创建job实例工厂  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 18:31  */ @Component public class JobFactory extends AdaptableJobFactory {     @Resource     private AutowireCapableBeanFactory capableBeanFactory;      @Override     protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {         //调用父类的方法         Object jobInstance = super.createJobInstance(bundle);         //进行注入         capableBeanFactory.autowireBean(jobInstance);         return jobInstance;     } }
  7.创建CommandLineRunner接口的实现类QuartzCommandRunner.java,作用为启动项目时预先加载配置文件中的所有定时任务,并根据启动参数启动相应任务package com.wwu.config;  import com.wwu.entity.ScheduledJob; import lombok.extern.slf4j.Slf4j; import org.quartz.SchedulerException; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.List;  /**  * @description: 启动项目时预先加载配置文件中的所有定时任务,并根据启动参数启动相应任务  * CommandLineRunner中的Order表示在项目启动时预先加载的类  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 18:13  */ @Slf4j @Component @Order(1) public class QuartzCommandRunner implements CommandLineRunner {     @Resource     private QuartzManager quartzManager;     @Resource     private QuartzConfig quartzConfig;      /**      * @description: 重写run方法      * @param [args]      * @return void      * @author 一蓑烟雨      * @date 2023/4/17 15:37     */     @Override     public void run(String... args) throws Exception {         try {             //初始化需要启动的任务列表             List jobList = initSchedule(args);             for (ScheduledJob scheduledJob : jobList) {                 //执行任务                 quartzManager.startJob(scheduledJob);             }         } catch (Exception e) {             e.printStackTrace();         }     }      /**      * @description: 初始化需要执行的任务列表      * @param [args]      * @return java.util.List      * @author 一蓑烟雨      * @date 2023/4/17 15:37     */     public List initSchedule(String... args) throws SchedulerException {         List jobs = new ArrayList();         try {             log.info("...根据参数加载配置文件quartz.properties中任务列表开始...");             //1.遍历启动程序时传入的接口类型参数             String[] typeParam = null;             for (String arg : args) {                 if (arg.startsWith("type")){                     typeParam =  arg.substring(5).split(",");                     break;                 }             }             //2.遍历quartz.properties配置文件中任务列表             for (ScheduledJob scheduledJob : quartzConfig.getScheduledJobs()) {                 //如果启动传入了参数,则按照参数加载启动任务                 if (typeParam != null && typeParam.length > 0) {                     //遍历参数值和任务列表,若相同则加入到启动任务列表中                     Arrays.stream(typeParam).forEach(param -> {                         if (param.trim().equals(scheduledJob.getJobName())) {                             jobs.add(scheduledJob);                             log.info("......" + scheduledJob);                         }                     });                 } else {                     //没有启动参数,默认启动配置文件中的所有任务                     jobs.add(scheduledJob);                     log.info("......" + scheduledJob);                 }             }             log.info("......共加载{}条任务需要执行......", jobs.size());         } catch (Exception e) {             e.printStackTrace();         }         log.info("...根据参数加载配置文件quartz.properties中任务列表结束...");         return jobs;     } }
  8.创建quartz定时任务工具类QuartzManager.java,对任务进行管理(创建、启动、修改、删除、暂停)package com.wwu.config;  import com.wwu.entity.ScheduledJob; import org.quartz.*; import org.quartz.impl.matchers.GroupMatcher; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Set;  /**  * @description: quartz定时任务工具类,对任务进行管理(创建、启动、修改、删除、暂停)  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 17:11  */ @Component public class QuartzManager {     /** 注入QuartzConfig中定义的任务调度器scheduler */     @Resource     private Scheduler scheduler;      /**      * @description: 获取所有任务信息      * @return java.util.List      * @author 一蓑烟雨      * @date 2023/4/16 18:59     */     public List getAllJobInfo() throws SchedulerException {         List jobList = new ArrayList();         GroupMatcher matcher = GroupMatcher.anyJobGroup();         Set jobKeys = scheduler.getJobKeys(matcher);         for(JobKey jobKey: jobKeys){             List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);             for(Trigger trigger: triggers){                 ScheduledJob job = new ScheduledJob();                 job.setJobName(jobKey.getName());                 job.setJobGroup(jobKey.getGroup());                 job.setJobDesc(trigger.getDescription());                 Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());                 job.setJobStatus(triggerState.name());                 if(trigger instanceof  CronTrigger){                     CronTrigger cronTrigger= (CronTrigger) trigger;                     job.setJobCron(cronTrigger.getCronExpression());                 }                 jobList.add(job);             }         }         return jobList;     }      /**      * @description: 获取某个任务的信息      * @param scheduledJob      * @return java.lang.String      * @author 一蓑烟雨      * @date 2023/4/16 18:07     */     public String getJobInfo(ScheduledJob scheduledJob) throws SchedulerException {         TriggerKey triggerKey = new TriggerKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         System.out.println("triggerKey:"+triggerKey);         CronTrigger cronTrigger= (CronTrigger) scheduler.getTrigger(triggerKey);         return String.format("time:%s,state:%s",cronTrigger.getCronExpression(),                 scheduler.getTriggerState(triggerKey).name());     }      /**      * @description: 获取任务数量      * @return java.lang.String      * @author 一蓑烟雨      * @date 2023/4/16 18:07      */     public int getJobSize() throws SchedulerException {         GroupMatcher matcher = GroupMatcher.anyJobGroup();         Set jobKeys = scheduler.getJobKeys(matcher);         return jobKeys.size();     }      /**      * @description: 获取触发器状态      * @param scheduledJob      * @return NONE:不存在;NORMAL:正常;PAUSED:暂停;COMPLETE:完成;ERROR:错误;BLOCKED:阻塞      * @author 一蓑烟雨      * @date 2023/4/17 18:56      */     public String getTriggerState(ScheduledJob scheduledJob) throws SchedulerException {         TriggerKey triggerKey = new TriggerKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);         return triggerState.name();     }      /**      * @description: 开启某个任务      * @param scheduledJob      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 18:05     */     public void startJob(ScheduledJob scheduledJob) throws Exception {         JobKey jobKey = JobKey.jobKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         //不存在则添加任务         if(!scheduler.checkExists(jobKey)){             addJobTask(scheduledJob);         }         //启动         scheduler.start();     }      /**      * @description: 添加某个任务      * @param scheduledJob      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 18:01     */     public boolean addJobTask(ScheduledJob scheduledJob) throws Exception {         //利用反射机制获取任务执行类         Class<? extends Job> jobClass = (Class<? extends Job>)(Class.forName(scheduledJob.getClassMethod()).newInstance().getClass());         //设置任务明细,调用定义的任务逻辑         JobDetail jobDetail = JobBuilder.newJob(jobClass)                 //添加认证信息(也可通过usingJobData传参数)                 .withIdentity(scheduledJob.getJobName(), scheduledJob.getJobGroup())                 //执行                 .build();         //设置任务触发器,cornTrigger规则定义执行规则         CronTrigger cronTrigger = TriggerBuilder.newTrigger()                 //通过键值对方式向job实现业务逻辑传参数                 .usingJobData("jobDesc",scheduledJob.getJobDesc())                 .usingJobData("jobCron",scheduledJob.getJobCron())                 //添加认证信息                 .withIdentity(scheduledJob.getJobName(), scheduledJob.getJobGroup())                 //程序启动后间隔多久开始执行任务                 .startAt(DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND))                 //执行Cron表达时                 .withSchedule(CronScheduleBuilder.cronSchedule(scheduledJob.getJobCron()))                 //执行                 .build();         //把任务明细和触发器注册到任务调度中         scheduler.scheduleJob(jobDetail, cronTrigger);         return true;     }      /**      * @description: 修改任务的Cron表达式      * @param scheduledJob      * @return boolean      * @author 一蓑烟雨      * @date 2023/4/16 17:46     */     public boolean modifyJob(ScheduledJob scheduledJob) throws SchedulerException{         TriggerKey triggerKey = new TriggerKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         CronTrigger cronTrigger= (CronTrigger) scheduler.getTrigger(triggerKey);         String oldTime = cronTrigger.getCronExpression();         if (!oldTime.equalsIgnoreCase(scheduledJob.getJobCron())){             CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduledJob.getJobCron());             CronTrigger trigger=TriggerBuilder.newTrigger()                     .withIdentity(scheduledJob.getJobName(), scheduledJob.getJobGroup())                     .withSchedule(cronScheduleBuilder)                     .build();             scheduler.rescheduleJob(triggerKey,trigger);             return true;         }else{             return false;         }     }      /**      * @description: 暂停所有任务      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 17:41     */     public void pauseAllJob()throws SchedulerException{         scheduler.pauseAll();     }      /**      * @description: 暂停某个任务      * @param scheduledJob      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 17:41     */     public void pauseJob(ScheduledJob scheduledJob)throws SchedulerException{         JobKey jobKey = JobKey.jobKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         JobDetail jobDetail = scheduler.getJobDetail(jobKey);         if (jobDetail == null) {             return;         }         scheduler.pauseJob(jobKey);     }      /**      * @description: 恢复所有任务      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 17:38     */     public void resumeAllJob()throws SchedulerException{         scheduler.resumeAll();     }      /**      * @description: 恢复某个任务      * @param scheduledJob      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 17:39     */     public void resumeJob(ScheduledJob scheduledJob)throws SchedulerException {         JobKey jobKey = JobKey.jobKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         JobDetail jobDetail = scheduler.getJobDetail(jobKey);         if (jobDetail == null) {             return;         }         scheduler.resumeJob(jobKey);     }      /**      * @description: 删除任务      * @param scheduledJob      * @return void      * @author 一蓑烟雨      * @date 2023/4/16 17:32     */     public void deleteJob(ScheduledJob scheduledJob)throws SchedulerException{         JobKey jobKey = JobKey.jobKey(scheduledJob.getJobName(), scheduledJob.getJobGroup());         JobDetail jobDetail = scheduler.getJobDetail(jobKey);         if (jobDetail == null) {             return;         }         scheduler.deleteJob(jobKey);     } }
  8.依次创建quartz中对应任务的job业务类FirstJob.java、SecondJob.java和ThirdJob.java,这些job业务类需要实现Job接口package com.wwu.jobs;  import lombok.extern.slf4j.Slf4j; import org.quartz.*;  /**  * @description: 定义任务逻辑,需要实现Job接口并重写execute()方法  * DisallowConcurrentExecution注解用来避免同一个任务由于执行时间过长导致并发执行  * @author 一蓑烟雨  * @version 1.0.0  * @date 2023-04-16 19:51  */ @Slf4j @DisallowConcurrentExecution public class FirstJob implements Job {     @Override     public void execute(JobExecutionContext context) throws JobExecutionException {         //获取触发器cronTrigger传递的参数         JobDataMap dataMap = context.getTrigger().getJobDataMap();         log.info("【{}】任务执行开始,执行频率为:{}",dataMap.get("jobDesc"),dataMap.get("jobCron"));         try {             Thread.sleep(30000);         } catch (InterruptedException e) {             e.printStackTrace();         }         log.info("【{}】任务执行结束",dataMap.get("jobDesc"));     } }
  9.在IDEA开发工具配置参数或将项目打包成jar并通过命令行传参执行(如type=job1,job2),即可看到传入参数对应的任务已开始执行

农家院的美食没吃够,在家自己动手来一锅,感觉自己做得更实惠春天是北京出游的最好季节,花红柳绿,景色宜人。每年都会去平谷游玩,今年4月15日又赶上桃花盛开的日子,还品尝到了农家院的美食。老两口不好点菜,服务员真诚推荐有特色的粘卷子,饭菜一锅这里的美食真的是回味无穷每次去昌吉到饭点,就想去回民小吃街转转。这里的饭店都是古色古香的建筑风格,独具特色的平安塔,这里有当地回民正宗风味丸子汤,粉汤,大盘鸡,清炖羊肉,烧烤,羊头羊蹄,拌面,抓饭,凉皮黄小米12Ultra硬件配置细节曝光,部分友商旗舰将成背景板小米12Ultra作为小米品牌的年中压轴旗舰,可谓是引起了广大网友的强烈关注。最新爆料则是曝光该款机型的硬件配置的细节,从曝光细节硬件配置来看,小米在这款机型做到了豪横堆料,部分友亲测好用这三款小米产品便宜值得买提及到小米这个品牌相信大家一定不会陌生,其品牌下的产品最大的特点就是易用性强,同时具有较高的性价比。今天就给大家推荐三款非常值得购买的小米单品,亲测好用。小米夜灯2价格59元首先给孩子没有电视看在家里无所适从,马不停蹄地去县城买了一台电视两年前在网上买的一台网络电视,昨天晚上突然开不了机了,昨天晚上家里就静悄悄地。今天早上,我和女儿七点钟才起床,儿子早早地就起来了,没有电视可以看,他一个人在客厅这里摸摸,那里搞搞,饺子皮变向日葵,米饭变辣条学会厨房魔法,将剩余主食变废为宝欢迎来到回家吃饭厨房魔术大赏!今天的嘉宾和大厨化身魔术师,让冰箱里剩余的主食大变身。把主食吃出花样的民间高手鲁砚波,给大家表演的魔术是把饺子皮变成向日葵,把馒头变成肉夹馍,马上开变发愁,孩子在家不运动可咋整?这份居家运动建议送给您(特别家教977期)为了在特殊时期为家长提供特别的家庭教育指导,全国妇联推出了特殊时期特别家教微信栏目,家长可以通过家庭教育微课学习家庭教育知识。发愁,孩子在家不运动可咋整?这份居家运动建议送给您(特农村足球,中国足球的希望所在当初,高大资本买下农村足球APP,创始人水哥带着两百万离开,3年以后,在高大资本创始人马翻手的操盘下,农村足球APP市值暴涨,让水哥有些后悔。当年,一时风光无限,农村足球APP的创贵州举办以赛促销的旅游商品大赛大赛宣传海报4月20日,记者贵州省文化和旅游厅获悉,由中共贵州省委宣传部贵州省文化和旅游厅贵州省工业和信息化厅贵州省商务厅联合主办的2022多彩贵州旅游商品大赛,将于4月22日在贵已有12省发布今年一季度GDP数据,目前贵州同比增速最高澎湃新闻记者彭艳秋截至目前,已有12个省区市发布2022年一季度GDP数据。从已公布的省份来看,2022年一季度GDP从高到低依次为山东(19926。8亿元)四川(12739。24藏在北京深山里的古村,以出过众多举人而闻名在北京的西边,门头沟区斋堂镇有这样一个村庄,村里出过众多举人,而远近闻名,被称作举人村。很难想象在如此深的大山中,居然还有这样一个村庄。这个村庄古迹众多,村庄古朴,曾经因为拍摄爸爸
GitLab本地代码上传至GitLab1。本地机安装Git官Git网httpsgitscm。comGit官网2。在本地代码目录中,鼠标右键GitBashHere,执行gitinit命令,此命令会在当前目录下创建一个。g6。78万起,档次颜值操控安全一样不落,Airev已锁定爆款?据了解,截至2023年,中国社会汽车保有量已经超3亿辆,庞大的数据不仅体现出了人民生活水平的不断提升,同时印证了国内道路交通环境的复杂现状,出行难停车更难。亟待解决的出行问题靠什么特斯拉官降之后,自主车企如何应对?飞凡汽车我们跟了文凌清图车宇世界网络温馨提示车宇世界,只做最真实的车评。本文为车宇世界行业观察0250之飞凡汽车跟进降价系列文章,为车宇世界原创,转载请注明,侵权必究。2023年1月9日,飞凡汽车荣耀90Pro概念机,集颜值和性能为一体,实力不允许低调声明原创不易,禁止搬运,违者必究!作为华为曾经的手机品牌,荣耀在独立之后,并没有令人失望,反而带来了不少优秀的作品,圈粉了不少的消费者。其中荣耀数字系列是很出彩,不仅具备了颜值,影小米上节目了!这次是因为自研技术好酒不怕巷子深,这句话大家应该也有所耳闻。对于一家手机厂商来说,最好的渠道就是权威媒体,得到权威媒体的报道与认可,就肯定意味着这家厂商在这个领域具备较高的话语权。就在最近的央视焦点Telia为NCC提供面向北欧数字基础设施的全方位服务的ICT解决方案据TelecomTV1月10日报道,Telia瑞典及其子公司TeliaCygate将为北欧建筑公司NCC在瑞典挪威芬兰和丹麦提供全方位服务的ICT解决方案。该解决方案包括用于NCC新能源专属车险出台一年,保费是否还在涨?2021年12月27日,中国保险行业协会新能源汽车商业保险专属条款(试行)正式上线,新能源车和传统燃油车共用同一车险条款成为过去。时间已经过去一年,关于新能源车险保费涨投保难的事情无人驾驶离我们还有多远?这些法律问题须厘清文刘辉法律法规的健全完善,可以使自动驾驶乃至无人驾驶服务模式定价机制等商业化运营的规划更加清晰,也会提振行业经营者和消费者的信心。无人驾驶的立法需求2018年,49岁的伊莱恩赫茨伯缠论原文解读缠中说禅108课教你炒股票4206年在中国证券市场竟然可以亏损累累,最后被迫转战香港,这种奇人绝对是06年市场的最大奇迹,前几天,本ID有幸听闻此人后,真有一睹为快的冲动。当被告知此人为一50岁的北京老男人后,桃江县政策性农业保险承保机构公开竞争性遴选公告湖南广源工程咨询有限公司受益阳市财政局益阳市农业农村局的委托,根据关于加快农业保险高质量发展的指导意见湖南省财政厅湖南省农业农村厅关于印发的通知等有关文件规定,对桃江县政策性农业保碧桂园创投频涉酒业,哪些房企已赴酒局?日前,碧桂园创投孵化酒业公司引发关注,不仅关注到其捕捉酒业赛道的机遇,也引发碧桂园进军酒业的猜想。事实上,房地产企业布局酒业赛道早已不是新鲜事,此前包括星河湾融创绿地等知名房企均有