今天的越写悦快乐系列文章为大家带来工作上的那些事儿,大家都知道在Spring Boot 项目中,我们经常需要定时地执行一些重复性的任务,比如统计用户访问日志,数据库的定时备份,那么这些业务都需要定时任务来为我们提供API,接下来我为大家分享一下如何在Spring Boot项目中接入定时任务。
开发环境
- Window 10.0.17763
- Java 8.0.191
- IntelliJI IDEA 2018.3
Maven 版本
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
Build 版本
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
</plugin>
构建步骤
添加依赖
对于Spring Boot的项目我们只需要在POM文件的parent
标签中加入以下内容即可。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/>
</parent>
配置Task
我们在application.properties
文件中加入以下内容:
spring.task.execution.pool.max-size=16
spring.task.execution.pool.core-size=16
spring.task.execution.pool.keep-alive=10s
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.allow-core-thread-timeout=true
spring.task.execution.thread-name-prefix=async-tour-
启用注解
我们在AsyncTourApplication
中加入@EnableAsync
注解,告知Spring框架开启任务。
package me.weitao.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* @author Watony Weng
* @date 2019/12/03
*/
@EnableAsync
@SpringBootApplication
public class AsyncTourApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncTourApplication.class, args);
}
}
编写任务类
为了方便测试,我们模拟线程执行并在执行过程中等待数秒,可以使用@Async
应用到某个方法上,表明该方法支持异步,文件内容请参考:
package me.weitao.app.components;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* @author Zhuye
* @date 2019/12/05
*/
@Component
@Slf4j
public class SimulationTask {
/**
* 模拟5秒的异步任务
*/
@Async
public Future<Boolean> asyncTask1() throws InterruptedException {
doTask("asyncTask1", 5);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟2秒的异步任务
*/
@Async
public Future<Boolean> asyncTask2() throws InterruptedException {
doTask("asyncTask2", 2);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟3秒的异步任务
*/
@Async
public Future<Boolean> asyncTask3() throws InterruptedException {
doTask("asyncTask3", 3);
return new AsyncResult<>(Boolean.TRUE);
}
/**
* 模拟5秒的同步任务
*/
public void task1() throws InterruptedException {
doTask("task1", 5);
}
/**
* 模拟2秒的同步任务
*/
public void task2() throws InterruptedException {
doTask("task2", 2);
}
/**
* 模拟3秒的同步任务
*/
public void task3() throws InterruptedException {
doTask("task3", 3);
}
private void doTask(String taskName, Integer time) throws InterruptedException {
log.info("{}开始执行,当前线程名称【{}】", taskName, Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(time);
log.info("{}执行成功,当前线程名称【{}】", taskName, Thread.currentThread().getName());
}
}
编写测试类
我们在test/java
下创建SimulationTaskTest
类,在该类中注入SimulationTask
,参考的文件的文件内容如下:
package me.weitao.app.task;
import lombok.extern.slf4j.Slf4j;
import me.weitao.app.AsyncTourApplicationTests;
import me.weitao.app.components.SimulationTask;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* @author Zhuye
* @date 2019/12/03
*/
@Slf4j
public class SimulationTaskTest extends AsyncTourApplicationTests {
@Autowired
private SimulationTask task;
/**
* 测试异步任务
*/
@Test
public void asyncTaskTest() throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
Future<Boolean> asyncTask1 = task.asyncTask1();
Future<Boolean> asyncTask2 = task.asyncTask2();
Future<Boolean> asyncTask3 = task.asyncTask3();
asyncTask1.get();
asyncTask2.get();
asyncTask3.get();
long end = System.currentTimeMillis();
log.info("异步任务全部执行结束,总耗时:{} 毫秒", (end - start));
}
/**
* 测试同步任务
*/
@Test
public void taskTest() throws InterruptedException {
long start = System.currentTimeMillis();
task.task1();
task.task2();
task.task3();
long end = System.currentTimeMillis();
log.info("同步任务全部执行结束,总耗时:{} 毫秒", (end - start));
}
}
运行测试查看结果
测试类编写完成后,我们可以定位到该测试类,点击方法前面的三角即可执行该测试方法,下面的截图就是异步方法的执行结果。
运行结果 - 图片来自简书App个人感想及收获
通过以上知识点的梳理,我们了解了如何利用注解快速执行定时任务,提升我们的业务服务能力,构建合适的产品矩阵,通过注解结合Spring框架强大的依赖注入特性可以构建高并发的Web应用,我们不仅要知道底层的技术细节,更要从整体出发、梳理系统架构、完善技术盲点、扩展技术边界、让技术能更好地服务于业务,要让业务能强化技术的潜能,我相信这不是一朝一夕的事情,需要我们去梳理、完善、成就和总结技术要点,让我们一起为公司创造更大的价值。若是我的文章对你有所启发,那将是我莫大的荣幸。
网友评论