4.1.7.手写实现一个spring boot starter实现
时长:40min
4.1.springboot starter组件
4.1.1.springboot starter组件的实现原理
如果创建一个springboot项目,会在pom.xml自动添加一个starter组件。
4.1.1.1.stater组件的类型
starter包有官方定义包,和第三方定义包。
1.官方starter
命名格式:spring-boot-starter-xxx,如:spring-boot-starter-web
自动装配,是基于条件装配。
2.第三方starter
命名格式:xxx-spring-boot-starter,如:mybatis-spring-boot-starter
自动装配,是基于spring.factories配置文件装配
4.1.1.2.starter组件做了哪些事情?
starter组件,实际是定义一个模块。它所做的工作包括:
》整合相关依赖包
》完成自动装配
4.1.2.基于redis手写一个starter
4.1.2.1.开发准备
查看本机本地环境是否有安装redis服务端。个人通过virtualbox + vagrant安装centos7系统。
希望在centos上安装redis服务器程序。【这里是在windows系统下】
1.启动虚拟机
首先,运行virtualbox软件,刚开始虚拟机是关闭状态。
然后到centos安装目录,打开cmd,启动vagrant,使用命令:
D:softcentos7>vagrant up
启动完成后,虚拟机变成运行状态,如下所示:
然后,进入虚拟机,使用命令:
D:softcentos7>vagrant ssh
Last login: Mon Jan 6 08:43:36 2020 from 10.0.2.2
[vagrant@localhost ~]$ //这里是vagrant普通用户登录
查看ip,使用命令:ip a【这里可以当作是127.0.0.1】
然后,使用xshell工具连接服务端。
然后,查看是否有安装redis服务器,如果没有,先进行安装。
然后,启动redis,如下所示:
4.1.2.2.开发一个starter
1.创建一个maven工程,开发一个redission的starter组件
因为是自定义的第三方starter包,项目命名为:redission-spring-boot-starter
【1】pom.xml中引入相关依赖包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> //需要springboot的相关注解 <version>2.3.1.RELEASE</version> <optional>true</optional> </dependency> <dependency> <groupId>org.redisson</groupId> //作为redis客户端组件 <artifactId>redisson</artifactId> <version>3.13.1</version> </dependency>
【2】创建redisson配置类
主要实现RedissonClient这个bean实现条件装配。
这个client类是用来连接redis服务器的。代码如下:
package com.wf.redission; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.redisson.config.SingleServerConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName RedissonAutoConfiguration * @Description 配置类 * @Author wf * @Date 2020/7/8 13:44 * @Version 1.0 */ @Configuration @ConditionalOnClass(Redisson.class) @EnableConfigurationProperties(RedissonProperties.class) public class RedissonAutoConfiguration { //这里传参RedissonProperties实例,是要求这个bean自动装配到spring中的。如果未注入,是会报错的。 //这里通过@EnableConfigurationProperties(RedissonProperties.class)配置类自动装配 @Bean public RedissonClient redissonClient(RedissonProperties redissonProperties){ Config config = new Config(); String prefix = "redis://"; //是否加密判断 if(redissonProperties.isSsl()){ prefix = "rediss://"; } String address = prefix + redissonProperties.getHost()+":" + redissonProperties.getPort(); SingleServerConfig singleServerConfig = config.useSingleServer().setAddress(address) .setConnectTimeout(redissonProperties.getTimeout()); return Redisson.create(config); } }
在这种远程连接的工具类,经常涉及到一个连接参数配置。可以在springboot的外部配置文件中
进行自行配置,这是如何实现的呢?
实际上,是依赖注入一个外部文件配置类。
【3】外部文件配置类创建
package com.wf.redission; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @ClassName RedissonProperties * @Description 配置文件类 * @Author wf * @Date 2020/7/8 13:57 * @Version 1.0 */ @ConfigurationProperties(prefix = "wf.redisson") public class RedissonProperties { private String host = "localhost"; private int port = 6379; private int timeout;//超时时间 private boolean ssl;//是否加密传输 public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public boolean isSsl() { return ssl; } public void setSsl(boolean ssl) { this.ssl = ssl; } }
说明:
这里其实是@ConfigurationProperties(prefix = "wf.redisson")注解起重要作用。
【4】创建配置文件实现自动装配
创建resources资源文件夹,然后创建META-INF文件夹,并在该目录下创建spring.factories配置文件,
如下所示:
配置内容如下所示:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.wf.redission.RedissonAutoConfiguration
然后,这个组件就开发完成了。下面进行打包发布。
2.创建springboot项目,引入该starter,进行使用
【1】pom.xml中引入starter依赖
<!--引入 自定义redission starter组件--> <dependency> <groupId>com.wf.redission</groupId> <artifactId>redission-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
【2】创建redisTestController
package com.wf.demo.springbootdemo.web; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName RedisTestController * @Description redis使用 * @Author wf * @Date 2020/7/8 14:34 * @Version 1.0 */ @RestController public class RedisTestController { @Autowired private RedissonClient redissonClient; @GetMapping("set") public String set(){ RBucket<Object> bucket = redissonClient.getBucket("name"); if(bucket.get() == null){ bucket.set("wf.com"); } return bucket.get().toString(); } }
【3】配置连接参数
具体配置内容如下所示:
wf.redisson.host=127.0.0.1 wf.redisson.port=6379 wf.redissson.timeout=3000
【4】启动springboot项目,进行测试
启动失败,因为redis连接失败。如下所示:
连接失败的原因,可能是ip配置不对。
目前配置ip为127.0.0.1,需要查看虚拟机中ip地址是多少。
然后,配置成静态ip:192.168.33.10,再次启动失败。猜想是redis远程连接未设置好。
结果,果然是这样。所以,启动成功。访问接口如下:
说明:
redis远程连接,测试通过。说明starter定义成功。
3.开发问题总结
虽然我们的starter开发成功了,功能没有问题。但是,我在springboot进行配置连接参数时,
key是没有提示的。
如何能够实现这种提示功能呢?还是需要修改starter组件。
【1】开发外部配置key提示功能
A.starter组件中引入依赖包
<!--外部配置提示功能--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>2.3.1.RELEASE</version> </dependency>
B.META-INF下添加配置文件additional-spring-configuration-metadata.json
这个文件会配置属性解析,属性值。从而可以增加一些自动化的描述。
文件内容如何配置,可以参考springboot中的配置文件,如下所示:
{ "properties": [ { "sourceType": "org.apache.ibatis.session.Configuration", "defaultValue": "org.apache.ibatis.scripting.xmltags.XMLLanguageDriver", "name": "mybatis.configuration.default-scripting-language", "description": "A default LanguageDriver class.", "type": "java.lang.Class<? extends org.apache.ibatis.scripting.LanguageDriver>", "deprecation": { "reason": "Because when this configuration property is used, there is case that custom language driver cannot be registered correctly.", "replacement": "mybatis.default-scripting-language-driver" } }, { "sourceType": "org.apache.ibatis.session.Configuration", "defaultValue": "org.apache.ibatis.type.EnumTypeHandler", "name": "mybatis.configuration.default-enum-type-handler", "description": "A default TypeHandler class for Enum.", "type": "java.lang.Class<? extends org.apache.ibatis.type.TypeHandler>" }, { "defaultValue": false, "name": "mybatis.lazy-initialization", "description": "Set whether enable lazy initialization for mapper bean.", "type": "java.lang.Boolean" }, { "name": "mybatis.scripting-language-driver.velocity.userdirective", "deprecation": { "level": "error", "reason": "The 'userdirective' is deprecated since Velocity 2.x. This property defined for keeping backward compatibility with older velocity version.", "replacement": "mybatis.scripting-language-driver.velocity.velocity-settings.runtime.custom_directives" } } ] }
当前组件的配置内容如下:
{ "properties": [ { "name": "wf.redisson.host", "type": "java.lang.String", "description": "redis的服务器地址", "defaultValue": "localhost" }, { "name": "wf.redisson.port", "type": "java.lang.Integer", "description": "redis服务开放端口号", "defaultValue": 6379 }, { "name": "wf.redisson.timeout", "type": "java.lang.Integer", "description": "redis的服务器连接超时时间", "defaultValue": 3000 }, { "name": "wf.redisson.ssl", "type": "java.lang.Boolean", "description": "redis数据传输是否加密", "defaultValue": false } ] }
开发就完成了,重新打包发布。
【2】回到springboot项目中测试
发现已经重新打包,还是不能提示。后面我找到原因。
配置的这个路径:wf.redisson必须与包路径定义一样,原来我的包路径定义为com.wf.redission
所以,不能解析成功。
现在我修改一致之后,重新打包starter项目,在jar包中会自动生成一个spring-configuration-metadata.json
文件,这个文件才是导致key配置提示的关键。生成文件如下所示:
下面回到springboot项目中,进行配置,验证是否会key提示。 可以发现,提示功能成功了。
4.2.Actuator监控
下节再述。