自定义spring boot starter 初尝试
自定义简单spring boot starter 步骤
从几篇博客中了解了如何自定义starter,大概分为以下几个步骤:
1 引入相关依赖;
2 生成属性配置类;
3 生成核心服务类;
4 生成自动化配置类;
5 注册配置/META-INF/spring.factories;
6 打包发布;
下面以一个简单的demo为例,一步一步说明自定义spring boot的starter的过程。
解决问题
使用Slf4j的MDC实现一个工程中的链路追踪。通过设置open的属性代表是否打开链路追踪,从而为每一个请求生成一个traceId。当然理想是比较丰满的,实际操作如果要实现上述功能,要配合AOP/Filter/Interceptor这类工具,具体参考 文章。本文只是做个demo。
引入相关依赖
Demo比较简单,所以需要的依赖也不多,如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
生成属性配置类
属性类一定要加@ConfigurationProperties注解,用于表示这个文件是一个属性类。
在注解@ConfigurationProperties后面可以添加prefix前缀,如果open属性要设置具体值,需要这样配置,lxl.mdc.open = true;
package com.demo.spring.starter.mdc; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 自定义starter的properties类 * * @author lxl * @since 2018/12/10 */ @ConfigurationProperties(prefix = "lxl.mdc") public class MdcDemoProperties { private Boolean open = true; public Boolean getOpen() { return open; } public void setOpen(Boolean open) { this.open = open; } }
生成核心服务类
核心服务类的作用:根据properties中lxl.mdc.open的配置,控制是否生成sessionId,并将其put到MDC中。
package com.demo.spring.starter.mdc; import java.util.UUID; import org.slf4j.MDC; /** * 自定义starter的核心服务类 * * @author lxl * @since 2018/12/10 */ public class MdcDemoService { private final String SESSION_ID = "SESSION_ID"; private MdcDemoProperties properties; public MdcDemoService() { } public MdcDemoService(MdcDemoProperties properties) { this.properties = properties; } public String traceId() { if (null != this.properties.getOpen() && false == this.properties.getOpen()) { MDC.put(SESSION_ID, null);; }else{ MDC.put(SESSION_ID, UUID.randomUUID().toString()); } return MDC.get(SESSION_ID); } }
生成自动化配置类
@Configuration:标识此类为一个spring配置类
@EnableConfigurationProperties(MdcDemoProperties.class):启动配置文件,可以有多个,多个配置文件这样写:value={xxProperties1.class,xxProperteis2.class….}
@ConditionalOnClass
,当classpath
下发现该类的情况下进行自动配置。
更多注解参考 官方说明。
package com.demo.spring.starter.mdc; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /*** * 自定义strter的配置类2 * * @author lxl * @since 2018/12/10 */ @Configuration @EnableConfigurationProperties(MdcDemoProperties.class) @ConditionalOnClass(MdcDemoService.class) public class MdcDemoServiceAutoConfiguration { @Autowired private MdcDemoProperties properties; @Bean @ConditionalOnMissingBean(MdcDemoService.class) public MdcDemoService traceId() { return new MdcDemoService(properties); } }
注册配置/META-INF/spring.factories
手动在resources文件下创建META-INF/spring.factories 文件,配置如下:org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.spring.starter.mdc.MdcDemoServiceAutoConfiguration
多个类通过,分隔即可。
打包发布
本地测试 可以通过 mvn install 打包命令打包成一个jar包,本地测试的话需要将mvn的settings文件的仓库改成本地地址,不然会出现找不到包的错误。
测试
1 新建一个spring boot 工程
参考 地址。
2 pom中引入mvn依赖
<dependency> <groupId>com.alibaba.com.custom.starter</groupId> <artifactId>mdc-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>
3 mvn依赖查看
{ "groups": [ { "name": "lxl.mdc", "type": "com.demo.spring.starter.mdc.MdcDemoProperties", "sourceType": "com.demo.spring.starter.mdc.MdcDemoProperties" } ], "properties": [ { "name": "lxl.mdc.open", "type": "java.lang.Boolean", "sourceType": "com.demo.spring.starter.mdc.MdcDemoProperties" } ], "hints": [] }
4 配置application.properties
lxl.mdc.open = open
5 测试demo
@GetMapping(value = "/test") public Result test(@RequestParam(name = "id") Long id) { logger.info("==========test log requestId in controller=============="); System.out.println("applition.properties=" + env.getProperty("lxl.mdc.open")); System.out.println("MDC.get('SESSION_ID')=" + service.traceId()); return dataplusAuthorityTenantService.testMDCInService(id); }
6 测试输出
applition.properties=false MDC.get('SESSION_ID')=null
applition.properties=true MDC.get('SESSION_ID')=31f9f18d-893e-4dd7-b323-e9587968256b
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco }
span.s1 { color: #3933ff }