You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中动态构建GraphQL查询并传递参数?

动态构建GraphQL查询并传递参数(Java)

一、动态传递搜索参数(首要目标)

要实现参数动态化,最佳实践是使用GraphQL变量替代硬编码值,避免字符串拼接带来的安全问题和可读性问题。

步骤1:修改查询为带变量的形式

将原查询中的硬编码"java"替换为变量$query,并在查询头部声明变量类型:

query TestAPI($query: String!) {
  testAPI(query: $query) {
    page 
    pageCount 
    documents {
      id
      ... on Document {
        title
        updated
        subjects{
            id
            name
            url
        }
        rating {
            average
            count
        }
        categories {
            id
            name
            url
            subcategories {
                id
                name
                url
            }
        }
        images {
            px100x100
        }
      }
    }
  }
}

步骤2:在代码中传入动态参数

通过GraphQLRequest.builder().variables()方法传递变量值,示例代码如下:

// 初始化WebClient和GraphQLWebClient(可复用,无需每次创建)
WebClient webClient = WebClient.builder()
        .baseUrl("http://test.com/graphql")
        .build();
GraphQLWebClient graphqlClient = GraphQLWebClient.newInstance(webClient, objectMapper);

// 动态参数值(可替换为任意输入源)
String dynamicQuery = "spring";

// 构建带变量的GraphQL请求
GraphQLRequest request = GraphQLRequest.builder()
        .query("query TestAPI($query: String!) {\n" +
                "  testAPI(query: $query) {\n" +
                "    page \n" +
                "    pageCount \n" +
                "    documents {\n" +
                "      id\n" +
                "      ... on Document {\n" +
                "        title\n" +
                "        updated\n" +
                "        subjects{\n" +
                "            id\n" +
                "            name\n" +
                "            url\n" +
                "        }\n" +
                "        rating {\n" +
                "            average\n" +
                "            count\n" +
                "        }\n" +
                "        categories {\n" +
                "            id\n" +
                "            name\n" +
                "            url\n" +
                "            subcategories {\n" +
                "                id\n" +
                "                name\n" +
                "                url\n" +
                "            }\n" +
                "        }\n" +
                "        images {\n" +
                "            px100x100\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}")
        .variables(Map.of("query", dynamicQuery)) // 传入动态变量
        .build();

// 发送请求
GraphQLResponse response = graphqlClient.post(request).block();

二、动态构建查询字段(次要目标)

如果需要动态添加/移除查询字段,可以通过字符串拼接或封装字段构建工具类实现,以下是两种方案:

方案1:字符串拼接实现动态字段

创建方法根据传入的字段列表动态生成documents节点下的字段内容:

private String buildDocumentFields(List<String> requiredFields) {
    // 基础必选字段
    StringBuilder fieldsBuilder = new StringBuilder("id\n      ... on Document {\n");
    
    // 动态添加指定字段
    for (String field : requiredFields) {
        switch (field) {
            case "title":
            case "updated":
                fieldsBuilder.append("        ").append(field).append("\n");
                break;
            case "subjects":
                fieldsBuilder.append("        subjects{\n            id\n            name\n            url\n        }\n");
                break;
            case "rating":
                fieldsBuilder.append("        rating {\n            average\n            count\n        }\n");
                break;
            case "categories":
                fieldsBuilder.append("        categories {\n            id\n            name\n            url\n            subcategories {\n                id\n                name\n                url\n            }\n        }\n");
                break;
            case "images":
                fieldsBuilder.append("        images {\n            px100x100\n        }\n");
                break;
            // 可扩展更多字段类型
        }
    }
    
    fieldsBuilder.append("      }");
    return fieldsBuilder.toString();
}

调用方法生成完整查询:

// 动态指定需要的字段
List<String> requiredFields = Arrays.asList("title", "subjects", "rating");

// 构建动态字段部分
String documentFields = buildDocumentFields(requiredFields);

// 拼接完整查询字符串
String dynamicQueryStr = String.format("query TestAPI($query: String!) {\n" +
        "  testAPI(query: $query) {\n" +
        "    page \n" +
        "    pageCount \n" +
        "    documents {\n" +
        "%s\n" +
        "    }\n" +
        "  }\n" +
        "}", documentFields);

// 构建请求并发送
GraphQLRequest request = GraphQLRequest.builder()
        .query(dynamicQueryStr)
        .variables(Map.of("query", "spring"))
        .build();

GraphQLResponse response = graphqlClient.post(request).block();

方案2:使用GraphQL-Java构建器(严谨性更高)

如果需要避免字符串拼接的语法错误,可以引入graphql-java依赖,用其API动态构建查询对象:

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java</artifactId>
    <version>21.0</version>
</dependency>

核心逻辑示例:

// 构建documents字段(可动态添加子字段)
ObjectField documentField = ObjectField.newObjectField("documents")
        .field("id")
        .inlineFragment(InlineFragment.newInlineFragment().typeCondition("Document")
                .field("title")
                .field(ObjectField.newObjectField("subjects")
                        .field("id")
                        .field("name")
                        .field("url")
                        .build())
                .build())
        .build();

// 构建完整查询
OperationDefinition query = OperationDefinition.newOperationDefinition()
        .name("TestAPI")
        .operation(OperationType.QUERY)
        .variable(Variable.newVariable().name("query").type(TypeName.newTypeName("String").build()).build())
        .selectionSet(SelectionSet.newSelectionSet()
                .selection(ObjectField.newObjectField("testAPI")
                        .argument(Argument.newArgument().name("query").value(VariableReference.newVariableReference("query").build()).build())
                        .field("page")
                        .field("pageCount")
                        .field(documentField)
                        .build())
                .build())
        .build();

// 序列化为可执行的查询字符串
String queryStr = new Printer().print(query);

内容的提问来源于stack exchange,提问作者ThatMan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:17:04