springboot和quartz整合实现动态定时任务(持久化单节点)

  Quartz是一个完全由java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制,它支持定时任务持久化到数据库,从而避免了重启服务器时任务丢失,支持分布式多节点,大大的提高了单节点定时任务的容错性。springboot在2.0版本以前没有对quartz做自动配置,因此需要我们自己去手动配置,网上找了许多资料,但是大都不能完全满足自己的需要,因此自己整合了一下方便以后参考(copy),整合代码基于springboot1.5.9和quartz2.3.0,过程如下:

  1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>powerx.io</groupId><artifactId>springboot-quartz</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springboot-quartz</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.9.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><druid.version>1.1.5</druid.version><quartz.version>2.3.0</quartz.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!--quartz相关依赖--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>${quartz.version}</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>${quartz.version}</version></dependency><!--定时任务需要依赖context模块--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></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></plugin></plugins></build></project>

  2、整合配置类

  采用jobDetail使用Spring Ioc托管方式来完成整合,我们可以在定时任务实例中使用Spring注入注解完成业务逻辑处理,代码如下

package com.example.demo.config;import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;import javax.sql.DataSource;@Configuration
@EnableScheduling
public class QuartzConfiguration {/*** 继承org.springframework.scheduling.quartz.SpringBeanJobFactory* 实现任务实例化方式*/public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implementsApplicationContextAware {private transient AutowireCapableBeanFactory beanFactory;@Overridepublic void setApplicationContext(final ApplicationContext context) {beanFactory = context.getAutowireCapableBeanFactory();}/*** 将job实例交给spring ioc托管* 我们在job实例实现类内可以直接使用spring注入的调用被spring ioc管理的实例** @param bundle* @return* @throws Exception*/@Overrideprotected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {final Object job = super.createJobInstance(bundle);/*** 将job实例交付给spring ioc*/beanFactory.autowireBean(job);return job;}}/*** 配置任务工厂实例** @return*/@Beanpublic JobFactory jobFactory() {/*** 采用自定义任务工厂 整合spring实例来完成构建任务*/AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();return jobFactory;}/*** 配置任务调度器* 使用项目数据源作为quartz数据源** @param jobFactory 自定义配置任务工厂* @param dataSource 数据源实例* @return* @throws Exception*/@Bean(destroyMethod = "destroy", autowire = Autowire.NO)public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws Exception {SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();//将spring管理job自定义工厂交由调度器维护
        schedulerFactoryBean.setJobFactory(jobFactory);//设置覆盖已存在的任务schedulerFactoryBean.setOverwriteExistingJobs(true);//项目启动完成后,等待2秒后开始执行调度器初始化schedulerFactoryBean.setStartupDelay(2);//设置调度器自动运行schedulerFactoryBean.setAutoStartup(true);//设置数据源,使用与项目统一数据源
        schedulerFactoryBean.setDataSource(dataSource);//设置上下文spring bean nameschedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");//设置配置文件位置schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));return schedulerFactoryBean;}
}

  AutowiringSpringBeanJobFactory:可以看到上面配置类中,AutowiringSpringBeanJobFactory我们继承了SpringBeanJobFactory类,并且通过实现ApplicationContextAware接口获取ApplicationContext设置方法,通过外部实例化时设置ApplicationContext实例对象,在createJobInstance方法内,我们采用AutowireCapableBeanFactory来托管SpringBeanJobFactory类中createJobInstance方法返回的定时任务实例,这样我们就可以在定时任务类内使用Spring Ioc相关的注解进行注入业务逻辑实例了。

  JobFactory:自定义任务工厂

  SchedulerFactoryBean:使用项目内部数据源的方式来设置调度器的jobSotre,官方quartz有两种持久化的配置方案。

  第一种:采用quartz.properties配置文件配置独立的定时任务数据源,可以与使用项目的数据库完全独立。
  第二种:采用与创建项目统一个数据源,定时任务持久化相关的表与业务逻辑在同一个数据库内。

  可以根据实际的项目需求采取不同的方案,我采用了第二种方案,在上面配置类中可以看到方法schedulerFactoryBean内自动注入了JobFactory实例,也就是我们自定义的AutowiringSpringBeanJobFactory任务工厂实例,另外一个参数就是DataSource,在我们引入spring-boot-starter-jdbc依赖后会根据application.yml文件内的数据源相关配置自动实例化DataSource实例,这里直接注入是没有问题的。我们通过调用SchedulerFactoryBean对象的setConfigLocation方法来设置quartz定时任务框架的基本配置,配置文件所在位置:resources/quartz.properties => classpath:/quartz.properties下。

  quartz.properties内容如下:

org.quartz.scheduler.instanceName = schedulerFactoryBeanorg.quartz.scheduler.instanceId = AUTOorg.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.tablePrefix = QRTZ_org.quartz.jobStore.useProperties = falseorg.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 10org.quartz.threadPool.threadPriority = 5

  在上面配置中org.quartz.jobStore.classorg.quartz.jobStore.driverDelegateClass是定时任务持久化的关键配置,配置了数据库持久化定时任务以及采用MySQL数据库进行连接,当然你也可以连接别的数据库org.quartz.jobStore.tablePrefix属性配置了定时任务数据表的前缀,在quartz官方提供的创建表SQL脚本默认就是qrtz_,我们需要解压quartz2.3.0的jar,在quartz-2.2.3/docs/dbTables下找到tables_mysql_innodb.sql,然后在mysql客户端执行来创建相应的表。

  3、动态定时任务demo

  QuartzService.java

package com.example.demo.service;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import javax.annotation.PostConstruct;import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;@Service
public class QuartzService {@Autowiredprivate Scheduler scheduler;@PostConstructpublic void startScheduler() {try {scheduler.start();} catch (SchedulerException e) {e.printStackTrace();}}/*** 增加一个job* * @param jobClass*            任务实现类* @param jobName*            任务名称* @param jobGroupName*            任务组名* @param jobTime*            时间表达式 (这是每隔多少秒为一次任务)* @param jobTimes*            运行的次数 (<0:表示不限次数)*/public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,int jobTimes) {try {JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)// 任务名称和组构成任务key
                    .build();// 使用simpleTrigger规则Trigger trigger = null;if (jobTimes < 0) {trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime)).startNow().build();} else {trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes)).startNow().build();}scheduler.scheduleJob(jobDetail, trigger);} catch (SchedulerException e) {e.printStackTrace();}}/*** 增加一个job* * @param jobClass*            任务实现类* @param jobName*            任务名称* @param jobGroupName*            任务组名* @param jobTime*            时间表达式 (如:0/5 * * * * ? )*/public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime) {try {// 创建jobDetail实例,绑定Job实现类// 指明job的名称,所在组的名称,以及绑定job类JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)// 任务名称和组构成任务key
                    .build();// 定义调度触发规则// 使用cornTrigger规则Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)// 触发器key.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();// 把作业和触发器注册到任务调度中
            scheduler.scheduleJob(jobDetail, trigger);} catch (Exception e) {e.printStackTrace();}}/*** 修改 一个job的 时间表达式* * @param jobName* @param jobGroupName* @param jobTime*/public void updateJob(String jobName, String jobGroupName, String jobTime) {try {TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();// 重启触发器
            scheduler.rescheduleJob(triggerKey, trigger);} catch (SchedulerException e) {e.printStackTrace();}}/*** 删除任务一个job* * @param jobName*            任务名称* @param jobGroupName*            任务组名*/public void deleteJob(String jobName, String jobGroupName) {try {scheduler.deleteJob(new JobKey(jobName, jobGroupName));} catch (Exception e) {e.printStackTrace();}}/*** 暂停一个job* * @param jobName* @param jobGroupName*/public void pauseJob(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.pauseJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 恢复一个job* * @param jobName* @param jobGroupName*/public void resumeJob(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.resumeJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 立即执行一个job* * @param jobName* @param jobGroupName*/public void runAJobNow(String jobName, String jobGroupName) {try {JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);scheduler.triggerJob(jobKey);} catch (SchedulerException e) {e.printStackTrace();}}/*** 获取所有计划中的任务列表* * @return*/public List<Map<String, Object>> queryAllJob() {List<Map<String, Object>> jobList = null;try {GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);jobList = new ArrayList<Map<String, Object>>();for (JobKey jobKey : jobKeys) {List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);for (Trigger trigger : triggers) {Map<String, Object> map = new HashMap<>();map.put("jobName", jobKey.getName());map.put("jobGroupName", jobKey.getGroup());map.put("description", "触发器:" + trigger.getKey());Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());map.put("jobStatus", triggerState.name());if (trigger instanceof CronTrigger) {CronTrigger cronTrigger = (CronTrigger) trigger;String cronExpression = cronTrigger.getCronExpression();map.put("jobTime", cronExpression);}jobList.add(map);}}} catch (SchedulerException e) {e.printStackTrace();}return jobList;}/*** 获取所有正在运行的job* * @return*/public List<Map<String, Object>> queryRunJob() {List<Map<String, Object>> jobList = null;try {List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();jobList = new ArrayList<Map<String, Object>>(executingJobs.size());for (JobExecutionContext executingJob : executingJobs) {Map<String, Object> map = new HashMap<String, Object>();JobDetail jobDetail = executingJob.getJobDetail();JobKey jobKey = jobDetail.getKey();Trigger trigger = executingJob.getTrigger();map.put("jobName", jobKey.getName());map.put("jobGroupName", jobKey.getGroup());map.put("description", "触发器:" + trigger.getKey());Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());map.put("jobStatus", triggerState.name());if (trigger instanceof CronTrigger) {CronTrigger cronTrigger = (CronTrigger) trigger;String cronExpression = cronTrigger.getCronExpression();map.put("jobTime", cronExpression);}jobList.add(map);}} catch (SchedulerException e) {e.printStackTrace();}return jobList;}}

  UserService.java

package com.example.demo.service;import org.springframework.stereotype.Service;@Service
public class UserService {public void play() {System.out.println("user id play");}public void study() {System.out.println("user id study");}
}

  TestJob1.java

package com.example.demo.job;import java.util.Date;import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;public class TestJob1 extends QuartzJobBean {@Overrideprotected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {System.out.println(new Date() + "    job执行");}}

  TestJob2.java

package com.example.demo.job;import java.util.Date;import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;import com.example.demo.service.UserService;
@Component
public class TestJob2 extends QuartzJobBean {//注入业务service,完成定时任务逻辑
    @Autowiredprivate UserService service;@Overrideprotected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {System.out.println(new Date() + "    job2执行");service.play();}}

  TestController.java

package com.example.demo.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import com.example.demo.job.TestJob1;
import com.example.demo.job.TestJob2;
import com.example.demo.service.QuartzService;@RestController
public class TestController {@Autowiredprivate QuartzService quartzService;@RequestMapping("/addjob")public void startJob(String type) {if("TestJob1".equals(type)) {quartzService.addJob(TestJob1.class, "job1", "test", "0/5 * * * * ?");}else {quartzService.addJob(TestJob2.class, "job2", "test", "0/5 * * * * ?");}}@RequestMapping("/updatejob")public void updatejob() {quartzService.updateJob("job1", "test", "0/10 * * * * ?");}@RequestMapping("/deletejob")public void deletejob() {quartzService.deleteJob("job1", "test");}@RequestMapping("/pauseJob")public void pauseJob() {quartzService.pauseJob("job1", "test");}@RequestMapping("/resumeJob")public void resumeJob() {quartzService.resumeJob("job1", "test");}@RequestMapping("/queryAllJob")public Object queryAllJob() {return quartzService.queryAllJob();}@RequestMapping("/queryRunJob")public Object queryRunJob() {return quartzService.queryRunJob();}
}

  4、application.yml

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    username: rootpassword: rootjpa:hibernate:ddl-auto: update #ddl-auto:设为update表示每次都不会重新建表show-sql: trueapplication:name: quartz-cluster-node-first
server:port: 8081
# 打印日志
logging:level:root: INFOorg.hibernate: INFOorg.hibernate.type.descriptor.sql.BasicBinder: TRACEorg.hibernate.type.descriptor.sql.BasicExtractor: TRACEcom.springms: DEBUG

  至此,springboot整合quartz实现动态定时任务和任务持久化完毕,各功能我都测试过,符合预期,具体结果不再贴出,小伙伴们在使用时要注意springboot和quartz的版本问题,很多时候并不是代码有问题,而是jar不匹配。springboot2.0以后,直接有了spring-boot-starter-quartz包,我们只需要把原来的jar替换掉,无需任何配置就完成了整合。

 

转载于:https://www.cnblogs.com/hhhshct/p/9707710.html

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

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

相关文章

JAVA中protected的作用

类NewObject中有protected修饰的方法或者属性&#xff0c;则&#xff1a; 同一个包中&#xff1a; 可在同一个包里的子类中实例化NewObject类获得对象&#xff0c;然后可用该对象访问protected修饰的方法或者属性&#xff0c;即.操作访问。可在同一个包里的非子类中实例化NewOb…

wsimport 不是内部或外部命令,也不是可运行的程序或批处理文件

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 今天使用wsimport生成webservice client端代码&#xff0c;wsimport提示不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件…

静态变量的多线程同步问题

2019独角兽企业重金招聘Python工程师标准>>> 我们先来讨论一个问题&#xff0c;一个类的静态变量当类被多次实例化的时候&#xff0c;静态变量是否会受影响&#xff1f;首先我们应该清楚的是静态变量是在类被JVM classloader的时候分配内存&#xff0c;并且是分配在…

extends和implements区别

extends和implements区别 extends与implements的不同 1、在类的声明中&#xff0c;通过关键字extends来创建一个类的子类。 一个类通过关键字implements声明自己使用一个或者多个接口。 extends 是继承某个类, 继承之后可以使用父类的方法, 也可以重写父类的方法; imple…

评论:电商巨头们谁有勇气晒晒“价格战”账单?

摘要&#xff1a;国内电商接二连三上演的“价格战”&#xff0c;点燃了消费者的购买热情。在笔者看来&#xff0c;如果有哪个大型电商有勇气亮出价格战账单&#xff0c;那对竞争对手的刺激和打击效果将非同一般。晒出了账单后&#xff0c;消费者对购物场所的选择也将一目了然&a…

The xxx collides with a package/type

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 当类和包&#xff0c;重名时&#xff0c;包会报错误&#xff1a;The package aaa.a collides with a type&#xff1b;类也会报警告&…

Hive 行列转换

在京东众多业务中&#xff0c;促销业务充满了复杂性和挑战性&#xff0c;因为业务的灵活性&#xff0c;很多数据都存储成xml和json格式数据&#xff0c;这就要求下游数据分析师们需要对其做解析后方可使用 。 在众多操作中 &#xff0c;有一种是需要对数据做行列转换操作。 数据…

[译] 论 Rust 和 WebAssembly 对源码地址索引的极限优化

原文地址&#xff1a;Oxidizing Source Maps with Rust and WebAssembly原文作者&#xff1a;Nick Fitzgerald译文出自&#xff1a;掘金翻译计划本文永久链接&#xff1a;github.com/xitu/gold-m…译者&#xff1a;D-kylinTom Tromey 和我尝试使用 Rust 语言进行编码&#xff0…

Java WebService 简单实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 前言&#xff1a;朋友们开始以下教程前&#xff0c;请先看第五大点的注意事项&#xff0c;以避免不必要的重复操作。 一、准备工作&…

互联网侵入手机逐鹿背后:追求流量变现能力

摘要&#xff1a;小米联合创始人黎万强说&#xff0c;卖出10万台得免速死&#xff0c;卖出百万台算是得到了一张正式入行的门票。小米是一家新创公司&#xff0c;黎万强自己说&#xff0c;原本一无所有&#xff0c;作为原创品牌&#xff0c;它选择了口碑之路&#xff0c;则必须…

java api使用ElastichSearch指南

AggregationBuilders.terms:一段时间内&#xff0c;某个字段取值的数量排名前几的聚合 / ** param startTime 开始的时间* param endTime 结束的时间* param termAggName term过滤* param fieldName 要做count的字段* param top 返回的数量*/ RangeQueryBuilder actionPeriod …

关于JavaScript的数组随机排序

昨天了解了一下Fisher–Yates shuffle费雪耶兹随机置乱算法&#xff0c;现在再来看看下面这个曾经网上常见的一个写法&#xff1a; function shuffle(arr) { arr.sort(function () { return Math.random() - 0.5; }); } 或者使用更简洁的 ES6 的写法&#xff1a; function shu…

通用唯一识别码UUID

UUID是通用唯一识别码&#xff08;Universally Unique Identifier&#xff09;的缩写。UUID 的目的&#xff0c;是让分布式系统中的所有元素&#xff0c;都能有唯一的辨识资讯&#xff0c;而不需要透过中央控制端来做辨识资讯的指定。如此一来&#xff0c;每个人都可以建立不与…

java内省机制 + 内省是什么 + 内省实现方式 + 和反射的区别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、内省是什么、实现方式&#xff1a; 内省&#xff08;Introspector&#xff09;是Java语言对Bean类属性、事件的一种缺省处理方法。…

百度联合长虹发布第二款云手机 售价900元以下

摘要&#xff1a;【搜狐IT消息】5月15日消息&#xff0c;百度今天宣布联合长虹发布第二款智能手机&#xff0c;采用3.5英寸屏幕、300万像素摄像头&#xff0c;650MHz主频处理器&#xff0c;零售价格在700-899元之间&#xff0c;中国联通将为其提供话费补贴。 【搜狐IT消息】5月…

vmware workstation17环境安装centos7

打开控制面板&#xff0c;搜索“服务”&#xff0c;启动vmware authorize service -------解决无法开启虚拟机问题之无法连接MKS 2.虚拟机硬盘扩展为15G------解决安装centos7时出现的“检查存储配置出错”问题 3.硬盘分区----/boot 300mb&#xff08;不能小于200mb&#xff0…

博客园中的源代码格式显示

昨天写了一篇文章&#xff0c;但是在写的时候呢&#xff0c;没有注意&#xff0c;直接将代码复制上去了&#xff0c;今天正好有人提醒&#xff0c;看到了格式的混乱&#xff0c;借此记录整理一下&#xff0c;如何能直接粘贴代码&#xff0c;而且格式&#xff08;缩进&#xff0…

static的使用

类中的静态变量在程序运行期间&#xff0c;其内存空间对所有该类的对象实例而言是共享的&#xff0c;为了节省系统内存开销、共享资源&#xff0c;应该对一些适合使用static的变量声明为静态变量。 变量声明为static的使用场景&#xff1a; &#xff08;1&#xff09;变量所…

Linux内核的裁剪和移植

linux内核的裁剪和移植具体都在这个网址里面。https://blog.csdn.net/xie0812/article/details/10816059https://blog.csdn.net/xie0812/article/details/10821779转载于:https://blog.51cto.com/13401435/2145947

李开复唱衰互联网手机:大部分公司会失败

摘要&#xff1a;互联网企业和手机制造企业之间巨大的鸿沟也被李开复鲜明地指出来&#xff1a;“两个产业差别巨大&#xff0c;企业基因不同。”百度此前也坦诚表示&#xff0c;与长虹合作的千元机&#xff0c;主要是针对2000元以下的用户体验&#xff0c;不能与四五千元的苹果…