Skip to content

快速开始

概述

CoApi 将 HTTP 客户端设置精简到极致:用 @HttpExchange 方法定义一个 Java 或 Kotlin 接口,用 @CoApi 注解标记接口,Spring Boot 自动配置处理其余一切。无需手动构建 WebClientRestClient,无需设置代理工厂,无需样板代码。

一览

步骤操作关键文件源码
1. 添加依赖coapi-spring-boot-starterspring-boot-starter/build.gradle.ktsbuild.gradle.kts
2. 定义接口@CoApi + @GetExchangeGitHubApiClient.ktGitHubApiClient.kt
3. 配置 URLapplication.yamlapplication.yamlapplication.yaml
4. 注入并使用构造函数注入GithubController.ktGithubController.kt

步骤 1:添加依赖

Gradle(Kotlin DSL):

kotlin
implementation("me.ahoo.coapi:coapi-spring-boot-starter")

Maven:

xml
<dependency>
    <groupId>me.ahoo.coapi</groupId>
    <artifactId>coapi-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>

如需负载均衡,还需添加:

kotlin
implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")

步骤 2:定义接口

kotlin
@CoApi(baseUrl = "\${github.url}")
interface GitHubApiClient {

    @GetExchange("repos/{owner}/{repo}/issues")
    fun getIssue(@PathVariable owner: String, @PathVariable repo: String): Flux<Issue>
}

data class Issue(val url: String)

@CoApi 注解完成三件事:

  1. 将此接口标记为 HTTP 客户端(也充当 @Component
  2. 定义基础 URL(支持 ${...} 属性占位符)
  3. 触发自动配置以注册 bean

步骤 3:配置 URL

yaml
# application.yaml
github:
  url: https://api.github.com

@CoApi(baseUrl) 中的 ${github.url} 占位符会针对 Spring 的 Environment 进行解析。

步骤 4:启用并使用

Spring Boot(自动配置):无需其他操作。CoApi 会自动发现应用程序基础包中的 @CoApi 接口。

非 Boot / 显式模式:添加 @EnableCoApi

kotlin
@EnableCoApi(clients = [GitHubApiClient::class])
@SpringBootApplication
class MyApplication

注入到任何组件中:

kotlin
@RestController
class GithubController(private val gitHubApiClient: GitHubApiClient) {

    @GetMapping("/issues")
    fun getIssues(): Flux<Issue> {
        return gitHubApiClient.getIssue("Ahoo-Wang", "CoApi")
    }
}

设置流程

mermaid
flowchart TD
    A["Add coapi-spring-boot-starter"] --> B["Define CoApi interface"]
    B --> C["Configure URL in YAML"]
    C --> D{"Spring Boot?"}
    D -->|Yes| E["Auto-discovery via AutoCoApiRegistrar"]
    D -->|No| F["EnableCoApi(clients=[...])"]
    E --> G["CoApiRegistrar registers beans"]
    F --> G
    G --> H["Inject interface and call methods"]

请求流程

mermaid
sequenceDiagram
    autonumber
    participant Controller as GithubController
    participant Proxy as GitHubApiClient Proxy
    participant Adapter as WebClientAdapter
    participant Client as WebClient
    participant API as api.github.com

    Controller->>Proxy: getIssue("Ahoo-Wang", "CoApi")
    Proxy->>Adapter: exchange(request)
    Adapter->>Client: GET /repos/Ahoo-Wang/CoApi/issues
    Client->>API: HTTP GET request
    API-->>Client: JSON response
    Client-->>Adapter: Flux<Issue>
    Adapter-->>Proxy: Flux<Issue>
    Proxy-->>Controller: Flux<Issue>

Bean 注册

mermaid
sequenceDiagram
    autonumber
    participant Boot as Spring Boot
    participant Auto as AutoCoApiRegistrar
    participant Reg as CoApiRegistrar
    participant Registry as BeanDefinitionRegistry

    Boot->>Auto: registerBeanDefinitions()
    Auto->>Auto: inferClientMode()
    Auto->>Registry: register HttpExchangeAdapterFactory
    Auto->>Auto: scan classpath for @CoApi interfaces
    Auto->>Reg: register(definitions)
    loop For each @CoApi interface
        Reg->>Registry: register name.HttpClient (WebClient/RestClient)
        Reg->>Registry: register name.CoApi (CoApiFactoryBean proxy)
    end

常见变体

负载均衡客户端

kotlin
@CoApi(serviceId = "github-service")
interface ServiceApiClient {
    @GetExchange("repos/{owner}/{repo}/issues")
    fun getIssue(@PathVariable owner: String, @PathVariable repo: String): Flux<Issue>
}

配置服务实例:

yaml
spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            github-service:
              - host: api.github.com
                secure: true
                port: 443

同步客户端(Java)

java
@CoApi(baseUrl = "${github.url}")
public interface GitHubSyncClient {
    @GetExchange("repos/{owner}/{repo}/issues")
    List<Issue> getIssue(@PathVariable String owner, @PathVariable String repo);
}

设置 coapi.mode=SYNC 以切换到基于 RestClient 的模式。返回 List<T> 而不是 Flux<T>

共享 API 契约模式

定义提供者和消费者都依赖的共享 API 接口:

kotlin
// Shared module: example-provider-api
@HttpExchange("todo")
interface TodoApi {
    @GetExchange
    fun getTodo(): Flux<Todo>
}

// Consumer module
@CoApi(serviceId = "provider-service")
interface TodoClient : TodoApi

// Provider module
@RestController
class TodoController : TodoApi {
    override fun getTodo(): Flux<Todo> = Flux.just(Todo("Hello"))
}

相关页面

参考资料

  1. GitHubApiClient 示例example/example-consumer-client/src/main/kotlin/.../GitHubApiClient.kt
  2. ConsumerServerexample/example-consumer-server/src/main/kotlin/.../ConsumerServer.kt
  3. GithubControllerexample/example-consumer-server/src/main/kotlin/.../GithubController.kt
  4. Consumer application.yamlexample/example-consumer-server/src/main/resources/application.yaml
  5. CoApi 注解api/src/main/kotlin/me/ahoo/coapi/api/CoApi.kt
  6. EnableCoApi 注解spring/src/main/kotlin/me/ahoo/coapi/spring/EnableCoApi.kt