玩转 Spring Boot 入门篇
Posted 一猿小讲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩转 Spring Boot 入门篇相关的知识,希望对你有一定的参考价值。
Spring 颠覆了 Java 企业级项目的开发,使得企业级的开发由重变轻、由繁至简,可谓是为 Java 程序员带来了春天。
Spring Boot 是 Spring 框架对“约定优于配置”理念的最佳实践的产物,带来了自动配置、开箱即用、完善的监控体系等诸多特性,着实让你逃离繁琐的 XML 配置,更加专注于业务逻辑开发,可谓是 Java 程序员的又一春。
坊间传闻:由于 Spring Boot 将 Spring 开发的自动化程度提升到了一个新的高度,正式让 Spring 风云再起;由于 Spring Boot 的魔法(自动配置、内嵌容器、应用监控等)降低研发的难度,横扫 Spring 在你成功路上的绊脚石。官方宣称:Spring Boot 开箱即用,绝对没有代码生成,也不需要 XML 配置。
Spring Boot 如此之玄妙?你是否已按捺不住,想要亲自操刀,跃跃欲试?一探究竟?
莫急,先大致了解一下本次分享的内容大纲,然后再磨刀霍霍向 Spring Boot。
1. 磨刀不误砍柴工。
为了后续项目实战的需要,也避免后续因为环境不同而导致的差异化问题,在正式敲开 SpringBoot 大门之前,有必要先统一依赖的研发环境。
JDK 版本:java version "1.8.0_251"
Maven 版本:Apache Maven 3.3.9
Spring Boot 的版本:Spring Boot 2.6.2
开发工具:Intellij IDEA
具体的安装步骤,网上的文章比比皆是,可跟随谷哥或度娘的指示,一步一步傻瓜式的安装操作,相信肯定难不倒你,本文不做赘述。
接下来花一分钟的时间,快速搭建 Spring Boot 项目。
2. 快速敲开 Spring Boot 的大门
2.1. 创建 SpringBoot 项目
创建 Spring Boot 项目的招式(使用 Spring Initializr 、Spring TooI Suite、InteIIiJ IDEA 等)有很多种,切记不要太在意这些招式,挑花拳绣腿练一练。
花拳:用 Spring Initializr 构建 Spring Boot 项目。
浏览器直接访问 https://start.spring.io/ 链接,便可打开 Spring Initializer 的 Web 页面。
虽然成年人不做选择题,但是此时的确需要做如下两个选择:
选择 Java 的版本:与 JDK 安装版本保持一致,本文的实验环境为 JDK 1.8 ,所以选择 8;
选择 Web 依赖包:为了更好体验 Spring Boot,选择添加 Web 依赖。
然后点击“GENERATE”按钮便可生成一个 Spring Boot 项目的压缩包,克制一下好奇心,待练完绣腿再体验 Spring Boot 到底有多神奇。
绣腿:在 InteIIiJ IDEA 里构建 Spring Boot 项目。
在 Intellij IDEA 界面中,单击【File】→【New】→【Project】,在弹出的窗口中选择【Spring Initializr】选项,如下图所示。
确认 Java Version,本次实验环境选择 Java 8,如下图所示。
选择【Spring Boot Version】,这里按默认版本即可(当前默认版本为 2.6.2),勾选【Web】→【Spring Web】选项,然后单击【Next】按钮,如下图所示。
点击 Next。
至此,一个完整的 Spring Boot 项目就创建完成了,但是,如何跑起来呢?
2.2. 运行 Spring Boot 项目
方式一:直接运行 main 函数,例如在 IDEA 里运行效果如下。
方式二:采用 mvnw spring-boot:run 命令执行
进入 Spring Boot 项目的根目录下,直接运行如下命令
./mvnw spring-boot:run
方式三:采用 java -jar 命令运行
此时先对项目进行 maven 编译,打包,然后进入 target 目录,执行如下命令:
# java -jar xxx.jar
java -jar demo-0.0.1-SNAPSHOT.jar
细心的同学会发现控制台日志输出时,会有 Tomcat 以及 8080 端口的身影,这是为什么呢?
这就展现了一点 Spring Boot 的独特魅力,内嵌了 Tomcat 服务器,运行一个 Java main 函数顺带启动了一个应用服务器,简直太神奇了(本次不深入探究,后面原理篇会细谈)。
至此,Spring Boot 项目就跑起来了。
遗憾的是连一行代码都还没有写,这也是 Spring Boot 的魅力所在,让 Java 程序员更专注于业务逻辑开发。
2.3. 添加业务逻辑
终于可以写几行代码了,终于可以实现点业务逻辑了。
自定义需求:提供一个 say 方法,可接受用户输入的参数 name,默认值为 World,然后输出 Hello name!
实现步骤如上图所示很简单:
提供一个 say 方法,可接受用户输入的参数 name,默认值为 World,然后输出 Hello name!(见上图中标注2)
添加注解 @RestController(见上图中标注1,注解后续会单独讲解)
2.4 跑起来,Try it
直接浏览器访问 http://localhost:8080/say ,此时参数 name 不传入值,直接展示默认值。
访问时传入参数值,http://localhost:8080/say?name=Amy,此时参数 name 传入 Amy,页面展示如下。
至此,SpringBoot 的大门已打开,万里长征稳稳地踏了一步,接下来再一起看看 Spring Boot 项目的目录结构。
2.5. Spring Boot 项目的目录结构
pom.xml:构建说明文件。
/src/main/java:Java 源代码文件。
/src/main/resources:所有的资源文件,包括静态资源文件、配置文件、页面文件等。
/src/main/resources/static:Web 应用程序的静态内容(js、css、images等)。
/src/main/resources/templates:存放呈现模型数据的模板。
/src/main/resources/application.properties:配置文件,可以根据需要添加配置属性。
/src/test/java:单元测试类 java 源代码。
/target:存放编译后的 .class 文件、配置文件以及项目打包后生成的 jar 文件等。
至此,却有很多疑问涌上心头。
若同一台服务器上,部署 N 套 Spring Boot 项目,默认开启都是 8080,端口岂不是被占用,何解?
另外 Spring Boot 还带来了什么好玩的事情呢?下面一起捣腾捣腾、尝试玩一玩 Spring Boot 项目。
2.6. 玩玩 Spring Boot 项目
控制台输出截图
上图是 Spring Boot 项目启动时的控制台日志输出,接下来主要对图中标注的部分进行倒腾替换一下。
2.6.1. 8080 端口被占用了咋办(控制台输出截图标注 1)?
同一台服务器上,部署 N 套 Spring Boot 项目,默认开启都是 8080,端口被占用,何解?
解决方案却很简单,只需在 /src/main/resources 目录的 application.properties 配置文件中自定义 server.port 就可以了,此时把服务启动的端口修改为 8888,配置如下。
server.port=8888
服务跑起来,服务端口成功修改为 8888,效果如下。
2.6.2. 内嵌的 Tomcat 容器是否可以置换一下(控制台输出截图标注 2)?
Spring Boot 除了可以选择 Tomcat 容器,还可以选择其它服务器,接下来尝试选择 Jetty 作为内嵌服务器。
实现方式很简单:
打开 pom.xml 文件,首先排除掉默认的 Tomcat 容器;
然后添加 Jetty 服务器依赖,就 Ok 了。
服务跑起来,Spring Boot 选择的内嵌容器由 Tomcat 成功修改为 Jetty 容器,效果如下。
2.6.3. 能否定义超级个性 banner (控制台输出截图标注 3)?
Spring Boot 支持以 txt、gif、jpg、png 为后缀,以 banner 命名的资源文件形式来自定义 banner,例如 banner.txt 或者 banner.jpg。
实现方式很简单,花拳绣腿而已。
首先打开如下任一网址录入文字,选择个性化的样式,把生成的内容保存到 banner.txt。
http://patorjk.com/software/taag/
https://www.bootschool.net/ascii
然后把 banner.txt 复制到项目中 src/main/resources 目录下。
服务跑起来,控制台的输出确实个性化了有没有?
感兴趣的可以考虑找个性化图片,去试试看效果如何。
3、例行回顾
本文是 Spring Boot 入门级的讲解,以 Spring 官方文档入门案例作为切入点,主要分享了如下部分:
准备 Spring Boot 项目依赖环境
创建 Spring Boot 项目的两种方式
运行 Spring Boot 项目的三种方法
尝试添加业务逻辑代码,实现了一个 say Hello 的 API
Spring Boot 项目的目录结构介绍
尝试修改默认 WEB 端口
尝试修改 Spring Boot 内嵌容器
尝试加入个性化的 Banner
如果是 Java 小白,相信通过这个入门级的项目,能够正式迈入 Spring Boot 的大门,相信程序中的很多注解会让你摸不着头脑,不过这些都可以先忽略,随着后续的逐步深入与练习,这些都会形成肌肉记忆,一切都不是问题。
如果是 Java 老兵,相信通过这个入门级的项目,能够轻松感受到 Spring Boot 着实去除了繁琐的 XML 配置,使项目更加简洁化、智能化,让 Java 程序员更专注业务逻辑开发,正如 Spring 的 slogan 所言:Spring makes Java simple. 真可谓是 Java 程序员的又一春。
揭秘本文封面图片,一只奔跑的袋鼠。希望在追逐技术的道路上,我们像袋鼠一样:大胆往前跳,永远不后退。
袋鼠是澳洲的象征物,出现在澳洲国徽中,以及一些澳洲货币图案上。许多澳洲的组织团体,如澳洲航空,也将袋鼠作为其标志。澳大利亚军队的车辆,舰船在海外执行任务时很多时候都会涂上袋鼠标志。 澳大利亚之所以让袋鼠作为国徽上动物之一,还有一个原因,就是它永远只会往前跳,永远不会后退。希望人们也有像袋鼠一样,永不退缩的精神。
玩转 Spring Boot 入门篇就写到这里,希望大家能够喜欢。一起聊技术、谈业务、喷架构,少走弯路,不踩大坑,会持续输出更多精彩分享,欢迎关注,敬请期待!
参考资料:
https://spring.io/
https://start.spring.io/
https://spring.io/projects/spring-boot
https://github.com/spring-projects/spring-boot
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/
https://stackoverflow.com/questions/tagged/spring-boot
《Spring Boot实战》《深入浅出Spring Boot 2.x》
《一步一步学Spring Boot:微服务项目实战(第二版)》
《Spring Boot揭秘:快速构建微服务体系》
玩转 Spring Boot 集成篇(任务动态管理代码篇)
* 定时任务管理**/
@ private TaskInfoService taskInfoService;
@ public Result list(@RequestBody TaskInfoReq reqVo)
@ public Result edit(@RequestBody TaskInfoReq reqVo)
@ public Result pause(Integer taskId)
@ public Result add(@RequestBody TaskInfoReq taskInfoReq)
@ public Result resume(Integer taskId)
@ public Result delete(@RequestBody TaskInfoReq reqVo)
com.example.demo.quartz.task;
com.example.demo.quartz.entity.TaskInfo;
com.example.demo.quartz.utils.SpringContextUtils;
com.example.demo.quartz.vo.TaskInfoReq;
org.quartz.*;
org.slf4j.Logger;
org.slf4j.LoggerFactory;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.stereotype.Component;
* 任务管理
* 1、添加任务 2、更新任务 3、暂停任务 4、恢复任务
**/
Logger LOGGER = LoggerFactory.getLogger(TaskManager.class);
String JOB_DEFAULT_GROUP_NAME = String TRIGGER_DEFAULT_GROUP_NAME = Scheduler scheduler;
SpringContextUtils springContextUtils;
* 添加任务
*/
flag = (!CronExpression.isValidExpression(taskInfoReq.getCron()))
LOGGER.error(
String className = springContextUtils.getBean(taskInfoReq.getJobName()).getClass().getName();
JobDetail jobDetail = JobBuilder.newJob().withIdentity(JobKey(taskInfoReq.getJobName(), JOB_DEFAULT_GROUP_NAME))
.ofType((Class<Job>) Class.forName(className))
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withSchedule(CronScheduleBuilder.cronSchedule(taskInfoReq.getCron()))
.withIdentity(TriggerKey(taskInfoReq.getJobName(), TRIGGER_DEFAULT_GROUP_NAME))
.build();
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
(Exception e)
LOGGER.error( flag =
flag;
* 更新任务
*/
flag =
JobKey jobKey = JobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME);
TriggerKey triggerKey = TriggerKey(taskInfo.getJobName(), TRIGGER_DEFAULT_GROUP_NAME);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
(scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey))
Trigger newTrigger = TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withSchedule(CronScheduleBuilder.cronSchedule(taskInfo.getCron()))
.withIdentity(triggerKey)
.build();
scheduler.rescheduleJob(triggerKey, newTrigger);
LOGGER.info(
LOGGER.info( (SchedulerException e)
LOGGER.error( flag =
flag;
* 暂停任务
*/
scheduler.pauseJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME));
LOGGER.info( (SchedulerException e)
LOGGER.error(
* 恢复任务
*/
scheduler.resumeJob(JobKey.jobKey(taskInfo.getJobName(), JOB_DEFAULT_GROUP_NAME));
LOGGER.info( (SchedulerException e)
LOGGER.error(
com.example.demo.quartz.common.EnumTaskEnable;
com.example.demo.quartz.entity.TaskInfo;
com.example.demo.quartz.service.TaskInfoService;
com.example.demo.quartz.vo.TaskInfoReq;
org.quartz.Scheduler;
org.quartz.SchedulerException;
org.slf4j.Logger;
org.slf4j.LoggerFactory;
org.springframework.beans.BeanUtils;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.stereotype.Component;
org.springframework.util.StringUtils;
javax.annotation.PostConstruct;
java.util.List;
logger = @ scheduler;
@ springJobFactory;
@ taskInfoService;
@ void start()
scheduler.setJobFactory(springJobFactory);
(taskInfo : tasks)
( data=new taskInfoService.addJob(data);
logger.info( (e)
logger.error(e.getMessage(), e);
new
com.example.demo.quartz.config;
org.quartz.spi.TriggerFiredBundle;
org.springframework.beans.factory.annotation.Autowired;
org.springframework.beans.factory.config.AutowireCapableBeanFactory;
org.springframework.scheduling.quartz.AdaptableJobFactory;
org.springframework.stereotype.Component;
* 解决spring bean注入Job的问题
*/
AutowireCapableBeanFactory capableBeanFactory;
Object Exception
Object jobInstance = capableBeanFactory.autowireBean(jobInstance);
jobInstance;
(
AUTO_INCREMENT datetime datetime PRIMARY (AUTO_INCREMENT=lombok.Data;
java.io.Serializable;
java.util.Date;
TaskInfo Serializable
Integer id;
cron;
jobName;
status;
createTime;
updateTime;
com.example.demo.quartz.common.Result;
com.example.demo.quartz.entity.TaskInfo;
com.example.demo.quartz.vo.TaskInfoReq;
java.util.List;
* 定时任务接口
**/
interface TaskInfoService
List<TaskInfo> selectTasks();
com.example.demo.quartz.service.impl;
com.example.demo.quartz.common.CodeMsg;
com.example.demo.quartz.common.EnumTaskEnable;
com.example.demo.quartz.common.ResponseFactory;
com.example.demo.quartz.common.Result;
com.example.demo.quartz.dao.TaskInfoDao;
com.example.demo.quartz.entity.TaskInfo;
com.example.demo.quartz.service.TaskInfoService;
com.example.demo.quartz.task.TaskManager;
com.example.demo.quartz.vo.TaskInfoReq;
com.github.pagehelper.PageHelper;
com.github.pagehelper.PageInfo;
org.quartz.CronExpression;
org.slf4j.Logger;
org.slf4j.LoggerFactory;
org.springframework.beans.BeanUtils;
org.springframework.stereotype.Service;
org.springframework.transaction.javax.java.util.Date;
java.util.List;
java.util.Objects;
* 定时任务业务实现
**/
static Logger LOGGER = LoggerFactory.getLogger(TaskInfoServiceImpl. TaskInfoDao taskInfoDao;
TaskManager taskManager;
Result selectTaskListByPage(TaskInfoReq taskInfoReq)
PageHelper.startPage(taskInfoReq.getPageCurrent(), taskInfoReq.getPageSize());
List<TaskInfo> list = taskInfoDao.selectTaskInfos(taskInfoReq);
PageInfo<TaskInfo> pageInfo = new PageInfo<>(list);
ResponseFactory.build(pageInfo);
Result updateJob(TaskInfoReq taskInfoReq)
(!CronExpression.isValidExpression(taskInfoReq.getCron()))
LOGGER.error( ResponseFactory.build(CodeMsg.TASK_CRON_ERROR);
TaskInfo isExistData = taskInfoDao.selectByJobName(taskInfoReq.getJobName());
((!Objects.isNull(isExistData)) && (!isExistData.getId().equals(taskInfoReq.getId())))
ResponseFactory.build(CodeMsg.TASK_CRON_DOUBLE);
TaskInfo = taskInfoDao.selectByPrimaryKey(taskInfoReq.getId());
(== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES);
BeanUtils.copyProperties(taskInfoReq, taskInfoDao.updateByPrimaryKeySelective( (!taskManager.updateJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
ResponseFactory.build();
Result pauseJob(Integer taskId)
TaskInfo = taskInfoDao.selectByPrimaryKey(taskId);
(== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES);
(!taskManager.pauseJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
taskInfoDao.updateByPrimaryKeySelective( ResponseFactory.build();
Result resumeJob(Integer taskId)
TaskInfo = taskInfoDao.selectByPrimaryKey(taskId);
(== ResponseFactory.build(CodeMsg.TASK_NOT_EXITES);
(!taskManager.resumeJob( ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
taskInfoDao.updateByPrimaryKeySelective( ResponseFactory.build();
Result addJob(TaskInfoReq taskInfoReq)
(!taskManager.addJob(taskInfoReq))
ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
TaskInfo = taskInfoDao.selectByJobName(taskInfoReq.getJobName());
(Objects.isNull( = new TaskInfo();
BeanUtils.copyProperties(taskInfoReq, taskInfoDao.insertSelective( ResponseFactory.build();
ResponseFactory.build(CodeMsg.TASK_CRON_DOUBLE);
Result delete(TaskInfoReq reqVo)
Result result = (CodeMsg.SUCCESS == result.getCode())
taskInfoDao.deleteByPrimaryKey(reqVo.getId());
ResponseFactory.build();
ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
(Exception e)
ResponseFactory.build(CodeMsg.TASK_EXCEPTION);
List<TaskInfo> selectTasks()
taskInfoDao.selectAll();
id, cron, job_name, status, create_time, update_time
select
from sc_task_info
where id = #id,jdbcType=INTEGER
delete from sc_task_info
where id = #id,jdbcType=INTEGER
SELECT LAST_INSERT_ID()
insert into sc_task_info (cron, job_name, status,
create_time, update_time)
values (#cron,jdbcType=VARCHAR, #jobName,jdbcType=VARCHAR, #status,jdbcType=CHAR,
#createTime,jdbcType=TIMESTAMP, #updateTime,jdbcType=TIMESTAMP)
SELECT LAST_INSERT_ID()
insert into sc_task_info
cron,
job_name,
status,
create_time,
update_time,
#cron,jdbcType=VARCHAR,
#jobName,jdbcType=VARCHAR,
#status,jdbcType=CHAR,
#createTime,jdbcType=TIMESTAMP,
#updateTime,jdbcType=TIMESTAMP,
update sc_task_info
cron = #cron,jdbcType=VARCHAR,
job_name = #jobName,jdbcType=VARCHAR,
status = #status,jdbcType=CHAR,
create_time = #createTime,jdbcType=TIMESTAMP,
update_time = #updateTime,jdbcType=TIMESTAMP,
where id = #id,jdbcType=INTEGER
update sc_task_info
set cron = #cron,jdbcType=VARCHAR,
job_name = #jobName,jdbcType=VARCHAR,
status = #status,jdbcType=CHAR,
create_time = #createTime,jdbcType=TIMESTAMP,
update_time = #updateTime,jdbcType=TIMESTAMP
where id = #id,jdbcType=INTEGER
select * from sc_task_info where job_name=#jobName
select * from sc_task_info
select * from sc_task_info
lombok.Data;
* 任务请求类
**/
TaskInfoReq
Integer id;
cron;
status;
jobName;
int pageSize= int pageCurrent=com.example.demo.quartz.common;
lombok.Data;
code;
String msg;
Object retData;
* 响应工具类
*/
Result code, String errmsg)
Result result = Result();
result.setCode(code);
(errmsg == || errmsg.trim().length() == result.setMsg(CodeMsg.getMsg(code));
result.setMsg(errmsg);
result;
Result code)
commonBuild(code, CodeMsg.getMsg(code));
Result
commonBuild(CodeMsg.SUCCESS,
Result
Result json = commonBuild(CodeMsg.SUCCESS, json.setRetData(data);
json;
EnumTaskEnable
START( STOP( code;
msg;
EnumTaskEnable(code, msg)
getCode()
code;
com.example.demo.quartz.common;
java.util.HashMap;
java.util.Map;
* 公共返回码
*/
Map<Integer, String> MSG = HashMap<Integer, String>();
SUCCESS = ERROR = TASK_NOT_EXITES = TASK_EXCEPTION = TASK_CRON_ERROR = TASK_CRON_DOUBLE =
MSG.put(SUCCESS, MSG.put(ERROR, MSG.put(TASK_NOT_EXITES, MSG.put(TASK_EXCEPTION, MSG.put(TASK_CRON_ERROR, MSG.put(TASK_CRON_DOUBLE,
String errcode)
MSG.get(errcode);
com.example.demo.quartz.utils;
org.springframework.beans.BeansException;
org.springframework.context.ApplicationContext;
org.springframework.context.ApplicationContextAware;
org.springframework.context.annotation.Lazy;
org.springframework.stereotype.Component;
ApplicationContext applicationContext;
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
*
* applicationContext
*/
SpringContextUtils.applicationContext = applicationContext;
* ApplicationContext
*/
ApplicationContext
applicationContext;
* 获取对象
* 这里重写了bean方法,起主要作用
*
* name
* Object 一个以所给名字注册的bean的实例
* BeansException
*/
<T>
(T) applicationContext.getBean(name);
(Exception e)
<T>
applicationContext.getBean(clazz);
(Exception e)
MySQL 链接信息
Mapper资源文件存放的路径
Dao 接口文件存放的目录
开启 debug,输出 SQL
com.example.demo.quartz.task;
org.apache.commons.logging.Log;
org.apache.commons.logging.LogFactory;
org.quartz.JobExecutionContext;
org.quartz.JobExecutionException;
org.springframework.scheduling.quartz.QuartzJobBean;
org.springframework.stereotype.Component;
* 定义一个调度器要执行的任务
*/
Log logger = LogFactory.getLog(DongAoJob.class);
JobExecutionException
logger.info(
com.example.demo.quartz;
org.springframework.boot.SpringApplication;
org.springframework.boot.autoconfigure.SpringBootApplication;
SpringApplication.run(DemoJobApplication.class, args);
6. 运行验证
其实挂个简单页面就能轻松完成页面化配置任务,本次用 Postman 方式直接调用任务管理的 API。
6.1 添加任务
此时库任务 Id 为7:
控制台:
6.2 查询任务
6.3 编辑任务
控制台输出:
6.4 暂停任务
http://localhost:15158/task/pause?taskId=7
6.5 恢复任务
http://localhost:15158/task/resume?taskId=7
7. 例行回顾
本文是 Spring Boot 项目集成 Quartz 来实现任务的动态管理,主要是代码,感兴趣的可以自行拿去验证改造并用于实践。
玩转 Spring Boot 集成定时任务篇就写到这里,希望大家能够喜欢。
一起聊技术、谈业务、喷架构,少走弯路,不踩大坑,会持续输出更多精彩分享,欢迎关注,敬请期待!
历史系列文章:
玩转 Spring Boot 入门篇
玩转 Spring Boot 集成篇(MySQL、Druid、HikariCP)
玩转 Spring Boot 集成篇(MyBatis、JPA、事务支持)
玩转 Spring Boot 集成篇(Redis)
玩转 Spring Boot 集成篇(Actuator、Spring Boot Admin)
玩转 Spring Boot 集成篇(RabbitMQ)
玩转 Spring Boot 集成篇(@Scheduled、静态、动态定时任务)
以上是关于玩转 Spring Boot 入门篇的主要内容,如果未能解决你的问题,请参考以下文章
玩转 Spring Boot 集成篇(@Scheduled静态动态定时任务)