首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,649 阅读
2
Mac打印机设置黑白打印
5,043 阅读
3
修改elementUI中el-table树形结构图标
4,946 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,705 阅读
5
intelliJ Idea 2022.2.X破解
4,458 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Mac
Spring Cloud
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
MySQL
.Net
Spring Cloud Alibaba
Mybatis-Plus
Typecho
jQuery
Java Script
IntelliJ IDEA
微信小程序
Laughing
累计撰写
629
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
629
篇与
的结果
2020-10-02
Spring Boot使用Redis
什么是RedisRedis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。Redis官网:https://redis.io/spring boot 使用Redis添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>修改application.yaml在配置文件中,增加redis配置信息增加Redis配置类/** * Redis配置 * @author laughing * @date 2020/10/2 * @site https://lisen.cc */ @Configuration public class RedisConfig { /** * RedisTemplate配置,放置存储数据乱码 * @param redisConnectionFactory * @return */ @Bean public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // key采用String的序列化方式 redisTemplate.setKeySerializer(new StringRedisSerializer()); // hash的key也采用String的序列化方式 redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // value序列化方式采用fastjson redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // hash的value序列化方式采用jackson redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } }编写Redis工具类/** * Redis工具类 * @author laughing * @date 2020/10/2 * @site https://lisen.cc */ @Component public class RedisUtils { @Resource RedisTemplate<String, Object> redisTemplate; /** * 判断是否存在 * * @return */ public boolean hasKey(String key) { return redisTemplate.hasKey(key); } /** * 获取值 * @param key * @return */ public Object getValue(String key){ return redisTemplate.opsForValue().get(key); } /** * 设置值 * * @param key * @param value */ public void setValue(String key, Object value) { redisTemplate.opsForValue().set(key, value); } /** * 获取过期时间 * * @param key * @return */ public Long getExpire(String key) { return redisTemplate.getExpire(key); } /** * 获取过期时间 * * @param key * @param timeUnit * @return */ public Long getExpire(String key, TimeUnit timeUnit) { return redisTemplate.getExpire(key, timeUnit); } /** * 设置过期时间 * * @param key * @param timeOut * @return */ public Boolean setExpire(String key, Duration timeOut) { return redisTemplate.expire(key, timeOut); } /** * 删除 * * @param key * @return */ public Boolean delete(String key) { return redisTemplate.delete(key); } /** * 删除 * @param keys * @return */ public Long deleteAll(List<String> keys){ return redisTemplate.delete(keys); } }使用这里进行简单的测试。@SpringBootTest class RedisApplicationTests { @Resource RedisUtils redisUtils; @Test void contextLoads() { } @Test void setValue(){ String key = "name"; String value = "李森的博客"; redisUtils.setValue(key,value); } }这里只演示一个设置值,通过Another Redis Desktop查看数据库
2020年10月02日
1,604 阅读
0 评论
0 点赞
2020-10-01
在windows上安装Redis
前言Redis官方不建议在windows下使用Redis,所以官网没有windows版本可以下载。还好微软团队维护了开源的window版本,虽然只有3.2版本,对于普通测试使用足够了。Windows Redis下载地址https://github.com/MicrosoftArchive/redis/releases注意点击Asset,展开就能看到对应的安装包。Windows Redis使用我相信没有任何人在实际项目中,会在Win下使用Redis。(如果有,就当我这句话没说)如上所述,所以我不讲解如果通过.msi的方式进行安装。(尽管都是一样的),我们这里介绍.zip的方式进行安装(使用)。解压下载的.zip文件将redis路径添加到环境变量cmd启动redis如果已经将redis路径添加到path,执行redis-server.exeredis会自动加载redis目录下的redis.windows.conf配置文件,当然,你也可以执行配置文件位置,就像下面这样redis-server.exe C:\Users\laughing\Documents\Redis-x64-3.2.100\redis.windows.conf如果很不幸,你没有将redis添加到path,那么你必须先cd到redis目录下,然后执行上面的命令。redis启动成功后,界面如下使用命令行启动Redis服务进入redis目录,执行以下命令:redis-server --service-install redis.windows.conf执行完成后,打开windows 服务,如果看到Redis,则代表安装成功。服务的方式运行,不需要我们每次都通过cmd打开窗口,并可以配置redis开机启动。redis服务启动执行以下命令启动redis:redis-server --service-start当然,你也可以在windows服务界面,通过图形化的方式启动。停止redis服务redis-server --service-stop当然,你也可以在windows服务界面,通过图形化的方式启动。测试redis能够连接首先执行redis-cli打开客户端界面,输入ping,如果提示'PONG',则代表打开成功。
2020年10月01日
1,448 阅读
0 评论
1 点赞
2020-10-01
另一个 Redis 桌面管理工具- Another-Redis-Desktop-Manager
AnotherRedisDesktopManager是国人开源的一个Redis客户端。它是一款更快、更好、更稳定的 Redis 桌面管理工具,兼容 Linux, windows, mac。更重要的是,在加载大量的键时它不会崩溃!AnotherRedisDesktopManager也是我最近一直使用的redis客户端。项目地址:https://github.com/qishibo/AnotherRedisDesktopManager
2020年10月01日
2,176 阅读
0 评论
1 点赞
2020-10-01
最新idea2020.02激活教程有效期到2089
本教程以失效,请参考最新文章 2020.2 IntelliJ IDEA激活-已解决27号过期问题idea 2020.2是由捷克IntelliJ公司而打造的一款Java集成开发环境,常常会被java工程师用于javabweb、大数据等场景的开发,是众多工程师们优先选择使用的开发工具。该软件界面美观,操作方便,拥有丰富的导航查看模式,用户通过快捷键即可显示最近打开过的文件和类名查找框,拥有强大的编码辅助功能,用户无需任何输入就可以实现代码的自动生成,还支持XML、JSP、EJB、EJB、JavaDoc预览、程序员意图等等,让你编码得心应手,加快敲代码的效率。虽然该软件现已全新发售,但是对于很多初学的学生党来说支付不起,所以小编带来了idea 2020.1破解版,成功安装完软件之后,使用附带的破解补丁可以完美激活,详细的使用教程请看下方,小编亲测有效,有需要的朋友快来下载吧。获取破解文件https://pan.baidu.com/s/15atsWT73TEMdPmMI565I-A 提取码: 2v42使用方法先下载压缩包解压后得到jetbrains-agent-latest.zip,把它放到你认为合适的文件夹内。启动你的IDE,如果上来就需要注册,选择:试用(Evaluate for free)进入IDE拖动jetbrains-agent-latest.zip到编辑器里面选择resart输入安装参数激活成功安装参数LFq51qqupnaiTNn39w6zATiOTxZI2JYuRJEBlzmUDv4zeeNlXhMgJZVb0q5QkLr+CIUrSuNB7ucifrGXawLB4qswPOXYG7+ItDNUR/9UkLTUWlnHLX07hnR1USOrWIjTmbytcIKEdaI6x0RskyotuItj84xxoSBP/iRBW2EHpOc
2020年10月01日
1,781 阅读
0 评论
1 点赞
2020-09-30
Spring boot整合mybatis多数据源简单使用
日常开发中,我们很少会在一个应用程序中同时使用多个数据源。但是,如果涉及一些数据迁移等应用,可能会涉及将数据从一个库迁移到另外一个库,甚至是不同类型的数据库,比如MySQL到Oracle。这篇博文,我们不介绍mybatis的基本使用,只介绍基于mybatis配置多数据源的方法。数据源准备我这里用了本地MySQL两个库,分别是mybatisone和mybatistwo,mybatisone库中有一张userone表,mybatistwo库中有一张usertwo表,建表sql如下:userone/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80021 Source Host : localhost:3306 Source Schema : mybatisone Target Server Type : MySQL Target Server Version : 80021 File Encoding : 65001 Date: 01/10/2020 00:34:29 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for userone -- ---------------------------- DROP TABLE IF EXISTS `userone`; CREATE TABLE `userone` ( `id` bigint(0) NOT NULL, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of userone -- ---------------------------- INSERT INTO `userone` VALUES (1, '姓名1'); SET FOREIGN_KEY_CHECKS = 1; usertwo/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80021 Source Host : localhost:3306 Source Schema : mybatistwo Target Server Type : MySQL Target Server Version : 80021 File Encoding : 65001 Date: 01/10/2020 00:34:35 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for usertwo -- ---------------------------- DROP TABLE IF EXISTS `usertwo`; CREATE TABLE `usertwo` ( `id` bigint(0) NOT NULL, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of usertwo -- ---------------------------- INSERT INTO `usertwo` VALUES (1, '姓名2'); SET FOREIGN_KEY_CHECKS = 1; 添加依赖主要依赖如下 <!--mybatis依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--MySQL驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.14</version> </dependency>application.yaml配置文件yaml文件配置数据源信息以及mybatis的配置信息spring: datasource: mybatisone: url: jdbc:mysql://localhost:3306/mybatisone?chartset=utf8mb4&serverTimezone=UTC&usessl=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource mybatistwo: url: jdbc:mysql://localhost:3306/mybatistwo?chartset=utf8mb4&serverTimezone=UTC&usessl=false username: root password: root type: com.alibaba.druid.pool.DruidDataSource mybatis: mapper-locations: classpath*:mapper/*.xml type-aliases-package: cc.lisen.simplemybatis.entity配置druid根据yaml文件提供的DataSource,分别配置对应的两个数据源。DataSourceConfig.java/** * datasource配置文件 * @author laughing * @date 2020/9/30 * @site https://lisen.cc */ @Configuration public class DataSourceConfig { /** * * @return 第一个数据源 */ @Bean @ConfigurationProperties(prefix = "spring.datasource.mybatisone") DataSource dataSourceOne(){ return DruidDataSourceBuilder.create().build(); } /** * * @return 第二个数据源 */ @Bean @ConfigurationProperties(prefix = "spring.datasource.mybatistwo") DataSource dataSourceTwo(){ return DruidDataSourceBuilder.create().build(); } }配置mybatis数据源MyBatisConfigOne.java/** * mybatis第一个配置文件 * @author laughing * @date 2020/9/30 * @site https://lisen.cc */ @Configuration @MapperScan(basePackages = {"cc.lisen.simplemybatis.mapper.one"},sqlSessionFactoryRef = "sqlSessionFactoryOne",sqlSessionTemplateRef = "sqlSessionTemplateOne") public class MyBatisConfigOne { private final Logger logger = LoggerFactory.getLogger(MyBatisConfigOne.class); @Resource(name = "dataSourceOne") DataSource dataSourceOne; @Bean SqlSessionFactory sqlSessionFactoryOne() { SqlSessionFactory sqlSessionFactory = null; try { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml")); sqlSessionFactoryBean.setDataSource(dataSourceOne); sqlSessionFactory = sqlSessionFactoryBean.getObject(); }catch (Exception ex){ logger.error(ex.getMessage()); } return sqlSessionFactory; } @Bean SqlSessionTemplate sqlSessionTemplateOne(){ return new SqlSessionTemplate(sqlSessionFactoryOne()); } }MyBatisConfigTwo.java/** * mybatis第二个配置文件 * @author laughing * @date 2020/9/30 * @site https://lisen.cc */ @Configuration @MapperScan(basePackages = {"cc.lisen.simplemybatis.mapper.two"},sqlSessionFactoryRef = "sqlSessionFactoryTwo",sqlSessionTemplateRef = "sqlSessionTemplateTwo") public class MyBatisConfigTwo { private final Logger logger = LoggerFactory.getLogger(MyBatisConfigTwo.class); @Resource(name = "dataSourceTwo") DataSource dataSourceTwo; @Bean SqlSessionFactory sqlSessionFactoryTwo() { SqlSessionFactory sqlSessionFactory = null; try { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/two/*.xml")); sqlSessionFactoryBean.setDataSource(dataSourceTwo); sqlSessionFactory = sqlSessionFactoryBean.getObject(); }catch (Exception ex){ logger.error(ex.getMessage()); } return sqlSessionFactory; } @Bean SqlSessionTemplate sqlSessionTemplateTwo(){ return new SqlSessionTemplate(sqlSessionFactoryTwo()); } }生成mybatis信息mybatis不是我们要讲解的重点,我这里的信息都是通过Free MyBatis插件自动生成的。不做过多介绍。增加实体Userone.java/** * userone * @author */ @Data public class Userone implements Serializable { private Long id; private String name; private static final long serialVersionUID = 1L; }Usertwo.java/** * usertwo * @author */ @Data public class Usertwo implements Serializable { private Long id; private String name; private static final long serialVersionUID = 1L; }增加mapperUseroneMapper.java@Mapper public interface UseroneMapper { int deleteByPrimaryKey(Long id); int insert(Userone record); int insertSelective(Userone record); Userone selectByPrimaryKey(Long id); int updateByPrimaryKeySelective(Userone record); int updateByPrimaryKey(Userone record); }Usertwo.java/** * usertwo * @author */ @Data public class Usertwo implements Serializable { private Long id; private String name; private static final long serialVersionUID = 1L; }增加xmlUseroneMapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.lisen.simplemybatis.mapper.one.UseroneMapper"> <resultMap id="BaseResultMap" type="cc.lisen.simplemybatis.entity.Userone"> <id column="id" jdbcType="BIGINT" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> </resultMap> <sql id="Base_Column_List"> id, `name` </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from userone where id = #{id,jdbcType=BIGINT} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> delete from userone where id = #{id,jdbcType=BIGINT} </delete> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="cc.lisen.simplemybatis.entity.Userone" useGeneratedKeys="true"> insert into userone (`name`) values (#{name,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="cc.lisen.simplemybatis.entity.Userone" useGeneratedKeys="true"> insert into userone <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null"> `name`, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null"> #{name,jdbcType=VARCHAR}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="cc.lisen.simplemybatis.entity.Userone"> update userone <set> <if test="name != null"> `name` = #{name,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <update id="updateByPrimaryKey" parameterType="cc.lisen.simplemybatis.entity.Userone"> update userone set `name` = #{name,jdbcType=VARCHAR} where id = #{id,jdbcType=BIGINT} </update> </mapper>UsertwoMapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.lisen.simplemybatis.mapper.two.UsertwoMapper"> <resultMap id="BaseResultMap" type="cc.lisen.simplemybatis.entity.Usertwo"> <id column="id" jdbcType="BIGINT" property="id" /> <result column="name" jdbcType="VARCHAR" property="name" /> </resultMap> <sql id="Base_Column_List"> id, `name` </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from usertwo where id = #{id,jdbcType=BIGINT} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> delete from usertwo where id = #{id,jdbcType=BIGINT} </delete> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="cc.lisen.simplemybatis.entity.Usertwo" useGeneratedKeys="true"> insert into usertwo (`name`) values (#{name,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="cc.lisen.simplemybatis.entity.Usertwo" useGeneratedKeys="true"> insert into usertwo <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null"> `name`, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null"> #{name,jdbcType=VARCHAR}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="cc.lisen.simplemybatis.entity.Usertwo"> update usertwo <set> <if test="name != null"> `name` = #{name,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <update id="updateByPrimaryKey" parameterType="cc.lisen.simplemybatis.entity.Usertwo"> update usertwo set `name` = #{name,jdbcType=VARCHAR} where id = #{id,jdbcType=BIGINT} </update> </mapper>配置测试Api/** * @author laughing * @date 2020/9/30 * @site https://lisen.cc */ @RestController public class MyBatisController { @Resource UseroneMapper useroneMapper; @Resource UsertwoMapper usertwoMapper; @RequestMapping("/one") public Userone userone(){ return useroneMapper.selectByPrimaryKey(1L); } @RequestMapping("/two") public Usertwo usertwo(){ return usertwoMapper.selectByPrimaryKey(1L); } }增加两个Api,分别用于获取数据源1和数据源2的数据。整体代码结构里面封装了全局异常,如果不了解的,可以参考 SpringBoot 之 @ControllerAdvice使用场景代码测试我们在分别打开两个请求,查看获取的数据注意事项在配置数据源时,注意设置mapper的位置,即如下代码:sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml"));如果没有设置,可能会提示Invalid bound statement (not found)
2020年09月30日
1,241 阅读
0 评论
0 点赞
2020-09-30
Spring Boot Quartz基于持久化存储的动态管理
精彩回顾我们在spring boot quartz定时任务基本使用及介绍和spring boot quartz持久化存储分别对quartz基本信息及持久化存储进行了介绍。这篇文章我们继续介绍给予持久化存储实现任务的动态管理。创建表结构为了存储我们自己动态创建的任务,除了spring boot quartz持久化存储介绍的添加quartz表结构之外,我们还需要添加一个自己的表。以下是MySQL的表结构,其他类型的数据库请按需修改。/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80021 Source Host : localhost:3306 Source Schema : quartz Target Server Type : MySQL Target Server Version : 80021 File Encoding : 65001 Date: 30/09/2020 13:34:24 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for task_quartz -- ---------------------------- DROP TABLE IF EXISTS `task_quartz`; CREATE TABLE `task_quartz` ( `id` bigint(0) NOT NULL AUTO_INCREMENT, `job_group` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务分组', `job_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务名', `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务描述', `cron_expression` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'cron表达式', `job_class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名', `job_status` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '任务状态', `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '创建者', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `modify_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '更新者', `modify_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `NameWithGroup`(`job_group`, `job_name`) USING BTREE COMMENT '任务及分组唯一' ) ENGINE = MyISAM AUTO_INCREMENT = 68 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1; 创建工程,添加依赖如果要实现任务的动态管理,这里单独借助一张表,存储任务的信息。先介绍一个依赖的情况:MySQL数据库mybatis执行sqlquartz依赖lombok具体项目依赖如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>修改配置文件application.yamlserver: port: 8080 spring: profiles: active: devapplication-dev.yamlspring: datasource: url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true&&serverTimezone=UTC username: root password: root type: com.zaxxer.hikari.HikariDataSource quartz: job-store-type: jdbc mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: cc.lisen.quartztask.entity configuration: map-underscore-to-camel-case: true 主要配置信息:MySQL数据库连接mybatis配置job-store-type存储到数据库增加mybatis相关操作TaskQuartzMapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.lisen.quartztask.mapper.TaskQuartzMapper"> <resultMap id="BaseResultMap" type="cc.lisen.quartztask.entity.TaskQuartz"> <id column="id" jdbcType="BIGINT" property="id"/> <result column="job_group" jdbcType="VARCHAR" property="jobGroup"/> <result column="job_name" jdbcType="VARCHAR" property="jobName"/> <result column="description" jdbcType="VARCHAR" property="description"/> <result column="cron_expression" jdbcType="VARCHAR" property="cronExpression"/> <result column="job_class_name" jdbcType="VARCHAR" property="jobClassName"/> <result column="job_status" jdbcType="VARCHAR" property="jobStatus"/> <result column="create_by" jdbcType="VARCHAR" property="createBy"/> <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> <result column="modify_by" jdbcType="VARCHAR" property="modifyBy"/> <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/> </resultMap> <sql id="Base_Column_List"> id, job_group, job_name, description, cron_expression, job_class_name, job_status, create_by, create_time, modify_by, modify_time </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from task_quartz where id = #{id,jdbcType=BIGINT} </select> <select id="selectByJobNameAndJobGroup" resultType="cc.lisen.quartztask.entity.TaskQuartz"> select <include refid="Base_Column_List"/> from task_quartz where job_name = #{jonName,jdbcType=VARCHAR} and job_group = #{jobGroup,jdbcType=VARCHAR} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> delete from task_quartz where id = #{id,jdbcType=BIGINT} </delete> <delete id="deleteByJobNameAndJobGroup"> delete from task_quartz where job_name = #{jonName,jdbcType=VARCHAR} and job_group = #{jobGroup,jdbcType=VARCHAR} </delete> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="cc.lisen.quartztask.entity.TaskQuartz" useGeneratedKeys="true"> insert into task_quartz (job_group, job_name, description, cron_expression, job_class_name, job_status, create_by, create_time, modify_by, modify_time) values (#{jobGroup,jdbcType=VARCHAR}, #{jobName,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{cronExpression,jdbcType=VARCHAR}, #{jobClassName,jdbcType=VARCHAR}, #{jobStatus,jdbcType=VARCHAR}, #{createBy,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{modifyBy,jdbcType=VARCHAR}, #{modifyTime,jdbcType=TIMESTAMP}) </insert> <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="cc.lisen.quartztask.entity.TaskQuartz" useGeneratedKeys="true"> insert into task_quartz <trim prefix="(" suffix=")" suffixOverrides=","> <if test="jobGroup != null"> job_group, </if> <if test="jobName != null"> job_name, </if> <if test="description != null"> description, </if> <if test="cronExpression != null"> cron_expression, </if> <if test="jobClassName != null"> job_class_name, </if> <if test="jobStatus != null"> job_status, </if> <if test="createBy != null"> create_by, </if> <if test="createTime != null"> create_time, </if> <if test="modifyBy != null"> modify_by, </if> <if test="modifyTime != null"> modify_time, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="jobGroup != null"> #{jobGroup,jdbcType=VARCHAR}, </if> <if test="jobName != null"> #{jobName,jdbcType=VARCHAR}, </if> <if test="description != null"> #{description,jdbcType=VARCHAR}, </if> <if test="cronExpression != null"> #{cronExpression,jdbcType=VARCHAR}, </if> <if test="jobClassName != null"> #{jobClassName,jdbcType=VARCHAR}, </if> <if test="jobStatus != null"> #{jobStatus,jdbcType=VARCHAR}, </if> <if test="createBy != null"> #{createBy,jdbcType=VARCHAR}, </if> <if test="createTime != null"> #{createTime,jdbcType=TIMESTAMP}, </if> <if test="modifyBy != null"> #{modifyBy,jdbcType=VARCHAR}, </if> <if test="modifyTime != null"> #{modifyTime,jdbcType=TIMESTAMP}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="cc.lisen.quartztask.entity.TaskQuartz"> update task_quartz <set> <if test="jobGroup != null"> job_group = #{jobGroup,jdbcType=VARCHAR}, </if> <if test="jobName != null"> job_name = #{jobName,jdbcType=VARCHAR}, </if> <if test="description != null"> description = #{description,jdbcType=VARCHAR}, </if> <if test="cronExpression != null"> cron_expression = #{cronExpression,jdbcType=VARCHAR}, </if> <if test="jobClassName != null"> job_class_name = #{jobClassName,jdbcType=VARCHAR}, </if> <if test="jobStatus != null"> job_status = #{jobStatus,jdbcType=VARCHAR}, </if> <if test="createBy != null"> create_by = #{createBy,jdbcType=VARCHAR}, </if> <if test="createTime != null"> create_time = #{createTime,jdbcType=TIMESTAMP}, </if> <if test="modifyBy != null"> modify_by = #{modifyBy,jdbcType=VARCHAR}, </if> <if test="modifyTime != null"> modify_time = #{modifyTime,jdbcType=TIMESTAMP}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <update id="updateByPrimaryKey" parameterType="cc.lisen.quartztask.entity.TaskQuartz"> update task_quartz set job_group = #{jobGroup,jdbcType=VARCHAR}, job_name = #{jobName,jdbcType=VARCHAR}, description = #{description,jdbcType=VARCHAR}, cron_expression = #{cronExpression,jdbcType=VARCHAR}, job_class_name = #{jobClassName,jdbcType=VARCHAR}, job_status = #{jobStatus,jdbcType=VARCHAR}, create_by = #{createBy,jdbcType=VARCHAR}, create_time = #{createTime,jdbcType=TIMESTAMP}, modify_by = #{modifyBy,jdbcType=VARCHAR}, modify_time = #{modifyTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=BIGINT} </update> </mapper>TaskQuartz.java/** * @author laughing * @date 2020/9/30 * @site https://www.lisen.cc */ @Data public class TaskQuartz implements Serializable { private Long id; /** * 任务分组 */ private String jobGroup; /** * 任务名 */ private String jobName; /** * 任务描述 */ private String description; /** * cron表达式 */ private String cronExpression; /** * 任务执行时调用哪个类的方法 包名+类名 */ private String jobClassName; /** * 任务状态 */ private String jobStatus; /** * 创建者 */ private String createBy; /** * 创建时间 */ private Date createTime; /** * 更新者 */ private String modifyBy; /** * 更新时间 */ private Date modifyTime; private static final long serialVersionUID = 1L; }TaskQuartzService.java/** * @author laughing * @date 2020/9/30 * @site https://www.lisen.cc */ public interface TaskQuartzService { /** * 根据主键删除 * @param id 主键 * @return 删除行数 */ int deleteByPrimaryKey(Long id); /** * 插入 * @param record 实体 * @return 成功返回1 */ int insert(TaskQuartz record); /** * 插入修改的值 * @param record 实体 * @return 成功返回1 */ int insertSelective(TaskQuartz record); /** * 根据主键获取 * @param id 主键 * @return 实体 */ TaskQuartz selectByPrimaryKey(Long id); /** * 更新 * @param record 实体 * @return 更新成功返回1 */ int updateByPrimaryKeySelective(TaskQuartz record); /** * 更新所有值 * @param record 实体 * @return 成功返回1 */ int updateByPrimaryKey(TaskQuartz record); /** * 根据名称及分组查找 * @param jobName 任务名称 * @param jobGroup 任务分组 * @return 任务 */ TaskQuartz selectByJobNameAndJobGroup(@Param("jonName") String jobName, @Param("jobGroup") String jobGroup); /** * 根据名称及分组查找 * @param jobName 任务名称 * @param jobGroup 任务分组 * @return 任务 */ int deleteByJobNameAndJobGroup(@Param("jonName") String jobName,@Param("jobGroup") String jobGroup); }TaskQuartzServiceImpl.java/** * @author laughing * @date 2020/9/30 * @site https://www.lisen.cc */ @Service public class TaskQuartzServiceImpl implements TaskQuartzService { @Resource TaskQuartzMapper taskQuartzMapper; /** * 根据主键删除 * * @param id 主键 * @return 删除行数 */ @Override public int deleteByPrimaryKey(Long id) { return taskQuartzMapper.deleteByPrimaryKey(id); } /** * 插入 * * @param record 实体 * @return 成功返回1 */ @Override public int insert(TaskQuartz record) { return taskQuartzMapper.insert(record); } /** * 插入修改的值 * * @param record 实体 * @return 成功返回1 */ @Override public int insertSelective(TaskQuartz record) { return taskQuartzMapper.insertSelective(record); } /** * 根据主键获取 * * @param id 主键 * @return 实体 */ @Override public TaskQuartz selectByPrimaryKey(Long id) { return taskQuartzMapper.selectByPrimaryKey(id); } /** * 更新 * * @param record 实体 * @return 更新成功返回1 */ @Override public int updateByPrimaryKeySelective(TaskQuartz record) { return taskQuartzMapper.updateByPrimaryKeySelective(record); } /** * 更新所有值 * * @param record 实体 * @return 成功返回1 */ @Override public int updateByPrimaryKey(TaskQuartz record) { return taskQuartzMapper.updateByPrimaryKey(record); } /** * 根据名称及分组查找 * * @param jobName 任务名称 * @param jobGroup 任务分组 * @return 任务 */ @Override public TaskQuartz selectByJobNameAndJobGroup(String jobName, String jobGroup) { return taskQuartzMapper.selectByJobNameAndJobGroup(jobName,jobGroup); } /** * 根据名称及分组查找 * * @param jobName 任务名称 * @param jobGroup 任务分组 * @return 任务 */ @Override public int deleteByJobNameAndJobGroup(String jobName, String jobGroup) { return taskQuartzMapper.deleteByJobNameAndJobGroup(jobName,jobGroup); } } 增加测试任务PrintJob.java/** * @author laughing * @date 2020/9/30 * @site https://www.lisen.cc */ public class PrintJob implements Job { private final Logger logger = LoggerFactory.getLogger(PrintJob.class); /** * 执行任务 * * @param jobExecutionContext * @throws JobExecutionException */ @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { try { logger.info("Hello Job执行时间: " + new Date() + " Blog:" + jobExecutionContext.getJobDetail().getJobDataMap().get("blog")); Thread.sleep(1000 * 5); System.out.println("================执行完成========================"); } catch (Exception e) { e.printStackTrace(); } } }测试新增任务新增任务时,我们并没有创建quartz相关表,只是存储到task_quartz表中,任务启动时,插入quartz表 /** * 新增或者保存任务 * 任务只是存储到task_quartz表中,任务启动时,插入quartz表 * * @param taskQuartz 实体 * @return 结果 */ @RequestMapping("saveQuartz") public Result save(@RequestBody TaskQuartz taskQuartz) { TaskQuartz task = taskQuartzService.selectByJobNameAndJobGroup(taskQuartz.getJobName(), taskQuartz.getJobGroup()); if (task == null) { task = new TaskQuartz(); BeanUtils.copyProperties(taskQuartz, task); taskQuartzService.insertSelective(task); } else { taskQuartzService.updateByPrimaryKeySelective(taskQuartz); } return Result.ok(); }测试启动任务任务启动时,启动任务时,将任务信息持久化到quartz表中/** * 启用任务 * 启动任务时,将任务信息持久化到quartz表中 * * @param taskQuartz 实体 * @return 结果 */ @RequestMapping("startJob") public Result startJob(@RequestBody TaskQuartz taskQuartz) { try { JobKey jobKey = getJobKeyByTaskQuartz(taskQuartz); // 存在先删除 if (scheduler.checkExists(jobKey)) { scheduler.deleteJob(jobKey); } Class classz = Class.forName(taskQuartz.getJobClassName()); JobDetail jobDetail = JobBuilder.newJob() .withDescription(taskQuartz.getDescription()) .withIdentity(jobKey) .usingJobData("blog", "https://lisen.cc") .ofType(classz).build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("Trigger_" + taskQuartz.getJobName(), "TriggerGroup_" + taskQuartz.getJobGroup()) .withSchedule(CronScheduleBuilder.cronSchedule(taskQuartz.getCronExpression())) .startNow() .build(); scheduler.scheduleJob(jobDetail, trigger); } catch (Exception exception) { return Result.error(exception.getMessage()); } return Result.ok(); }通过postman测试,我们可以观察控制台,任务时10s执行一次暂停任务/** * 暂停任务 * * @param taskQuartz 实体 * @return 结果 */ @RequestMapping("shutdown") public Result shutdown(@RequestBody TaskQuartz taskQuartz) { try { JobKey jobKey = getJobKeyByTaskQuartz(taskQuartz); scheduler.pauseJob(jobKey); return Result.ok(); } catch (Exception ex) { return Result.error(ex.getMessage()); } }恢复任务 /** * 恢复任务 * * @param taskQuartz 实体 * @return 结果 */ @RequestMapping("resumeJob") public Result resumeJob(@RequestBody TaskQuartz taskQuartz) { try { JobKey jobKey = getJobKeyByTaskQuartz(taskQuartz); scheduler.resumeJob(jobKey); return Result.ok(); } catch (Exception ex) { return Result.error(ex.getMessage()); } }删除任务/** * 删除任务 * * @param taskQuartz 实体 * @return 结果 */ @RequestMapping("removeJob") public Result removeJob(@RequestBody TaskQuartz taskQuartz) { try { JobKey jobKey = getJobKeyByTaskQuartz(taskQuartz); scheduler.deleteJob(jobKey); taskQuartzService.deleteByJobNameAndJobGroup(taskQuartz.getJobName(),taskQuartz.getJobGroup()); return Result.ok(); } catch (Exception ex) { return Result.error(ex.getMessage()); } }
2020年09月30日
1,153 阅读
0 评论
0 点赞
2020-09-29
Spring Boot Quartz持久化存储
在spring boot quartz定时任务基本使用及介绍的博文中,我们简单介绍了quartz的基础概念及简单的使用,细心的童鞋可以发现,那个demo虽然能用,但是存在一个问题:一旦应用停止,计划任务变失效了。如何解决应用停止或者重启不会丢失计划任务信息,便是我们这篇博文要讨论的问题。Quartz提供两种基本作业存储类型:RAMJobStore :RAM也就是内存,默认情况下Quartz会将任务调度存在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,但程序崩溃或者重新发布的时候,所有运行信息都会丢失。JDBC作业存储:存到数据库之后,可以做单点也可以做集群,当任务多了之后,可以统一进行管理。关闭或者重启服务器,运行的信息都不会丢失。缺点就是运行速度快慢取决于连接数据库的快慢。Quartz初始化表MySQL# # 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; Oracle-- -- A hint submitted by a user: Oracle DB MUST be created as "shared" and the -- job_queue_processes parameter must be greater than 2 -- However, these settings are pretty much standard after any -- Oracle install, so most users need not worry about this. -- -- Many other users (including the primary author of Quartz) have had success -- runing in dedicated mode, so only consider the above as a hint ;-) -- delete from qrtz_fired_triggers; delete from qrtz_simple_triggers; delete from qrtz_simprop_triggers; delete from qrtz_cron_triggers; delete from qrtz_blob_triggers; delete from qrtz_triggers; delete from qrtz_job_details; delete from qrtz_calendars; delete from qrtz_paused_trigger_grps; delete from qrtz_locks; delete from qrtz_scheduler_state; drop table qrtz_calendars; drop table qrtz_fired_triggers; drop table qrtz_blob_triggers; drop table qrtz_cron_triggers; drop table qrtz_simple_triggers; drop table qrtz_simprop_triggers; drop table qrtz_triggers; drop table qrtz_job_details; drop table qrtz_paused_trigger_grps; drop table qrtz_locks; drop table qrtz_scheduler_state; CREATE TABLE qrtz_job_details ( SCHED_NAME VARCHAR2(120) NOT NULL, JOB_NAME VARCHAR2(200) NOT NULL, JOB_GROUP VARCHAR2(200) NOT NULL, DESCRIPTION VARCHAR2(250) NULL, JOB_CLASS_NAME VARCHAR2(250) NOT NULL, IS_DURABLE VARCHAR2(1) NOT NULL, IS_NONCONCURRENT VARCHAR2(1) NOT NULL, IS_UPDATE_DATA VARCHAR2(1) NOT NULL, REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, JOB_DATA BLOB NULL, CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) ); CREATE TABLE qrtz_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, JOB_NAME VARCHAR2(200) NOT NULL, JOB_GROUP VARCHAR2(200) NOT NULL, DESCRIPTION VARCHAR2(250) NULL, NEXT_FIRE_TIME NUMBER(13) NULL, PREV_FIRE_TIME NUMBER(13) NULL, PRIORITY NUMBER(13) NULL, TRIGGER_STATE VARCHAR2(16) NOT NULL, TRIGGER_TYPE VARCHAR2(8) NOT NULL, START_TIME NUMBER(13) NOT NULL, END_TIME NUMBER(13) NULL, CALENDAR_NAME VARCHAR2(200) NULL, MISFIRE_INSTR NUMBER(2) NULL, JOB_DATA BLOB NULL, CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK 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 VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, REPEAT_COUNT NUMBER(7) NOT NULL, REPEAT_INTERVAL NUMBER(12) NOT NULL, TIMES_TRIGGERED NUMBER(10) NOT NULL, CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_cron_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, CRON_EXPRESSION VARCHAR2(120) NOT NULL, TIME_ZONE_ID VARCHAR2(80), CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_simprop_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, STR_PROP_1 VARCHAR2(512) NULL, STR_PROP_2 VARCHAR2(512) NULL, STR_PROP_3 VARCHAR2(512) NULL, INT_PROP_1 NUMBER(10) NULL, INT_PROP_2 NUMBER(10) NULL, LONG_PROP_1 NUMBER(13) NULL, LONG_PROP_2 NUMBER(13) NULL, DEC_PROP_1 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(13,4) NULL, BOOL_PROP_1 VARCHAR2(1) NULL, BOOL_PROP_2 VARCHAR2(1) NULL, CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_blob_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, BLOB_DATA BLOB NULL, CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_calendars ( SCHED_NAME VARCHAR2(120) NOT NULL, CALENDAR_NAME VARCHAR2(200) NOT NULL, CALENDAR BLOB NOT NULL, CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) ); CREATE TABLE qrtz_paused_trigger_grps ( SCHED_NAME VARCHAR2(120) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) ); CREATE TABLE qrtz_fired_triggers ( SCHED_NAME VARCHAR2(120) NOT NULL, ENTRY_ID VARCHAR2(95) NOT NULL, TRIGGER_NAME VARCHAR2(200) NOT NULL, TRIGGER_GROUP VARCHAR2(200) NOT NULL, INSTANCE_NAME VARCHAR2(200) NOT NULL, FIRED_TIME NUMBER(13) NOT NULL, SCHED_TIME NUMBER(13) NOT NULL, PRIORITY NUMBER(13) NOT NULL, STATE VARCHAR2(16) NOT NULL, JOB_NAME VARCHAR2(200) NULL, JOB_GROUP VARCHAR2(200) NULL, IS_NONCONCURRENT VARCHAR2(1) NULL, REQUESTS_RECOVERY VARCHAR2(1) NULL, CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID) ); CREATE TABLE qrtz_scheduler_state ( SCHED_NAME VARCHAR2(120) NOT NULL, INSTANCE_NAME VARCHAR2(200) NOT NULL, LAST_CHECKIN_TIME NUMBER(13) NOT NULL, CHECKIN_INTERVAL NUMBER(13) NOT NULL, CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) ); CREATE TABLE qrtz_locks ( SCHED_NAME VARCHAR2(120) NOT NULL, LOCK_NAME VARCHAR2(40) NOT NULL, CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME) ); create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); postgresql-- Thanks to Patrick Lightbody for submitting this... -- -- In your Quartz properties file, you'll need to set -- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate DROP TABLE IF EXISTS qrtz_fired_trigger`s; 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_cron_triggers; DROP TABLE IF EXISTS qrtz_simprop_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 BOOL NOT NULL, IS_NONCONCURRENT BOOL NOT NULL, IS_UPDATE_DATA BOOL NOT NULL, REQUESTS_RECOVERY BOOL NOT NULL, JOB_DATA BYTEA 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 NULL, PREV_FIRE_TIME BIGINT NULL, PRIORITY INTEGER NULL, TRIGGER_STATE VARCHAR(16) NOT NULL, TRIGGER_TYPE VARCHAR(8) NOT NULL, START_TIME BIGINT NOT NULL, END_TIME BIGINT NULL, CALENDAR_NAME VARCHAR(200) NULL, MISFIRE_INSTR SMALLINT NULL, JOB_DATA BYTEA 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 NOT NULL, REPEAT_INTERVAL BIGINT NOT NULL, TIMES_TRIGGERED BIGINT 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(120) 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 BOOL NULL, BOOL_PROP_2 BOOL 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 BYTEA 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 BYTEA 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 NOT NULL, SCHED_TIME BIGINT NOT NULL, PRIORITY INTEGER NOT NULL, STATE VARCHAR(16) NOT NULL, JOB_NAME VARCHAR(200) NULL, JOB_GROUP VARCHAR(200) NULL, IS_NONCONCURRENT BOOL NULL, REQUESTS_RECOVERY BOOL 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 NOT NULL, CHECKIN_INTERVAL BIGINT 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) ); create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY); create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME); create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP); create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE); create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME); create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE); create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE); create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME); create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY); create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP); create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP); create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP); create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP); commit; 其余的配置文件,大家可以去官网下载配置依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency>配置文件quartz.properties###################jdbcJobStore############################ org.quartz.scheduler.instanceName=MyScheduler org.quartz.scheduler.instanceId=AUTO org.quartz.threadPool.threadCount=3 # 所有的quartz数据例如job和Trigger的细节信息被保存在内存或数据库中,有两种实现:JobStoreTX(自己管理事务) #和JobStoreCMT(application server管理事务,即全局事务JTA) org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX # 类似于Hibernate的dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.StdJDBCDelegate #数据库表的前缀 org.quartz.jobStore.tablePrefix=QRTZ_ #配置数据源的名称 org.quartz.jobStore.dataSource=myDS #为了指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true(缺省方式) org.quartz.jobStore.useProperties = true # 检入到数据库中的频率(毫秒)。检查是否其他的实例到了应当检入的时候未检入这能指出一个失败的实例, #且当前Scheduler会以此来接管执行失败并可恢复的Job通过检入操作,Scheduler也会更新自身的状态记录 org.quartz.jobStore.clusterCheckinInterval=20000 # 是否集群、负载均衡、容错,如果应用在集群中设置为false会出错 org.quartz.jobStore.isClustered=false #misfire时间设置 org.quartz.jobStore.misfireThreshold=60000 # 连接超时重试连接的间隔。使用 RamJobStore时,该参数并没什么用【默认15000】【非必须】 #org.quartz.scheduler.dbFailureRetryInterval = 15000 #下面是数据库链接相关的配置 org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=UTC org.quartz.dataSource.myDS.user=root org.quartz.dataSource.myDS.password=root org.quartz.dataSource.myDS.maxConnections=5 使用定义Job类package org.lisen.quartzjdbc.scheduler; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.SimpleDateFormat; import java.util.Date; /** * @author laughing * @date 2020/9/29 * @site https://www.lisen.cc */ public class PrintService implements Job { private final Logger logger = LoggerFactory.getLogger(PrintService.class); /** * 执行 * @param jobExecutionContext * @throws JobExecutionException */ @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); } } 创建计划任务/** * @author laughing * @date 2020/9/29 * @site https://www.lisen.cc */ @RestController public class QuartzController { @RequestMapping("/quartzJdbc") public String quartzJdbc() throws SchedulerException { Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger","triGroup") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1) .withRepeatCount(0)) .build(); JobDetail job = JobBuilder.newJob(PrintService.class) .usingJobData("JobKey","JobValue") .withIdentity("Job","JobGroup") .withDescription("打印任务") .build(); scheduler.scheduleJob(job, trigger); scheduler.pauseAll(); return "success"; } }
2020年09月29日
1,443 阅读
0 评论
0 点赞
2020-09-29
Mac brew常见软件安装目录及命令
Homebrew 是一款Mac OS平台下的软件包管理工具,官方称之为:The missing package manager for OS X。Homebrew(官网地址:https://brew.sh)拥有安装、卸载、更新、查看、搜索等很多实用的功能, 简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径的情况,十分方便快捷。例如:安装 chrome,只需输入:brew cask install chrome 即可。 脑壳不太好使,一些东西老是健忘,开此贴,专门记录一下brew常见软件的一些使用说明{mtitle title="Nginx相关"/}默认安装位置/usr/local/etc/nginx默认html地址/usr/local/var/www{mtitle title="MySQL相关"/}MySQL常用命令将MySQL添加到环境变量echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.zshrc启动MySQLmysql.server start停止MySQLmysql.server stopMySQL信息用户名:root密码:root{mtitle title="Redis相关"/}Redis常用命令启动Redisredis-server /usr/local/etc/redis.conf
2020年09月29日
1,203 阅读
0 评论
1 点赞
2020-09-29
spring boot quartz定时任务基本使用及介绍
什么是QuartzQuartz是一个完全由java编写的开源作业调度框架,由OpenSymphony组织开源出来。所谓作业调度其实就是按照程序的设定,某一时刻或者时间间隔去执行某个代码。最常用的就是报表的制作了。Quartz基本使用添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>创建Job/** * @author laughing * @date 2020/9/29 * @site https://www.lisen.org */ public class PrintJobService implements Job { private final Logger logger = LoggerFactory.getLogger(PrintJobService.class); /** * 任务执行 * * @param jobExecutionContext 任务执行信息 */ @Override public void execute(JobExecutionContext jobExecutionContext) { logger.info("准备获取scheduler参数"); try { String schedulerValue = jobExecutionContext.getScheduler().getContext().getString("sKey"); logger.info(schedulerValue); } catch (SchedulerException e) { e.printStackTrace(); } logger.info("完成获取scheduler参数\n"); logger.info("准备获取TriggerData"); JobDataMap triggerDataMap = jobExecutionContext.getTrigger().getJobDataMap(); for (String triggerKey : triggerDataMap.getKeys()) { logger.info(triggerDataMap.getString(triggerKey)); } logger.info("完成获取TriggerData\n"); logger.info("准备获取JobData"); JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); for (String triggerKey : jobDataMap.getKeys()) { logger.info(jobDataMap.getString(triggerKey)); } logger.info("完成获取JobData"); } }使用/** * @author laughing * @date 2020/9/29 * @site https://www.lisen.org */ @RestController public class QuartzController { @RequestMapping("/quartz") public String quartz() throws SchedulerException { //创建一个scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); //通过scheduler传参数 scheduler.getContext().put("sKey", "sValue"); //创建一个Trigger Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group1") .usingJobData("t1", "tv1") //3秒执行一次 .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3) //执行1次 .withRepeatCount(0)) .build(); trigger.getJobDataMap().put("t2", "tv2"); //创建一个job JobDetail job = JobBuilder.newJob(PrintJobService.class) .usingJobData("j1", "jv1") .withIdentity("myJob", "myGroup").build(); job.getJobDataMap().put("j2", "jv2"); //注册trigger并启动scheduler scheduler.scheduleJob(job, trigger); scheduler.start(); return "success"; } }Quartz的基本组成一、调度器(Scheduler)调度器用来管理触发器和作业。Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中都拥有自己的唯一的组和名称用来进行彼此的区分,Scheduler可以通过组名或者名称来对Trigger和JobDetail来进行管理。一个Trigger只能对应一个Job,但是一个Job可以对应多个Trigger。每个Scheduler都包含一个SchedulerContext,用来保存Scheduler的上下文。Job和Trigger都可以获取SchedulerContext中的信息。Scheduler包含两个重要的组件,JobStore和ThreadPool。JobStore用来存储运行时信息,包括Trigger,Schduler,JobDetail,业务锁等。它有多种实现RAMJob(内存实现),JobStoreTX(JDBC,事务由Quartz管理)等。ThreadPool就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行。Scheduler是由SchdulerFactory创建,它有两个实现:DirectSchedulerFactory和StdSchdulerFactory。前者可以用来在代码里定制你自己的Schduler参数。后者是直接读取classpath下的quartz.properties(不存在就都使用默认值)配置来实例化Schduler。通常来讲,我们使用StdSchdulerFactory也就足够了二、触发器(Trigger)Trigger是用来定义Job的执行规则,直白的说就是什么时间、重复多少次。主要有四种触发器,其中SimpleTrigger和CronTrigger触发器用的最多。SimpleTrigger从某一个时间开始,以一定的时间间隔来执行任务。它主要有两个属性,repeatInterval 重复的时间间隔;repeatCount重复的次数,实际上执行的次数是n+1,因为在startTime的时候会执行一次。CronTrigger适合于复杂的任务,使用cron表达式来定义执行规则。CalendarIntervalTrigger类似于SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是CalendarIntervalTrigger执行任务的时间间隔比SimpleTrigger要丰富,它支持的间隔单位有秒,分钟,小时,天,月,年,星期。相较于SimpleTrigger有两个优势:1、更方便,比如每隔1小时执行,你不用自己去计算1小时等于多少毫秒。 2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒。它的主要两个属性,interval 执行间隔;intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期)DailyTimeIntervalTrigger指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。它适合的任务类似于:指定每天9:00 至 18:00 ,每隔70秒执行一次,并且只要周一至周五执行。它的属性有startTimeOfDay 每天开始时间;endTimeOfDay 每天结束时间;daysOfWeek 需要执行的星期;interval 执行间隔;intervalUnit 执行间隔的单位(秒,分钟,小时,天,月,年,星期);repeatCount 重复次数所有的trigger都包含了StartTime和endTIme这两个属性,用来指定Trigger被触发的时间区间。所有的trigger都可以设置MisFire策略,该策略是对于由于系统奔溃或者任务时间过长等原因导致trigger在应该触发的时间点没有触发,并且超过了misfireThreshold设置的时间(默认是一分钟,没有超过就立即执行)就算misfire了,这个时候就该设置如何应对这种变化了。激活失败指令(Misfire Instructions)是触发器的一个重要属性,它指定了misfire发生时调度器应当如何处理。所有类型的触发器都有一个默认的指令,叫做Trigger.MISFIRE_INSTRUCTION_SMART_POLICY,但是这个这个“聪明策略”对于不同类型的触发器其具体行为是不同的。对于SimpleTrigger,这个“聪明策略”将根据触发器实例的状态和配置来决定其行 为。具体如下:如果Repeat Count=0:只执行一次instruction selected = MISFIRE_INSTRUCTION_FIRE_NOW;如果Repeat Count=REPEAT_INDEFINITELY:无限次执行instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;如果Repeat Count>0: 执行多次(有限)instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;SimpleTrigger常见策略:MISFIRE_INSTRUCTION_FIRE_NOW 立刻执行。对于不会重复执行的任务,这是默认的处理策略。MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT 在下一个激活点执行,且超时期内错过的执行机会作废。MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_COUNT 立即执行,且超时期内错过的执行机会作废。MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT 在下一个激活点执行,并重复到指定的次数。MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_COUNT 立即执行,并重复到指定的次数。MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY 忽略所有的超时状态,按照触发器的策略执行。对于CronTrigger,该“聪明策略”默认选择MISFIRE_INSTRUCTION_FIRE_ONCE_NOW以指导其行为。CronTrigger常见策略:MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 立刻执行一次,然后就按照正常的计划执行。MISFIRE_INSTRUCTION_DO_NOTHING 目前不执行,然后就按照正常的计划执行。这意味着如果下次执行时间超过了end time,实际上就没有执行机会了。三、作业(Job)Job是一个任务接口,开发者定义自己的任务须实现该接口实现void execute(JobExecutionContext context)方法,JobExecutionContext中提供了调度上下文的各种信息。Job中的任务有可能并发执行,例如任务的执行时间过长,而每次触发的时间间隔太短,则会导致任务会被并发执行。如果是并发执行,就需要一个数据库锁去避免一个数据被多次处理。可以在execute()方法上添加注解@DisallowConcurrentExecution解决这个问题。四、作业详情(JobDetail)Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。因此需要通过一个类来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息,JobDetail承担了这一角色。所以说JobDetail是任务的定义,而Job是任务的执行逻辑。五、日历(Calendar)Calendar:org.quartz.Calendar和java.util.Calendar不同,它是一些日历特定时间点的集合(可以简单地将org.quartz.Calendar看作java.util.Calendar的集合——java.util.Calendar代表一个日历时间点,无特殊说明后面的Calendar即指org.quartz.Calendar)。一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。主要有以下CalendarHolidayCalendar:指定特定的日期,比如20140613。精度到天。DailyCalendar:指定每天的时间段(rangeStartingTime, rangeEndingTime),格式是HH:MM[:SS[:mmm]],也就是最大精度可以到毫秒。WeeklyCalendar:指定每星期的星期几,可选值比如为java.util.Calendar.SUNDAY。精度是天。MonthlyCalendar:指定每月的几号。可选值为1-31。精度是天AnnualCalendar: 指定每年的哪一天。使用方式如上例。精度是天。CronCalendar:指定Cron表达式。精度取决于Cron表达式,也就是最大精度可以到秒。六、JobDataMap用来保存JobDetail运行时的信息,JobDataMap的使用:.usingJobData("name","kyle")或者.getJobDataMap("name","kyle")七、cron表达式Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如, 在分钟字段时,表示“每分钟”;问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符;减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12;逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;斜杠(/):x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y;L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五;W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围;LW组合:在日期字段可以组合使用LW,它的意思是当月的最后一个工作日;井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发;C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。八、quartz.properties文件编写RAMJob的配置####################RAMJob的配置################## #在集群中每个实例都必须有一个唯一的instanceId,但是应该有一个相同的instanceName【默认“QuartzScheduler”】【非必须】 org.quartz.scheduler.instanceName = MyScheduler #Scheduler实例ID,全局唯一,【默认值NON_CLUSTERED】,或者可以使用“SYS_PROP”通过系统属性设置id。【非必须】 org.quartz.scheduler.instanceId=AUTO # 线程池的实现类(定长线程池,几乎可满足所有用户的需求)【默认null】【必须】 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool # 指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)【默认-1】【必须】 org.quartz.threadPool.threadCount = 25 # 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1)【默认Thread.NORM_PRIORITY (5)】【非必须】 org.quartz.threadPool.threadPriority = 5 #misfire设置的时间默认为一分钟 org.quartz.jobStore.misfireThreshold=60000 # 将schedule相关信息保存在RAM中,轻量级,速度快,遗憾的是应用重启时相关信息都将丢失。 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore # 建议设置为“org.terracotta.quartz.skipUpdateCheck=true”不会在程序运行中还去检查quartz是否有版本更新。【默认false】【非必须】 org.quartz.scheduler.skipUpdateCheck = truejdbcJobStore配置###################jdbcJobStore############################ org.quartz.scheduler.instanceName=MyScheduler org.quartz.scheduler.instanceId=AUTO org.quartz.threadPool.threadCount=3 # 所有的quartz数据例如job和Trigger的细节信息被保存在内存或数据库中,有两种实现:JobStoreTX(自己管理事务) #和JobStoreCMT(application server管理事务,即全局事务JTA) org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX # 类似于Hibernate的dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB org.quartz.jobStore.driverDelegateClass =org.quartz.impl.jdbcjobstore.StdJDBCDelegate #数据库表的前缀 org.quartz.jobStore.tablePrefix=QRTZ_ #配置数据源的名称 org.quartz.jobStore.dataSource=myDS #为了指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true(缺省方式) org.quartz.jobStore.useProperties = true # 检入到数据库中的频率(毫秒)。检查是否其他的实例到了应当检入的时候未检入这能指出一个失败的实例, #且当前Scheduler会以此来接管执行失败并可恢复的Job通过检入操作,Scheduler也会更新自身的状态记录 org.quartz.jobStore.clusterCheckinInterval=20000 # 是否集群、负载均衡、容错,如果应用在集群中设置为false会出错 org.quartz.jobStore.isClustered=false #misfire时间设置 org.quartz.jobStore.misfireThreshold=60000 # 连接超时重试连接的间隔。使用 RamJobStore时,该参数并没什么用【默认15000】【非必须】 #org.quartz.scheduler.dbFailureRetryInterval = 15000 #下面是数据库链接相关的配置 org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/zproject?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=UTC org.quartz.dataSource.myDS.user=root org.quartz.dataSource.myDS.password=root org.quartz.dataSource.myDS.maxConnections=5参考资料quartz基本介绍和使用
2020年09月29日
1,213 阅读
0 评论
0 点赞
2020-09-28
利用jib-maven-plugin一键部署docker镜像
前言jib-maven-plugin是谷歌出品的为您的Java应用程序构建Docker和OCI镜像的Maven插件。申请Docker容器这里已部署到Docker为例介绍,关于Docker容器的申请,可以 点击maven中使用通过在pom.xml文件加入插件引入spring boot工程<plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>1.7.0</version> <configuration> <!--from节点用来设置镜像的基础镜像,相当于Docerkfile中的FROM关键字--> <from> <!--从openjdk:alpine的基础上建造--> <image>openjdk:alpine</image> </from> <to> <!--镜像名称和tag--> <image>docker.io/iamlisen/dockerjib</image> <tags> <tag>v1</tag> </tags> <auth> <username>用户名</username> <password>密码</password> </auth> </to> <!--容器相关的属性--> <container> <!--jvm内存参数--> <jvmFlags> <jvmFlag>-Xms4g</jvmFlag> <jvmFlag>-Xmx4g</jvmFlag> </jvmFlags> <!--要暴露的端口--> <ports> <port>8080</port> </ports> </container> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>build</goal> </goals> </execution> </executions> </plugin>参数解释从docker-hub拉取openjdk:alpine镜像作为基础镜像构建标识为your_image的镜像,tag列表为v1容器启动时将通过java -Xms4g -Xmx4g并且暴露出端口8080docker构建绑定到package生命周期构建docker镜像通过以下命令构建docker镜像mvn compile jib:build配置通过将镜像设置为“推送”来配置插件:使用谷歌容器确保你有docker-credential-gcr命令行工具。Jib自动使用docker-credential-gcr来获取凭证。参阅其他认证的验证方法。例如,为了构建镜像gcr.io/my-gcp-project/my-app,配置将是:<configuration> <to> <image>gcr.io/my-gcp-project/my-app</image> </to> </configuration>使用亚马逊容器确保你有docker-credential-ecr-login命令行工具。Jib自动使用docker-credential-ecr-login来获取凭证。参阅其他认证的验证方法。例如,为了构建镜像aws_account_id.dkr.ecr.region.amazonaws.com/my-app,配置将是:<configuration> <to> <image>aws_account_id.dkr.ecr.region.amazonaws.com/my-app</image> </to> </configuration>使用Docker容器确保你有一个 docker-credential-helper设置。例如,在macOS,凭证助手将是docker-credential-osxkeychain。参阅其他认证的验证方法。例如,为了构建镜像my-docker-id/my-app,配置将是:<configuration> <to> <image>registry.hub.docker.com/my-docker-id/my-app</image> </to> </configuration>扩展扩展选项提供额外的配置选项为定制镜像生成。属性类型默认值描述totoRequired配置目标镜像以构建应用程序。fromfrom查看from配置基础镜像以构建应用程序的顶部。containercontainer查看container配置从镜像中运行的容器。allowInsecureRegistriesbooleanfalse如果设置为true,Jib忽略HTTPS证书错误,并可能退回HTTP作为最后的手段。强烈建议将这个参数设置为false,因为HTTP通信是未加密的,并且对于网络上的其他人来说是可见的,并且不安全的HTTPS并不比普通的HTTP好。如果使用自签名证书访问注册表,则将证书添加到Java运行时的可信密钥可能是启用此选项的另一种选择。skipbooleanfalse如果设置为true,则跳过Jib执行(对于多模块项目是有用的)。这也可以通过-Djib.skip跳过命令行选项来指定。useOnlyProjectCachebooleanfalse如果设置为true,Jib不会在不同的Maven项目之间共享缓存。from是具有以下属性的对象:属性类型默认值描述imagestringgcr.io/distroless/java基础的镜像参考。authauthNone直接指定凭证。credHelperstringNone证书助手的后缀,它可以对基础镜像进行身份验证(遵循docker-credential-)。to是具有以下属性的对象:属性类型默认值描述imagestringRequired目标镜像的参考。这也可以通过-Dimage命令行选项来指定。authauthNone直接指定凭证。credHelperstringNone证书助手的后缀,它可以对基础镜像进行身份验证(遵循docker-credential-)。tagslistNone额外的标签推向auth是一个具有以下属性的对象(请参阅使用特定凭据):属性类型描述usernamestring用户名passwordstring密码container是具有以下属性的对象:属性类型默认值描述appRootstring/app容器上放置应用程序内容的根目录。argslistNone默认的主方法参数来运行应用程序。entrypointlistNone启动容器的命令(类似于Docker的入口点指令)。如果设置,则忽略jvmFlags和mainClass。environmentmapNone键值对,用于设置容器上的环境变量(类似于Docker的Env指令)。formatstringDocker使用OCI构建OCI容器映像jvmFlagslistNone运行应用程序时要传递给JVM的附加标志。labelsmapNone用于应用镜像元数据的键值对(类似于Docker的标签指令)。mainClassstringInferred*主要类从应用程序启动。portslistNone容器在运行时暴露的端口(类似于Docker的公开指令)。useCurrentTimestampbooleanfalse默认情况下,Jib擦除所有时间戳以保证再现性。如果这个参数设置为true,Jib将把镜像的创建时间戳设置为构建时间,这将牺牲可再现性,以便能够容易地判断镜像何时创建。您还可以使用connection/read系统属性为注册表交互配置HTTP连接/读取超时,该属性通过命令行以毫秒为单位配置(缺省值是20000;您还可以将其设置为0用于无限超时):mvn compile jib:build -Djib.httpTimeout=3000
2020年09月28日
2,042 阅读
0 评论
2 点赞
2020-09-28
Spring Boot 启动任务
启动任务场景如果在项目启动阶段要做一些数据初始化操作,例如配置文件加载、数据库初始化等操作。这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行。这种,我们可以通过启动任务来完成。实现启动任务使用CommandLineRunner实现基本介绍Spring Boot 项目在启动时会遍历所有的 CommandLineRunner的实现类并调用其中的 run方法。如果整个系统中有多个 CommandLineRunner 的实现类,那么可以使用 @Order 注解对这些实现类的调用顺序进行排序(数字越小越先执行)。run 方法的参数是系统启动是传入的参数,即入口类中 main 方法的参数(在调用 SpringApplication.run 方法时被传入 Spring Boot 项目中)CommandLineRunner使用定义CommandLineRunner实现类定义两个实现类MyCommandLineRunner101、MyCommandLineRunner102,分别设置执行顺序为101和102。MyCommandLineRunner101.java/** * 顺序号是101的启动任务 * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Component @Order(101) public class MyCommandLineRunner101 implements CommandLineRunner { @Override public void run(String... args) { System.out.println("order--101--" + Arrays.toString(args)); } }MyCommandLineRunner102.java/** * 顺序号是102的启动任务 * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Component @Order(102) public class MyCommandLineRunner102 implements CommandLineRunner { @Override public void run(String... args) { System.out.println("order--102--" + Arrays.toString(args)); } }idea测试配置Program arguments,如下jar 包测试java -jar runner-0.0.1-SNAPSHOT.jar Hello World查看输出通过输出结果,我们可以看到,内容正确按照设置的order顺序进行输出。ApplicationRunner基本介绍ApplicationRunner 用法和CommandLineRunner 基本一致。项目在启动时会遍历所有的 ApplicationRunner 的实现类并调用其中的 run 方法。如果整个系统中有多个ApplicationRunner 的实现类,同样可以使用 @Order 注解对这些实现类的调用顺序进行排序(数字越小越先执行)。ApplicationRunner 与 CommandLineRunner 的区别主要体现在 run 方法的参数上。不同于 CommandLineRunner 中的 run 方法的数组参数,ApplicationRunner 里 run 方法的参数是一个 ApplicationArguments 对象ApplicationArguments 区分选项参数和非选项参数对于非选项参数:我们可以通过 ApplicationArguments 的 getNonOptionArgs() 方法获取,获取到的是一个数组。对于选项参数:可以通过 ApplicationArguments 的 getOptionNames() 方法获取所有选项名称。通过 getOptionValues() 方法获取实际值(它会返回一个列表字符串)。使用定义ApplicationRunner实现类定义两个实现类MyApplicationRunner103、MyApplicationRunner104,分别设置执行顺序为103和104。MyApplicationRunner103.java/** * 顺序号103 * * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Component @Order(103) public class MyApplicationRunner103 implements ApplicationRunner { @Override public void run(ApplicationArguments args) { System.out.println("开始输出103的ApplicationRunner"); System.out.println("开始输出103可选参数"); Set<String> optionNames = args.getOptionNames(); for (String optionName : optionNames) { System.out.println(args.getOptionValues(optionName)); } System.out.println("可选参数103输出完毕"); System.out.println("开始输出103非可选参数"); List<String> nonOptionArgs = args.getNonOptionArgs(); for (String nonOptionArg : nonOptionArgs) { System.out.println(nonOptionArg); } System.out.println("非可选参数103输出完毕"); } }MyApplicationRunner104.java/** * 顺序号104 * * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Component @Order(104) public class MyApplicationRunner104 implements ApplicationRunner { @Override public void run(ApplicationArguments args) { System.out.println("开始输出104的ApplicationRunner"); System.out.println("开始输出104可选参数"); Set<String> optionNames = args.getOptionNames(); for (String optionName : optionNames) { System.out.println(args.getOptionValues(optionName)); } System.out.println("可选参数104输出完毕"); System.out.println("开始输出104非可选参数"); List<String> nonOptionArgs = args.getNonOptionArgs(); for (String nonOptionArg : nonOptionArgs) { System.out.println(nonOptionArg); } System.out.println("非可选参数104输出完毕"); } }
2020年09月28日
1,253 阅读
0 评论
0 点赞
2020-09-28
Spring Boot 配合nginx完成跨域配置
在 springboot配置跨域 我们介绍了spring boot两种配置跨域的方式。实际项目中,我用的一般是通过nginx进行跨域设置。nginx跨域实现的几个目标肯定是能正常跨域访问为了方便跨域,我们一般对后台api进行封装,统一返回一个前缀作为区分我们先来实现第二个目标,统一后端返回的api地址。方法一、通过yaml配置通过配置文件设置server: servlet: context-path: /api这样,我们在前端的请求,都会自动加上'/api'前缀。但是这样的设置存在两个问题:所有的请求全部都是'/api'前缀。静态资源要求带'/api'前缀。所以,我们需要通过更优雅的方式来进行设置,也就是方法二。方法二、通过实现WebMvcConfigurer接口的configurePathMatch方法首先我们在配置文件,增加自定义的前缀#配置api前缀 request-path: api-path: /api注入配置信息/** * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Configuration @ConfigurationProperties(prefix = "request-path") @Data public class RequestPathProperties { private String apiPath; }增加自定义注解/** * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @RestController @Target({ElementType.TYPE}) @Documented @RequestMapping @Retention(RetentionPolicy.RUNTIME) public @interface ApiRestController { /** * Alias for {@link RequestMapping#name}. */ @AliasFor(annotation = RequestMapping.class) String name() default ""; /** * Alias for {@link RequestMapping#value}. */ @AliasFor(annotation = RequestMapping.class) String[] value() default {}; /** * Alias for {@link RequestMapping#path}. */ @AliasFor(annotation = RequestMapping.class) String[] path() default {}; }增加实现WebMvcConfigurer的configurePathMatch方法,配置前缀/** * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @Configuration public class MyWebMvcConfig implements WebMvcConfigurer { @Resource RequestPathProperties requestPathProperties; @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.addPathPrefix(requestPathProperties.getApiPath(), c->c.isAnnotationPresent(ApiRestController.class)); } }经过如上配置,我们所有注解@ApiRestController的请求,都会增加'/api'前缀增加两个配置类,一个通过@ApiRestController注解,一个通过普通的@RestController注解,分别访问测试/** * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @ApiRestController public class NginxCorsController { @RequestMapping("/nginxCors") public String nginxCors(){ return "nginxCors"; } }/** * @author laughing * @date 2020/9/26 * @site https://lisen.cc */ @RestController public class NormalController { @RequestMapping("/normal") public String normal(){ return "normal"; } }支持,完成了spring boot后台统一api地址的目标nginx配置跨域前端代码我们先配置前端页面,发起一个简单的post请求<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <div id="myDiv"></div> <script> $(document).ready(function () { $.ajax({ url: "/api/nginxCors", type:"post", async: false, success:function(data){ $("#myDiv").html(data); } }); }); </script> </body> </html>nginx配置我们要配置的规则很简单,所有/api开头的请求,全部重定向到后端spring boot上。打开nginx配置文件,我这里使用的是默认的,及'nginx.conf'修改locationserver { listen 1234; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; #简单配置跨域 location /api { proxy_pass http://localhost:8080/api/; } location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }重新加载nginx配置文件这里用的win,linux需要对应替换命令nginx.exe -s reload打开页面测试,可以看到能够正常跨域
2020年09月28日
1,752 阅读
0 评论
0 点赞
1
...
34
35
36
...
53