0 写在前面
SpringBoot 中有一个非常重要的机制——starter,它是遵循“约定大于配置”理念的一个重要表现。能够将功能集成进 starter 中,无需繁杂的配置(可以认为特指一大堆 xml 文件)即可在 maven 项目中引入并使用。日常开发中,经常会遇到一些独立于业务之外的通用模块(例如日志处理、redis 工具等),秉承着不重复造轮子的理念,我们可以考虑将类似的模块封装成一个 starter,按需引入,利用 SpringBoot 的自动装配将 Bean 注册进 IOC 容器中。
1 前置知识
封装一个 starter 并不适合零基础的小白。在了解如何封装一个 starter 之前,至少需要了解的前置知识如下:
- SpringBoot 的基础使用(如创建项目、编写配置文件以及配置类等)
- 如果能了解SpringBoot 的自动装配原理更好,不了解也没关系,不影响本 demo 的学习
- 了解Redis 的基础使用(其实这个也不强求,只是因为本 demo 选择做的是一个 redis 的工具类一样的 starter,所以最好还是有一点基础)
- maven 的基础知识,至少要了解本地仓库跟远程仓库这些概念。
- 了解自定义注解
- 已安装 redis
2 开始编写 starter
-
创建一个maven 项目
-
引入 springboot 父依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> <relativePath/> </parent> -
引入 redis 相关依赖
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <spring.boot.version>2.5.3</spring.boot.version> </properties> <dependencies> <!-- 添加 redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>${spring.boot.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>${spring.boot.version}</version> </dependency> </dependencies> -
创建基础包结构
-
在 config 包下创建 RedisTemplateConfig 类
package com.study.redis.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @author markcwg * @date 2021/8/10 3:48 下午 */ @Configuration public class RedisTemplateConfig { @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); //定义key序列化方式 redisTemplate.setKeySerializer(new StringRedisSerializer()); //定义value序列化方式 redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } -
在 helper 包下创建 RedisHelper 类
package com.study.redis.helper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.Set; /** * @author markcwg * @date 2021/8/10 3:53 下午 */ @Component public class RedisHelper { @Autowired private RedisTemplate<String, String> redisTemplate; /** * 是否存在key * * @param key 键 * @return 是否存在 */ public Boolean hasKey(String key) { return redisTemplate.hasKey(key); } /** * 查找匹配的key * * @param pattern 匹配表达式 * @return 所有匹配的数据 */ public Set<String> keys(String pattern) { return redisTemplate.keys(pattern); } /** * 设置指定 key 的值 * @param key 键 * @param value 值 */ public void set(String key, String value) { redisTemplate.opsForValue().set(key, value); } /** * 获取指定 key 的值 * @param key 键 * @return 值 */ public String get(String key) { return redisTemplate.opsForValue().get(key); } } -
在 config 包下创建 CustomRedisAutoConfiguration
package com.study.redis.config; import com.study.redis.helper.RedisHelper; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @author markcwg * @date 2021/7/30 4:10 下午 */ @ConditionalOnWebApplication @Configuration(proxyBeanMethods = false) @ComponentScan(basePackages = "com.study.redis.config") public class CustomRedisAutoConfiguration { @Bean public RedisHelper redisHelper() { return new RedisHelper(); } } -
在 annotations 包下创建 LoadRedis 注解
package com.study.redis.annotations; import com.study.redis.config.CustomRedisAutoConfiguration; import org.springframework.context.annotation.Import; import java.lang.annotation.*; /** * @author markcwg * @date 2021/8/10 4:00 下午 */ @Target(ElementType.TYPE) @Documented @Retention(RetentionPolicy.RUNTIME) @Import(CustomRedisAutoConfiguration.class) public @interface LoadRedis { } -
使用 mvn install 将 starter 放入自己的 maven 仓库
-
判断 maven 本地仓库是否已存在成品(此步可忽略)
3 原理解释
此处简单解释一下此 starter 的原理:通过 LoadRedis 注解引入 CustomRedisAutoConfiguration 自动配置类,在这个类中将 RedisHelper 注册进 IOC 容器,而 RedisHelper 里封装了常用的 redis 方法,可自行扩展
4 使用自定义的 starter
-
创建一个新的springboot 项目
-
引入自定义的 starter
<dependency> <groupId>com.study</groupId> <artifactId>starter-demo</artifactId> <version>0.1</version> </dependency> -
编写配置文件(此步要求已安装 redis)
server: port: 8082 spring: redis: host: 127.0.0.1 port: 6379 -
在启动类上加上 LoadRedis 注解
@SpringBootApplication @LoadRedis public class StarterTestDemoApplication { public static void main(String[] args) { SpringApplication.run(StarterTestDemoApplication.class, args); } } -
创建一个 RedisController 类用作测试
由于只用作测试,此处直接在 Controller 里直接写业务逻辑
package com.example.startertestdemo.com.study; import com.study.redis.helper.RedisHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author markcwg * @date 2021/8/10 4:19 下午 */ @RestController @RequestMapping("redis") public class RedisController { private RedisHelper redisHelper; @Autowired public RedisController(RedisHelper redisHelper) { this.redisHelper = redisHelper; } @PostMapping public String save(String key, String value) { redisHelper.set(key, value); return "success"; } @GetMapping public String get(String key) { return redisHelper.get(key); } } -
使用 postman 测试向 redis 中发送数据
-
使用 postman 测试从 redis 中获取数据
5 完结,撒花!
保持学习,保持热爱!