面临另一个问题
作为开发者,每次调用接口都需要自己生成时间戳,编写签名算法,生成随机数等等,这些都是相当繁琐的工作。
因此,要想办法让开发者能够以最简单的方式调用接口。开发者只需要关心传递哪些参数以及他们的密钥等信息就可以轻松地进行调用。
实际上,RPC(远程过程调用)就是为了实现这一目的而设计的。它就是追求简单化调用的理想情况。类似的例子是小程序开发或者调用第三方 API,如腾讯云的 API,它们都提供了相应的 SDK。
开发 SDK
Starter
现在的问题是如何开发这样一个 SDK?为了让开发者更方便使用 SDK,我们给它提供一个 starter
为什么需要 Starter?
理想情况:开发者只需要关心调用哪些接口、传递哪些参数,就跟调用自己写的代码一样简单。
开发 starter 的好处:开发者引入之后,可以直接在 application.yml 中写配置,自动创建客户端。
找到pom.xml,在这里看到引入 mybatis、redis、 swagger 接口文档的时候,都使用了 starter。
使用 starter 之后,我们有哪些好处?
比如,对于 Redis 的 starter,我们可以直接在 application.yml 配置文件中进行相关配置。我们可以在配置文件中简单地定义一个连接到 Redis 的配置块。
Spring Configuration Processor:它的作用就是帮助开发者自动生成配置的代码提示。
好处是无需手动编写繁琐的配置代码或者创建客户端实例。通过引入适当的 starter,开发者可以直接在 application.yml 中进行配置,自动创建相应的客户端。
使得开发过程更加简单便捷,无需过多关注底层实现细节,而是专注于配置和使用。
Starter 开发流程
开发
创建一个新项目 —— 项目名:suapi-client-sdk
选择依赖:Lombok、Spring Configuration Processor
下面这个东西要删掉,不然会报错(一定要删掉);
这个是 maven 构建项目的方式,我们现在是要构建依赖包,而不是直接运行 jar 包的项目。
项目之默认会生成一个 Spring Boot 的主类。我们并不打算运行一个 Web 项目,而是提供一个现成的客户端对象给用户使用。删掉主类,创建配置类。
目标是为用户生成一个可用的客户端对象,我们希望用户能够通过引入 starter 的方式直接使用客户端,而不需要手动创建,所以我们需要编写一个配置类。
在配置类中打上几个注解,加上两个参数accessKey secretKey。
// 通过 @Configuration 注解,将该类标记为一个配置类,告诉 Spring 这是一个用于配置的类
@Configuration
// 能够读取application.yml的配置,读取到配置之后,把这个读到的配置设置到我们这里的属性中,
// 这里给所有的配置加上前缀为"suapi.client"
@ConfigurationProperties("suapi.client")
// @Data 注解是一个 Lombok 注解,自动生成了类的getter、setter方法
@Data
// @ComponentScan 注解用于自动扫描组件,使得 Spring 能够自动注册相应的 Bean
@ComponentScan
public class SuApiClientConfig {
private String accessKey;
private String secretKey;
}
现在我们要给用户提供 ApiClient,把 suapi-interface 项目中的 client包、model包、utils包复制
粘贴到 suapi-client-sdk 项目中。
回到 suapi-client-sdk 项目 中的 SuApiClientConfig配置类, 写一下生成客户端的方法。
这个地方不像之前在 suapi-interface 项目中写死在 Main.java 里,只是测试。
现在就是通过读取这个配置拿到这两个值。用这两个值去得到这样一个客户端实例。
现在,如果我们引入这个库并配置好了 accessKey 和 secretKey 的相关属性,Spring Boot 将自动为我们生成一个客户端对象。然后,我们可以在项目中使用这个对象了。
还要做一件事情
①在 resources 目录下创建一个目录 META-INF
②在 META-INF
目录创建一个文件 spring.factories
spring.factories:定义了 Spring Boot 的自动配置。它是一个标准的 Java Properties 文件,用于指定要自动配置的类。这个文件中的每一行都是一个配置项,包含两个部分:配置项的全限定类名和对应的自动配置类。它们之间使用等号(=)进行分隔。在 Spring Boot 应用启动时,它会加载这个 spring.factories 文件,并根据其中的配置项自动进行相应的配置。
③在 spring.factories
文件内编写配置项为自动引入配置的类。
上述配置项指定了要自动配置的类
Spring Boot 将会在应用启动时自动加载和实例化 YuApiClientConfig,并将其应用于我们的应用程序中。我们就可以使用自动配置生成的 suApiClient 对象,而无需手动创建和配置
install
点击右侧菜单栏中的 maven,点击 Lifecycle → install,把它安装为本地的依赖。
使用
来到 interface 项目
引入我们写好的依赖
点击 application.yml 进行配置
编写测试方法
@SpringBootTest
class SuapiInterfaceApplicationTests {
@Resource
private SuApiClient suApiClient;
@Test
void contextLoads() {
// 调用suApiClient的getNameByGet方法,并传入参数,将返回的结果赋值给result变量
String result = suApiClient.getNameByGet("sujie");
// 创建一个User对象
User user = new User();
// 设置User对象的username属性
user.setUsername("sujie");
// 调用yuApiClient的getUserNameByPost方法,并传入user对象作为参数,将返回的结果赋值给usernameByPost变量
String usernameByPost = suApiClient.getUserNameByPost(user);
// 打印result变量的值
System.out.println(result);
// 打印usernameByPost变量的值
System.out.println(usernameByPost);
}
}
无敌大踩坑!!!
@ComponentScan不会自动创建带有 @ConfigurationProperties注解的类的 bean
@EnableConfigurationProperties 确保 @ConfigurationProperties 类能够正确处理,在 Spring Boot 应用启动阶段,起到激活和管理的作用。
为什么?
@ComponentScan不会自动创建带有@ConfigurationProperties注解的类的 bean 主要有以下原因:
一、设计目的不同
1. @ComponentScan的主要目的是扫描并注册带有特定注解(如@Component、@Service、@Repository等)的类作为 Spring 的组件。这些注解通常标识的是业务逻辑相关的类或者服务类,它们在应用中扮演着具体的角色,如处理业务逻辑、提供数据访问等。
2. @ConfigurationProperties主要用于将外部配置属性绑定到一个 Java 对象上,它的重点在于属性的绑定和配置管理,而不是作为一个独立的业务组件被自动注册。
二、职责分离
Spring 框架遵循了职责分离的原则。@ComponentScan专注于发现和注册业务相关的组件,而配置属性的处理通常需要额外的步骤来确保正确的绑定和验证。如果@ComponentScan自动创建带有@ConfigurationProperties的类的 bean,可能会导致一些不确定性和潜在的错误。
例如,如果一个配置属性类被错误地自动注册为 bean,可能会在应用中引起意外的行为,尤其是当这个类的作用和预期的业务组件不同时。
三、灵活性考虑
不自动创建@ConfigurationProperties类的 bean 给予了开发者更多的灵活性。开发者可以根据具体的需求选择是否将配置属性类注册为 bean。如果需要将其作为一个 bean 使用,可以通过添加@Component注解或者使用@EnableConfigurationProperties注解来明确地进行注册,这样可以更好地控制应用的配置和行为。
解决方法
在xxxInterfaceApplication启动类上
加@EnableConfigurationProperties(xxxApiClientConfig.class)
总结
开发一个 starter 关键步骤只有几个。
首先确认所需依赖。
然后写 META-INF,指定配置注册类。
通过这个注解来读取到配置信息。