如何在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
相关产品推荐
相关产品推荐

