跳到正文
W Winse Blog
mobile dev ai 2 min read

Conjure使用指南:告别接口API对接烦恼,拥抱高效开发

当下前后端开发分开范式下,前端和后端通过API接口进行数据交互。这种模式为开发团队提供了更好的模块化和独立性,但也带来了一些挑战:数据模型的一致性、代码重复 编写、以及跨语言 的兼容性等问题。

Conjure正是在这样的背景下产生的,它提供了一种统一的数据模型 定义方式,并通过代码生成的方式,使得前后端接口的对接变得更加简单、高效。

本文简单介绍Conjure的特性、使用方法、并展示最终的效果。后续文章将通过一个完整的项目示例和一个调用高德API的例子,深入的展示如何使用Conjure。

# 什么是 Conjure?

Conjure https://palantir.github.io/conjure/#/readme 是 Palantir 公司开发的一款多语言代码生成工具,专为 HTTP/JSON API接口设计

它通过YAML配置文件中定义 API 的服务端点、请求和响应,然后自动生成多种语言的类型安全的客户端和服务端的RPC代码。

# Conjure 的核心优势

1、统一定义:使用人类可读的 YAML 格式来描述 API,使定义过程清晰简洁。这种声明式方式确保了团队成员和不同服务之间对API行为的一致理解,从而达成“心智对齐”。

2、多语言支持:通过一次定义,生成适用于多语言代码。无论是前端的 TypeScript,还是后端服务器 Java。无论开发者使用哪种语言,Conjure 都能为你生成高质量的、可直接使用的代码。

3、强类型安全性:基于严格的 API 定义生成类型安全的代码。在编译阶段就能捕获类型错误,极大提升了项目的健壮性,同时提升了开发效率(如自动代码补全)。

4、减少重复劳动:自动化了大量重复的客户端和服务端代码工作,让开发者可以专注于业务逻辑,而不是在重复的枯燥的序列化、反序列化上面浪费大把时间。

5、简化版本控制:所有API数据类型和接口定义都集中在一个YAML配置文件中,简化了版本控制,没有冗余代码干扰。

虽然Conjure非常强大,但它并不是万能的。文档中提到:为了让增强API的一致性,Conjure在设计上仅支持部分的 HTTP 子集。这种方式也能够覆盖80%到90%的常见需求,当然剩下的特殊情况也能通过调整生成的代码来处理。

# Conjure原理

Conjure 的工作流程可以概括为以下三步:

1、定义API: 开发者使用 YAML 文件,以声明式的方式定义 API 的数据模型 (types,如用户、产品) 和服务接口 (services,如获取用户、创建订单)。这些定义包括 HTTP请求路径、请求参数以及返回值类型等详细规范。这是整个流程的起点,也是团队协作的核心。

2、中间表示模型 (IR): Conjure 编译器会读取并校验 YAML 接口定义文件,然后将其转换为一种JSON 格式的中间表示(IR),它是与实际代码语言无关的,包含了所有的 API 定义的结构化信息,充当了一个通用桥梁,便于将抽象的 API 定义转换为后续代码生成特定编程语言需要的格式。

3、多编程语言代码生成:根据这个
IR 反序列为抽象语法树(AST,java用javapoet,typescript用ts-simple-ast),生成目标语言的客户端和服务端代码。生成的代码包含了数据模型类、服务接口以及API调用和实现所需的基础结构代码。让开发者能够无缝地在现有项目中集成,快速实现API的调用或实现。

# Hello World!

结合 https://palantir.github.io/conjure/#/docs/getting\_started 和 https://github.com/palantir/gradle-conjure 两个文档。下面开始写 Conjure 的第一个hello world。

建立如下目录结构:

winse@DESKTOP-H3OHF4N:hello-conjure$ tree . . ├── build.gradle ├── hello-api │   ├── build.gradle │   └── src │       └── main │           └── conjure │               └── hello.yml └── settings.gradle 5 directories, 4 files

# * YAML配置

Conjure API 配置文件 hello.yml 定义了数据类型和服务端点。例如,一个简单的 RecipeBookAPI 如下所示:

types:   definitions:     default-package: com.company.product     objects:       Recipe:         fields:           name: RecipeName           steps: list<RecipeStep>       RecipeStep:         union:           mix: set<Ingredient>           chop: Ingredient       RecipeName:         alias: string       Ingredient:         alias: string services:   RecipeBookService:     name: RecipeBook     package: com.company.product     base-path: /recipes     endpoints:       createRecipe:         http: POST/         args:           createRecipeRequest:             param-type: body             type: Recipe

# * Gradle 配置

gradle的配置有两个文件:

在 settings.gradle 里面配置子项目。这里需要理解一下Conjure的声明式约定:Conjure YAML文件将放在:hello-api,生成的代码将写入后缀为-objects-jersey-typescript的子工程中。

rootProject.name = 'hello-conjure' include 'hello-api' include 'hello-api:hello-api-objects' include 'hello-api:hello-api-jersey' include 'hello-api:hello-api-typescript'

在 build.gradle 里配置gradle-conjure插件,添加代码生成工具。然后在接口子工程中配置需要生成哪些语言的代码。

buildscript {     repositories {         mavenCentral()     }     dependencies {         classpath'com.palantir.gradle.conjure:gradle-conjure:5.10.0'     } } allprojects {     repositories {         mavenCentral()     } } apply plugin: 'com.palantir.conjure' // 需要定义在rootProject, 指定依赖的版本号 configurations {     conjureCompiler     conjureJava     conjureTypeScript } dependencies {     conjureCompiler 'com.palantir.conjure:conjure:4.16.1'     conjureJava 'com.palantir.conjure.java:conjure-java:6.5.0'     conjureTypeScript 'com.palantir.conjure.typescript:conjure-typescript:5.4.0' } // 子工程配置 subprojects {     apply plugin: 'java-library'     apply plugin: 'com.palantir.conjure'          sourceCompatibility = 11     targetCompatibility = 11          compileJava {         options.encoding = "UTF-8"     }          conjure {         typescript {             version = "0.0.1"         }         java {             useImmutableBytes = true         }     }          dependencies {         implementation "com.palantir.conjure.java:conjure-lib:6.5.0"     } }

最后使用gradle命令生成代码即可:

E:\winsegit\hello-conjure>set PATH=D:\node-v20.13.1-win-x64;E:\local\gradle-8.13\bin;C:\Java\jdk-11.0.12\bin;%PATH% E:\winsegit\hello-conjure>gradle compileConjure

# 生成的代码

根据此 API 定义,conjure-java生成器将生成适用于 JAX-RS/Jersey 服务器的服务器存根(stub):

@Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/") @Generated("com.palantir.conjure.java.services.JerseyServiceGenerator") public interface RecipeBookService {     @POST     @Path("recipes")     @ClientEndpoint(method = "POST", path = "/recipes")     void createRecipe(Recipe createRecipeRequest); }

该生成器还为 Conjure定义的类型 生成不可变的类,这些类型在内部使用Jackson进行序列化和反序列化。

Conjure的运行时库可以轻松创建客户端,在客户端连接服务如下:

        RecipeBookService recipeBookService = JaxRsClient.create(                 RecipeBookService.class,                 UserAgent.of(UserAgent.Agent.of("hello", "0.0.1")),                 NoOpHostEventsSink.INSTANCE,                 ClientConfigurations.of(ServiceConfiguration.builder()                         .addUris("http://localhost:8080/api/")                         .security(SslConfiguration.of(Paths.get("C:\\Java\\jdk-11.0.12\\lib\\security\\cacerts"))) //如果需要指定                         .build()));         recipeBookService.createRecipe(                 Recipe.builder()                         .name(RecipeName.of("test"))                         .build());

当然 curl 的方式也是可以的:

winse@DESKTOP-H3OHF4N:~$ curl http://localhost:8080/api/recipes \     -H 'Content-Type: application/json' \     --data '{"name": "My recipe", "steps": []}'

上面配置生成了java和typescript两种语言的代码。java的分为模型 -objects 和 接口 -jersey 两个工程,typescript的代码全部放在 -typescript 中。

Java数据模型类

Java接口服务类

typescript工程(包括模型和接口)

# 结语

Palantir Conjure 为解决 API 对接 挑战提供了一个优雅且高效的解决方案。通过其声明式 API 定义、多语言代码生成和强类型安全性,Conjure 能够显著提升开发效率,降低错误率,并确保 API 在不同服务和语言之间的一致性。正如 Palantir 所述,Conjure 不仅简化了 API 的创建和使用过程,更重要的是,它将 API 定义提升为契约,使得服务间通信更加可靠和可预测。

如果你正为繁琐的 API 对接和维护所困扰,那么 Palantir Conjure 绝对值得你尝试。它将帮助你告别烦恼,拥抱更流畅、更可靠的开发体验。

编写一个配置,运行一个脚本,生成一套代码,接口对接不在烦恼。

在 GitHub 上讨论

欢迎通过 GitHub Issue 留言或反馈。每条讨论都会关联到对应文章的源文件路径。

2025-07-20-Conjure使用指南:告别接口API对接烦恼,拥抱高效开发.md

Related posts