java quartz 数据库_SpringBoot+Quartz+数据库存储

Spring整合Quartz

a、quartz调度框架是有内置表的

进入quartz的官网http://www.quartz-scheduler.org/,点击Downloads,

下载后在目录\docs\dbTables下有常用数据库创建quartz表的脚本,例如:“tables_mysql.sql”

table_mysql.sql

table_mysql_innodb.sql

org.quartz-scheduler

quartz-jobs

2.2.1

org.springframework.boot

spring-boot-starter-quartz

com.mchange

c3p0

0.9.5.2

更换成Druid连接池

A、 引入依赖

com.alibaba

druid-spring-boot-starter

1.1.10

B、 导入DruidConnectionProvider.java

C、修改quartz.properties配置

#配置数据库源

org.quartz.dataSource.qzDS.connectionProvider.class:

com.lingerqi.项目名.util.DruidConnectionProvider

在项目中添加quartz.properties文件(这样就不会加载自带的properties文件)

此文件的内容主要分为:scheduler,ThreadPool,JobStore,plugin,Datasources等部分,

覆盖properties文件的目的是覆盖默认的数据源,更换为druid的数据配置

#

#============================================================================

# Configure Main Scheduler Properties 调度器属性

#============================================================================

org.quartz.scheduler.instanceName: DefaultQuartzScheduler

org.quartz.scheduler.instanceId = AUTO

org.quartz.scheduler.rmi.export: false

org.quartz.scheduler.rmi.proxy: false

org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool

org.quartz.threadPool.threadCount= 10

org.quartz.threadPool.threadPriority: 5

org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

#============================================================================

# Configure JobStore

#============================================================================

#存储方式使用JobStoreTX,也就是数据库

org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX

org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate

#使用自己的配置文件

org.quartz.jobStore.useProperties:true

#数据库中quartz表的表名前缀

org.quartz.jobStore.tablePrefix:qrtz_

org.quartz.jobStore.dataSource:qzDS

#是否使用集群(如果项目只部署到 一台服务器,就不用了)

org.quartz.jobStore.isClustered = true

#============================================================================

# Configure Datasources

#============================================================================

#配置数据库源(org.quartz.dataSource.qzDS.maxConnections: c3p0配置的是有s的,druid数据源没有s)

org.quartz.dataSource.qzDS.connectionProvider.class:com.lingerqi.quartz02.utils.DruidConnectionProvider

org.quartz.dataSource.qzDS.driver: com.mysql.jdbc.Driver

org.quartz.dataSource.qzDS.URL: jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8

org.quartz.dataSource.qzDS.user: root

org.quartz.dataSource.qzDS.password: 123

org.quartz.dataSource.qzDS.maxConnection: 10

要搞清楚一个问题:从数据库读取任务信息动态生成定时任务,和把quartz持久化到数据库是没有关系的。前者是我们自己定义的业务表,而后者是quartz使用自己的表来存储信息。持久化到数据库后,就算服务器重启或是多个quartz节点也没关系,因为他们共享数据库中的任务信息。

自定义的业务表:

-- 注意:job_name存放的任务类的全路径,在quartz中通过jobName和jobGroup来确定trigger的唯一性,所以这两列为联合唯一索引

create table t_schedule_trigger

(

id int primary key auto_increment, -- ID

cron varchar(200) not null, -- 时间表达式

status char(1) not null, -- 使用状态 0:禁用 1:启用

job_name varchar(200) not null, -- 任务名称

job_group varchar(200) not null, -- 任务分组

unique index(job_name,job_group)

);

-- 额外添加到任务中的参数

create table t_schedule_trigger_param

(

param_id int primary key auto_increment, -- ID

name varchar(200) not null, -- 参数名

value varchar(512), -- 参数值

schedule_trigger_id int not null, -- 外键:引用t_schedule_trigger(id)

foreign key(schedule_trigger_id) references t_schedule_trigger(id)

);

package com.lingerqi.quartz02.utils;

import com.alibaba.druid.pool.DruidDataSource;

import org.quartz.SchedulerException;

import org.quartz.utils.ConnectionProvider;

import java.sql.Connection;

import java.sql.SQLException;

/*

#============================================================================

# JDBC

#============================================================================

org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate

org.quartz.jobStore.useProperties:false

org.quartz.jobStore.dataSource:qzDS

#org.quartz.dataSource.qzDS.connectionProvider.class:org.quartz.utils.PoolingConnectionProvider

org.quartz.dataSource.qzDS.connectionProvider.class:com.zking.q03.quartz.DruidConnectionProvider

org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver

org.quartz.dataSource.qzDS.URL:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8

org.quartz.dataSource.qzDS.user:root

org.quartz.dataSource.qzDS.password:root

org.quartz.dataSource.qzDS.maxConnections:30

org.quartz.dataSource.qzDS.validationQuery: select 0

*/

/**

* [Druid连接池的Quartz扩展类]

*

* @ProjectName: []

* @Author: [xuguang]

* @CreateDate: [2015/11/10 17:58]

* @Update: [说明本次修改内容] BY[xuguang][2015/11/10]

* @Version: [v1.0]

*/

public class DruidConnectionProvider implements ConnectionProvider {

/*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*

* 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供set方法,Quartz框架自动注入值。

*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/

//JDBC驱动

public String driver;

//JDBC连接串

public String URL;

//数据库用户名

public String user;

//数据库用户密码

public String password;

//数据库最大连接数

public int maxConnection;

//数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。

public String validationQuery;

private boolean validateOnCheckout;

private int idleConnectionValidationSeconds;

public String maxCachedStatementsPerConnection;

private String discardIdleConnectionsSeconds;

public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;

public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;

//Druid连接池

private DruidDataSource datasource;

/*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*

* 接口实现

*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/

public Connection getConnection() throws SQLException {

return datasource.getConnection();

}

public void shutdown() throws SQLException {

datasource.close();

}

public void initialize() throws SQLException{

if (this.URL == null) {

throw new SQLException("DBPool could not be created: DB URL cannot be null");

}

if (this.driver == null) {

throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");

}

if (this.maxConnection < 0) {

throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");

}

datasource = new DruidDataSource();

try{

datasource.setDriverClassName(this.driver);

} catch (Exception e) {

try {

throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);

} catch (SchedulerException e1) {

}

}

datasource.setUrl(this.URL);

datasource.setUsername(this.user);

datasource.setPassword(this.password);

datasource.setMaxActive(this.maxConnection);

datasource.setMinIdle(1);

datasource.setMaxWait(0);

datasource.setMaxPoolPreparedStatementPerConnectionSize(this.DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION);

if (this.validationQuery != null) {

datasource.setValidationQuery(this.validationQuery);

if(!this.validateOnCheckout)

datasource.setTestOnReturn(true);

else

datasource.setTestOnBorrow(true);

datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);

}

}

/*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*

* 提供get set方法

*

* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/

public String getDriver() {

return driver;

}

public void setDriver(String driver) {

this.driver = driver;

}

public String getURL() {

return URL;

}

public void setURL(String URL) {

this.URL = URL;

}

public String getUser() {

return user;

}

public void setUser(String user) {

this.user = user;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public int getMaxConnection() {

return maxConnection;

}

public void setMaxConnection(int maxConnection) {

this.maxConnection = maxConnection;

}

public String getValidationQuery() {

return validationQuery;

}

public void setValidationQuery(String validationQuery) {

this.validationQuery = validationQuery;

}

public boolean isValidateOnCheckout() {

return validateOnCheckout;

}

public void setValidateOnCheckout(boolean validateOnCheckout) {

this.validateOnCheckout = validateOnCheckout;

}

public int getIdleConnectionValidationSeconds() {

return idleConnectionValidationSeconds;

}

public void setIdleConnectionValidationSeconds(int idleConnectionValidationSeconds) {

this.idleConnectionValidationSeconds = idleConnectionValidationSeconds;

}

public DruidDataSource getDatasource() {

return datasource;

}

public void setDatasource(DruidDataSource datasource) {

this.datasource = datasource;

}

}

QuartzConfiguration.java(quartz调度框架与spring框架整合的配置类,主要是要将org.quartz.Scheduler交给spring进行管理)

package com.lingerqi.quartz02.config;

import com.lingerqi.quartz02.utils.MyJobFactory;

import org.quartz.Scheduler;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.config.PropertiesFactoryBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.ClassPathResource;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;

import java.util.Properties;

@Configuration

public class QuartzConfiguration {

@Autowired

private MyJobFactory myJobFactory;

//创建调度器工厂

@Bean

public SchedulerFactoryBean schedulerFactoryBean(){

//1.创建SchedulerFactoryBean

//2.加载自定义的quartz.properties配置文件

//3.设置MyJobFactory

SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();

try {

factoryBean.setQuartzProperties(quartzProperties());

factoryBean.setJobFactory(myJobFactory);

return factoryBean;

} catch (IOException e) {

throw new RuntimeException(e);

}

}

@Bean

public Properties quartzProperties() throws IOException {

PropertiesFactoryBean propertiesFactoryBean=new PropertiesFactoryBean();

propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));

propertiesFactoryBean.afterPropertiesSet();

return propertiesFactoryBean.getObject();

}

@Bean(name="scheduler")

public Scheduler scheduler(){

return schedulerFactoryBean().getScheduler();

}

}

案例中需要观察表数据变化的表

-- 自定义的业务表

SELECT * FROM t_schedule_trigger;

SELECT * FROM t_schedule_trigger_param;

-- quartz调度框架自带的表

SELECT * FROM qrtz_scheduler_state;

SELECT * FROM qrtz_cron_triggers;

SELECT * FROM qrtz_simple_triggers

SELECT * FROM qrtz_triggers;

SELECT * FROM qrtz_job_details;

a19f934f851f0d63cb7f111422b4bdc8.png

9963e35320038a15aa4292179d08c086.png

创建springboot项目

568ed247e3e3085806c3968a1ca30c6a.png

pom依赖

org.quartz-scheduler

quartz-jobs

2.2.1

com.alibaba

druid-spring-boot-starter

1.1.10

src/main/java

**/*.xml

src/main/resources

*.properties

*.xml

*.yml

org.mybatis.generator

mybatis-generator-maven-plugin

1.3.2

mysql

mysql-connector-java

${mysql.version}

true

配置application.yml

server:

servlet:

context-path: /

port: 80

spring:

datasource:

#1.JDBC

type: com.alibaba.druid.pool.DruidDataSource

driver-class-name: com.mysql.jdbc.Driver

url: jdbc:mysql://localhost:3306/mybatis_ssm?useUnicode=true&characterEncoding=utf8

username: root

password: 123

druid:

#2.\u8FDE\u63A5\u6C60\u914D\u7F6E

#\u521D\u59CB\u5316\u8FDE\u63A5\u6C60\u7684\u8FDE\u63A5\u6570\u91CF \u5927\u5C0F\uFF0C\u6700\u5C0F\uFF0C\u6700\u5927

initial-size: 5

min-idle: 5

max-active: 20

#\u914D\u7F6E\u83B7\u53D6\u8FDE\u63A5\u7B49\u5F85\u8D85\u65F6\u7684\u65F6\u95F4

max-wait: 60000

#\u914D\u7F6E\u95F4\u9694\u591A\u4E45\u624D\u8FDB\u884C\u4E00\u6B21\u68C0\u6D4B\uFF0C\u68C0\u6D4B\u9700\u8981\u5173\u95ED\u7684\u7A7A\u95F2\u8FDE\u63A5\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2

time-between-eviction-runs-millis: 60000

# \u914D\u7F6E\u4E00\u4E2A\u8FDE\u63A5\u5728\u6C60\u4E2D\u6700\u5C0F\u751F\u5B58\u7684\u65F6\u95F4\uFF0C\u5355\u4F4D\u662F\u6BEB\u79D2

min-evictable-idle-time-millis: 30000

validation-query: SELECT 1 FROM DUAL

test-while-idle: true

test-on-borrow: true

test-on-return: false

# \u662F\u5426\u7F13\u5B58preparedStatement\uFF0C\u4E5F\u5C31\u662FPSCache \u5B98\u65B9\u5EFA\u8BAEMySQL\u4E0B\u5EFA\u8BAE\u5173\u95ED \u4E2A\u4EBA\u5EFA\u8BAE\u5982\u679C\u60F3\u7528SQL\u9632\u706B\u5899 \u5EFA\u8BAE\u6253\u5F00

pool-prepared-statements: true

max-pool-prepared-statement-per-connection-size: 20

# \u914D\u7F6E\u76D1\u63A7\u7EDF\u8BA1\u62E6\u622A\u7684filters\uFF0C\u53BB\u6389\u540E\u76D1\u63A7\u754C\u9762sql\u65E0\u6CD5\u7EDF\u8BA1\uFF0C'wall'\u7528\u4E8E\u9632\u706B\u5899

filter:

stat:

merge-sql: true

slow-sql-millis: 5000

#3.\u57FA\u7840\u76D1\u63A7\u914D\u7F6E

web-stat-filter:

enabled: true

url-pattern: /*

#\u8BBE\u7F6E\u4E0D\u7EDF\u8BA1\u54EA\u4E9BURL

exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"

session-stat-enable: true

session-stat-max-count: 100

stat-view-servlet:

enabled: true

url-pattern: /druid/*

reset-enable: true

#\u8BBE\u7F6E\u76D1\u63A7\u9875\u9762\u7684\u767B\u5F55\u540D\u548C\u5BC6\u7801

login-username: admin

login-password: admin

allow: 127.0.0.1

#deny: 192.168.1.100

#\u663E\u793A\u65E5\u5FD7

logging:

level:

com.lingerqi.quartz02.mapper: debug

Quartz02Application.java前面加上以下注解:

@MapperScan("com.lingerqi.quartz02.mapper")

@EnableTransactionManagement

@EnableScheduling

@SpringBootApplication

generatorConfig.xml

/p>

"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >

connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>

targetProject="src/main/java">

targetProject="src/main/java">

targetProject="src/main/java" type="XMLMAPPER">

enableCountByExample="false" enableDeleteByExample="false"

enableSelectByExample="false" enableUpdateByExample="false">

enableCountByExample="false" enableDeleteByExample="false"

enableSelectByExample="false" enableUpdateByExample="false">

ScheduleTriggerMapper.java

/**

* 查询触发器中包含的所有任务

* @return

*/

List queryScheduleTriggerLst();

ScheduleTriggerParamMapper.java

/**

* 查询出当前任务类对应所需的参数

* @param triggerId

* @return

*/

List queryScheduleParamLst(Integer triggerId);

spring自带定时任务作业类ScheduleTriggerServiceImpl.java

package com.lingerqi.quartz02.service.impl;

import com.lingerqi.quartz02.entity.ScheduleTrigger;

import com.lingerqi.quartz02.entity.ScheduleTriggerParam;

import com.lingerqi.quartz02.mapper.ScheduleTriggerMapper;

import com.lingerqi.quartz02.mapper.ScheduleTriggerParamMapper;

import org.quartz.*;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Service;

import java.util.List;

@Service

public class ScheduleTriggerServiceImpl {

@Autowired

private ScheduleTriggerMapper scheduleTriggerMapper;

@Autowired

private ScheduleTriggerParamMapper scheduleTriggerParamMapper;

@Autowired

private Scheduler scheduler;

@Scheduled(cron = "0/10 * * * * ?")

public void refreshScheduler(){

try {

List scheduleTriggers =

scheduleTriggerMapper.queryScheduleTriggerLst();

if(null!=scheduleTriggers){

for (ScheduleTrigger scheduleTrigger : scheduleTriggers) {

String cron = scheduleTrigger.getCron(); //表达式

String jobName = scheduleTrigger.getJob_name(); //任务名称

String jobGroup = scheduleTrigger.getJob_group(); //任务分组

String status = scheduleTrigger.getStatus(); //任务状态

//JobName+JobGroup=Primary Key

//根据jobName和jobGroup生成TriggerKey

TriggerKey triggerKey =

TriggerKey.triggerKey(jobName, jobGroup);

//根据TriggerKey到Scheduler调度器中获取触发器

CronTrigger cronTrigger = (CronTrigger)

scheduler.getTrigger(triggerKey);

if(null==cronTrigger){

if(status.equals("0"))

continue;

System.out.println("创建调度器");

//创建任务详情

JobDetail jobDetail=

JobBuilder.newJob((Class extends Job>) Class.forName(jobName))

.withIdentity(jobName,jobGroup)

.build();

//往Job任务中传递参数

JobDataMap jobDataMap = jobDetail.getJobDataMap();

List params =

scheduleTriggerParamMapper.queryScheduleParamLst(scheduleTrigger.getId());

for (ScheduleTriggerParam param : params) {

jobDataMap.put(param.getName(),param.getValue());

}

//创建表达式调度器

CronScheduleBuilder cronSchedule =

CronScheduleBuilder.cronSchedule(cron);

//创建Trigger

cronTrigger=TriggerBuilder.newTrigger()

.withIdentity(jobName,jobGroup)

.withSchedule(cronSchedule)

.build();

//将jobDetail和Trigger注入到scheduler调度器中

scheduler.scheduleJob(jobDetail,cronTrigger);

}else{

//System.out.println("Quartz 调度任务中已存在该任务");

if(status.equals("0")){

JobKey jobKey = JobKey.jobKey(jobName, jobGroup);

scheduler.deleteJob(jobKey);

continue;

}

//调度器中的表达式

String cronExpression =

cronTrigger.getCronExpression();

if(!cron.equals(cronExpression)){

//创建表达式调度器

CronScheduleBuilder cronSchedule =

CronScheduleBuilder.cronSchedule(cron);

//重构

cronTrigger=cronTrigger.getTriggerBuilder()

.withIdentity(triggerKey)

.withSchedule(cronSchedule)

.build();

//刷新调度器

scheduler.rescheduleJob(triggerKey,cronTrigger);

}

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

读取数据库中表达式启动定时任务

数据库表t_schedule_trigger配置

440538543440131755e9eaff6834597b.png

MyJob.java

package com.lingerqi.quartz02.quartz;

import lombok.extern.slf4j.Slf4j;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.stereotype.Component;

import java.util.Date;

@Component

@Slf4j

public class MyJob implements Job {

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

System.out.println("MyJob是一个空的任务计划,时间:"+new Date().toLocaleString());

}

}

c2af16995d0d7f73b1b1c0b8eca0e48d.png

Spring自带定时任务每10s执行一次,查询自定义触发器表,获取到具体的作业类及任务表达式,quartz的任务为每5s执行一次,所以打印如上

更改定时任务状态

更改数据库调度器表t_schedule_trigger的state状态

当禁用该触发器时,那么程序只会执行spring自带的定时任务,每10s执行一次查询

定时任务中携带参数

39d9a061b185dfc29cbc8ed495ed1fd5.png

MyJob1

@Component

@Slf4j

public class MyJob1 implements Job {

@Autowired

private ScheduleTriggerParamService scheduleTriggerParamService;

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

JobDetail jobDetail =

jobExecutionContext.getJobDetail();

JobDataMap jobDataMap = jobDetail.getJobDataMap();

System.out.println(new Date().toLocaleString()+"-->携带参数个数:"+jobDataMap.size());

}

}

15e621ea95921776ba94919b1971f6a9.png

程序执行spring自带的定时任务,每10s执行一次查询,查询t_schedule_trigger表,调度器表中有两个调度器,都是每5s执行一次,其中一个调度器是需要携带参数的,携带的参数在t_schedule_trigger_param表中,所以一开始调度器启动的时候需要查询t_schedule_trigger_param表数据,最终打印语句如上。

更改定时任务规则

MyJob2.java

@Component

@Slf4j

public class MyJob2 implements Job{

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

JobDetail jobDetail =

jobExecutionContext.getJobDetail();

JobDataMap jobDataMap = jobDetail.getJobDataMap();

System.out.println(new Date().toLocaleString()+"-->MyJob2参数传递name="+jobDataMap.get("name")+",score="+

jobDataMap.get("score"));

}

}

0aa78e9157174a578964af7b44e1cc68.png

程序执行spring自带的定时任务,每10s执行一次查询,查询t_schedule_trigger表,将任务3的表达式由0/3 * * * * ?改成0/20 * * * * ?,最终结果如上

@Component

@Slf4j

public class MyJob2 implements Job{

@Override

public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

JobDetail jobDetail =

jobExecutionContext.getJobDetail();

JobDataMap jobDataMap = jobDetail.getJobDataMap();

System.out.println(new Date().toLocaleString()+"-->MyJob2参数传递name="+jobDataMap.get("name")+",score="+

jobDataMap.get("score"));

}

}

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

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

相关文章

【CodeForces - 1062C】Banh-mi (贪心,数学,找规律,快速幂)

题干&#xff1a; JATC loves Banh-mi (a Vietnamese food). His affection for Banh-mi is so much that he always has it for breakfast. This morning, as usual, he buys a Banh-mi and decides to enjoy it in a special way. First, he splits the Banh-mi into nn pa…

【牛客 - 练习】约数个数的和(数论,数学)

题干&#xff1a; 给个n&#xff0c;求1到n的所有数的约数个数的和~ 输入描述: 第一行一个正整数n 输出描述: 输出一个整数&#xff0c;表示答案 示例1 输入 复制 3 输出 复制 5 说明 样例解释&#xff1a; 1有1个约数1 2有2个约数1,2 3有2个约数1,3 备注: n…

mysql json 创建索引_MySQL · 最佳实践 · 如何索引JSON字段

概述MySQL从5.7.8起开始支持JSON字段&#xff0c;这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能&#xff0c;至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能来对JSON对象中的字段…

mysql链路跟踪工具_EasySwoole利用链路追踪组件制作甩锅工具

前言最近前端老是反馈API调用异常&#xff0c;说请求成功但是没有数据返回&#xff01;我写的代码怎么可能有bug&#xff0c;肯定是前端调用的方式不对&#xff01;经过一番套鼓&#xff0c;直接把请求参数和响应内容打印到控制台&#xff0c;果然不出我所料&#xff0c;请求缺…

java selector 源码_Java NIO核心组件-Selector和Channel

昨天我们介绍了一下SelectorProvider和IO multiplexing.特别是IO multiplexing中的epoll系统调用,是Linux版本的Java的NIO的核心实现.那今天我们就来介绍一下, Java NIO中的核心组件, Selector和Channel.这两个组件,对于熟悉Java OIO,而不熟悉Java NIO的朋友来说,理解其作用是极…

python 爬虫 博客园_Python爬虫爬取博客园作业

分析一下他们的代码&#xff0c;我在浏览器中对应位置右键&#xff0c;然后点击检查元素&#xff0c;可以找到对应部分的代码。但是&#xff0c;直接查看当前网页的源码发现&#xff0c;里面并没有对应的代码。我猜测这里是根据服务器上的数据动态生成的这部分代码&#xff0c;…

java 与 xml_xml与java对象转换

public static void main(String[] args) {//java bean 转 xmlDept d new Dept();List staffs new ArrayList<>();Staff s1 new Staff("wuyun", 20);Staff s2 new Staff("lilei", 22);staffs.add(s1);staffs.add(s2);d.setDeptName("开放平…

【牛客 - 370H】Rinne Loves Dynamic Graph(分层图最短路)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/370/H 来源&#xff1a;牛客网 Rinne 学到了一个新的奇妙的东西叫做动态图&#xff0c;这里的动态图的定义是边权可以随着操作而变动的图。 当我们在这个图上经过一条边的时候&#xff0c;这个图上所…

中位数及带权中位数问题(转)

先从一到简单的题看起&#xff1a; 士兵站队问题 在一个划分成网格的操场上&#xff0c;n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、下、左、右移动一步&#xff0c;但在同一时刻任一网格点上只能有一名士兵。按照军官的命令&#xff0c;…

*【HDU - 4272 】LianLianKan (dfs 或 状压dp,贪心不行)

题干&#xff1a; I like playing game with my friend, although sometimes looks pretty naive. Today I invent a new game called LianLianKan. The game is about playing on a number stack. Now we have a number stack, and we should link and pop the same element…

java中的values函数_巧用valueat函数(快逸免费版)

在制作报表时&#xff0c;经常会遇到将数据库里一列数据按照条件取值后&#xff0c;分为多列显示的需求&#xff0c;例如&#xff1a;数据库中有一列名为type的数据&#xff0c;在报表中&#xff0c;第一列选择type为1的数据&#xff0c;第二列选择type为2的数据。由于受到扩展…

Java设计流程执行器_Java进阶面试精选系列:SpringMVC+SpringBoot+Hibernate+Mybatis+设计模式...

小编精心收集&#xff1a;为金三银四准备&#xff0c;以下面试题先过一遍&#xff0c;为即将到了的面试做好准备&#xff0c;也过一遍基础知识点。一、Spring/Spring MVC1.为什么要使用 spring&#xff1f;2.解释一下什么是 aop&#xff1f;3.解释一下什么是 ioc&#xff1f;3.…

【牛客 - 370E】Rinne Loves Gift(Bellman_Ford判负环,二分,分数规划)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/370/E 来源&#xff1a;牛客网 Rinne 喜欢礼物&#xff0c;也喜欢送礼物 圣诞节快到了&#xff0c;Rinne 要去给给住在城市里的人送礼物 城市的交通可以抽象成一个 n 个点 m 条边的有向图 每条边上有…

【POJ - 2976】【ZOJ - 3068】【SCU - 2992】Dropping tests (01分数规划)

题干&#xff1a; In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be . Given your test scores and a positive integer k, determine how high you can make your cumulative aver…

重写过的url 怎么获取当前页面url java_网站URL重写(Java UrlRewrite 的使用)

现在大部分的网站和商城都会使用到URL重写&#xff0c;接触到这个&#xff0c;也是因为正在做的电子商务商城。URL重写&#xff0c;是将原有的URL采用另一种规则来显示&#xff0c;使得用户方便访问同时也屏蔽一些信息。在此说下它的好处&#xff0c;在开发过程中&#xff0c;经…

Java行业情景分析_Java 设计模式情景分析——单例模式

单例模式可以说是应用最广的模式之一&#xff0c;在应用单例模式时&#xff0c;单例对象的类必须保证只有一个实例存在&#xff0c;而且可以自行实例化并向整个系统提供这个实例。一般在不能自由构造对象的情况下&#xff0c;就会使用单例设计模式&#xff0c;例如创建一个对象…

php实现播放直播_PHP直播技术分享(一:实现直播)

推流服务器采用的是自搭的推流服务器 , 自己玩玩 做外包项目还是去搞七牛云/阿里这样的服务器吧,开始bb-----1:技术栈image.jpeg2:开发中业务(1)主播申请时创建个秘钥 , 这个秘钥随时字符串即可到时候根据字符串找到拉流的直播位置存数据库包括推流地址image.png3:配置nginx-rt…

php获取location,php获取header[‘location’]信息常见问题

15/01/31本文关键字: 302, header, location//初始化url信息$host “#8221;;$url$host.”l/rzTf7ap2viw/&iid222004556&resourceId0_04_05_99/v.swf”;//按照字段获取header响应信息$headers get_headers($url, TRUE);//获取这个土豆的302跳转地址$u302 $headers[“Lo…

php对联广告,html左右对联代码 cms网站对联广告html代码

实现网页左右两侧居中的对联广告代码你只记得自己有好多朋友却从没想过小编只有你一人。无标题文档 #left{ width:200px;height:450px; position:absolute; left:0px; background:red; border:1px #000 solid} #right{width:200px;height:450px; position:absolute; right:0px;…

php 分页 url重写 分页问题,解决千古难题,wordpress分页URL问题,wordpress给分页加链接...

原本的wordpress文章如果分页会成如下的结构&#xff1a;http://www.xyqzmt.cn/1.html/2通常固定链接都是这样的结构&#xff0c;设为/%postname%.html或者/%post_id%.html 以前我一直无法解决如上的问题&#xff0c;最后放弃挣扎&#xff0c;如果遇到很长的文章全都放在一个页…