如何从零开始写一个xxx-spring-boot-stop
WU双
共 18100字,需浏览 37分钟
· 2023-10-14
1
If you are just getting started with Spring, you may want to begin using the Spring Framework by creating a Spring Boot-based application. Spring Boot provides a quick (and opinionated) way to create a production-ready Spring-based application.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
<!-- more bean definitions go here -->
</beans>
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
2
1. The autoconfigure module that contains the auto-configuration code for "acme". 2. The starter module that provides a dependency to the autoconfigure module as well as "acme" and any additional dependencies that are typically useful.
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.4.2</version>
<name>spring-boot-starter-data-redis</name>
<description>Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client</description>
<url>https://spring.io/projects/spring-boot</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>https://spring.io</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
<developers>
<developer>
<name>Pivotal</name>
<email>info@pivotal.io</email>
<organization>Pivotal Software, Inc.</organization>
<organizationUrl>https://www.spring.io</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-projects/spring-boot.git</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-projects/spring-boot.git</developerConnection>
<url>https://github.com/spring-projects/spring-boot</url>
</scm>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/spring-projects/spring-boot/issues</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
// 这里表示只有项目依赖中有RedisOperations这个类,下面的配置才会生效,正是因为我们引入了spring-boot-starter-data-redis依赖,然后项目中才会有RedisOperations类,所以该自动配置才会生效
// RedisProperties为redis相关的配置,包括集群地址、连接池配置等信息都可以通过这个类来进行配置
// 这里是导入了其他的配置类,为Redis连接池相关的配置
public class RedisAutoConfiguration {
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
public class CacheService {
// 因为Spring Boot已经自动注入了StringRedisTemplate,所以这里我们代码里直接使用即可
private StringRedisTemplate redisTemplate;
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, JSON.toJSONString(value));
}
public void set(String key, Object value, long expireTimeout, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, JSON.toJSONString(value), expireTimeout, timeUnit);
}
public <T> T get(String key, Class<T> clazz) {
return JSON.parseObject(redisTemplate.opsForValue().get(key), clazz);
}
public void delete(String key) {
redisTemplate.delete(key);
}
}
3
写一个自己的
@ConfigurationProperties(prefix = "scheduler")
public class SchedulerProperties {
/**
* 定时任务调度时间,单位ms,默认值1000ms
*/
private long period = 1000L;
/**
* 定时任务名称
*/
private String taskName;
public long getPeriod() {
return period;
}
public void setPeriod(long period) {
this.period = period;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
}
public class SchedulerAutoConfiguration {
public Scheduler schedulerTask(ScheduledThreadPoolExecutor scheduledThreadPoolExecutor, SchedulerProperties schedulerProperties) {
return new Scheduler(scheduledThreadPoolExecutor, schedulerProperties);
}
}
public class SchedulerExecutorConfiguration {
public ScheduledThreadPoolExecutor scheduledThreadPoolExecutor() {
return new ScheduledThreadPoolExecutor(1);
}
}
public class Scheduler {
public static final Logger LOGGER = LoggerFactory.getLogger(Scheduler.class);
private final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private final SchedulerProperties schedulerProperties;
public Scheduler(ScheduledThreadPoolExecutor scheduledThreadPoolExecutor, SchedulerProperties schedulerProperties) {
this.scheduledThreadPoolExecutor = scheduledThreadPoolExecutor;
this.schedulerProperties = schedulerProperties;
this.init();
}
public void init() {
scheduledThreadPoolExecutor.scheduleAtFixedRate(() -> {
LOGGER.info("scheduler task [{}], period [{}ms], currentTime [{}]", schedulerProperties.getTaskName(), schedulerProperties.getPeriod(), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}, 0, schedulerProperties.getPeriod(), TimeUnit.MILLISECONDS);
}
}
\ =
com.example.scheduler.SchedulerAutoConfiguration
<dependency>
<groupId>com.example</groupId>
<artifactId>scheduler-spring-boot-starter</artifactId>
<version>${scheduler-spring-boot-starter-version}</version>
</dependency>
2023-10-11 14:22:20.683 INFO 25680 --- [pool-1-thread-1] com.example.scheduler.Scheduler : scheduler task [test-example], period [5000ms], currentTime [2023-10-11 14:22:20]
2023-10-11 14:22:25.689 INFO 25680 --- [pool-1-thread-1] com.example.scheduler.Scheduler : scheduler task [test-example], period [5000ms], currentTime [2023-10-11 14:22:25]
2023-10-11 14:22:30.685 INFO 25680 --- [pool-1-thread-1] com.example.scheduler.Scheduler : scheduler task [test-example], period [5000ms], currentTime [2023-10-11 14:22:30]
2023-10-11 14:22:35.681 INFO 25680 --- [pool-1-thread-1] com.example.scheduler.Scheduler : scheduler task [test-example], period [5000ms], currentTime [2023-10-11 14:22:35]
{
"groups": [
{
"name": "scheduler",
"type": "com.example.scheduler.SchedulerProperties",
"sourceType": "com.example.scheduler.SchedulerProperties"
}
],
"properties": [
{
"name": "scheduler.period",
"type": "java.lang.Long",
"description": "定时任务调度时间,单位ms",
"sourceType": "com.example.scheduler.SchedulerProperties"
},
{
"name": "scheduler.task-name",
"type": "java.lang.String",
"description": "定时任务名称",
"sourceType": "com.example.scheduler.SchedulerProperties"
}
],
"hints": []
}
4
测试你的spring-boot-starter
class SchedulerAutoConfigurationTest {
// 通过contextRunner来模拟运行环境,这里是模拟配置了SchedulerAutoConfiguration类的应用环境,实际也就是引用了scheduler-spring-boot-starter后生效的配置
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(SchedulerAutoConfiguration.class));
void testAutoConfiguration() {
this.contextRunner.run((context) -> {
// 测试自动配置有没有注入ScheduledThreadPoolExecutor Bean
assertThat(context).hasSingleBean(ScheduledThreadPoolExecutor.class);
// 测试自动配置有没有注入SchedulerProperties Bean
assertThat(context).hasSingleBean(SchedulerProperties.class);
// 测试自动配置有没有注入Scheduler Bean
assertThat(context).hasSingleBean(Scheduler.class);
});
}
void testProperties() {
// 模拟环境配置了相应的参数
this.contextRunner.withPropertyValues("scheduler.period=5000", "scheduler.task-name=test-example")
.run((context) -> {
// 测试对应参数设置是否生效
assertThat(context.getBean(SchedulerProperties.class).getPeriod()).isEqualTo(5000);
assertThat(context.getBean(SchedulerProperties.class).getTaskName()).isEqualTo("test-example");
});
}
}
聊技术,不止于技术。
评论
如何计算数据中心的冷却需求?
今日分享 【导读】数据中心的冷却要求受多种因素影响,包括设备的热量输出、占地面积、设施设计和电气系统功率额定值等等……众所周知,环境因素会严重影响数据中心设备。过多的热量积聚会损坏服务器,可能导致其自动关闭。经常在高于可接受的温度下运行服务器会缩短其使用
数据中心运维管理
0
有意思!一个关于 Spring 历史的在线小游戏
发现 Spring One 的官网上有个好玩的彩蛋,分享给大家!进到Spring One的官网,可以看到右下角有个类似马里奥游戏中的金币图标。点击该金币之后,会打开一个新的页面,进入下面这样一个名为:The History Of Spring 的在线小游戏你可以使用上下左右的方向键来控制Spring
公众号程序猿DD
1
【Python】coverage,一个有趣的 Python 库!
大家好,今天为大家分享一个有趣的 Python 库 - coveragepy。Github地址:https://github.com/nedbat/coveragepy在软件开发中,测试是确保代码质量和稳定性的关键步骤之一。而代码覆盖率则是衡量测试覆盖代码的程度的重要指标之一。Python cove
机器学习初学者
0
【性能监控】如何有效监测网页静态资源大小?
前言作为前端人员肯定经常遇到这样的场景:需求刚上线,产品拿着手机来找你,为什么页面打开这么慢呀,心想自己开发的时候也有注意性能问题呀,不可能会这么夸张。那没办法只能排查下是哪一块影响了页面的整体性能,打开浏览器控制台一看,页面上的这些配图每张都非常大,心想这些配图都这么大,页面怎么快,那么我们有没有
高级前端进阶
0
机房水冷空调管路应该如何安装布局?
近年来随着云计算技术的快速发展,全球数据中心开始向着巨型化的方向发展,单机柜功率密度不断提高,5KW、7KW、10KW甚至几十KW功率机柜已逐步成为常规配置。新一代数据中心更显著的表现为:规模更大、密度更高、制冷要求更高、局部过热成为常态等特点。本文就来探讨下水
数据中心运维管理
0
如何看待研究生报考「放导师鸽子」、「录而不读」的行为?
近日,某双一流高校教授在博客晒出被学生「放鸽子」的经历。该教授称「学生在联系的时候各种甜言蜜语,山盟海誓,就差签卖身契了,一旦手握几个 offer 立马变了个人,完全不考虑给招生单位和老师带来的麻烦」,并放出两个例子在他看来,这些学生「功利、浮躁、没有诚信」。他甚至在微信设置了一个失信名单。类似「录
机器学习初学者
0
面试官:电商库存扣减如何设计?如何防止超卖?
来源:my.oschina.net/xiaolyuh/blog/1615639👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示
小哈学Java
0
盘点一个使用超级鹰识别验证码并自动登录的案例
点击上方“Python共享之家”,进行关注回复“资源”即可获赠Python学习资料今日鸡汤江上几人在,天涯孤棹还。大家好,我是皮皮。一、前言前几天在Python钻石交流群【静惜】问了一个Python实现识别验证码并自动登录的问题,提问截图如下:验证码的截图如下所示:二、实现过程这里大家激烈的探讨,【
IT共享之家
0