如何在Quarkus GraphQL服务中实现可执行查询指令
在Quarkus GraphQL中实现自定义字段指令
1. 定义自定义指令
首先要在GraphQL schema里声明你的自定义指令,明确它可以作用在字段上,有两种实现方式:
方式1:使用SDL文件(推荐)
在src/main/resources/graphql/schema.graphqls中添加指令及类型定义:
directive @customDirective(arg: String!) on FIELD type Hero { id: ID! name: String! location: String! } type Query { hero(id: ID!): Hero }
方式2:使用Java注解定义
如果偏好纯代码方式,可通过@DirectiveDefinition注解声明指令:
import io.smallrye.graphql.api.DirectiveDefinition; import io.smallrye.graphql.api.DirectiveLocation; @DirectiveDefinition( name = "customDirective", locations = {DirectiveLocation.FIELD}, arguments = { @DirectiveArgument(name = "arg", typeName = "String", required = true) } ) public class CustomDirective { }
2. 实现指令逻辑处理器
编写指令的核心处理类,实现FieldDirectiveWiring接口,拦截字段解析过程并根据参数执行自定义操作:
import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; import graphql.schema.FieldDirectiveWiring; import graphql.schema.FieldDirectiveWiringEnvironment; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class CustomDirectiveWiring implements FieldDirectiveWiring { @Override public graphql.schema.GraphQLFieldDefinition onField(FieldDirectiveWiringEnvironment env) { // 获取字段原有的数据获取器 DataFetcher<?> originalFetcher = env.getFieldDefinition().getDataFetcher(); // 包装原数据获取器,注入指令逻辑 DataFetcher<?> wrappedFetcher = (DataFetchingEnvironment fetchEnv) -> { // 提取客户端传入的指令参数 String argValue = fetchEnv.getDirective("customDirective") .getArgument("arg") .getValue(String.class); // 执行字段原有解析逻辑 Object originalValue = originalFetcher.get(fetchEnv); // 根据参数对字段值做自定义处理(比如修改、过滤、增强) return processFieldValue(originalValue, argValue); }; // 将新的数据获取器绑定到字段上 return env.getFieldDefinition().transform(builder -> builder.dataFetcher(wrappedFetcher)); } private Object processFieldValue(Object originalValue, String argValue) { // 这里替换成你的业务逻辑,比如根据参数修改location值 if (originalValue instanceof String location) { return String.format("%s [处理标记:%s]", location, argValue); } return originalValue; } }
3. 为字段绑定指令
将自定义指令应用到目标字段,同样支持两种方式:
方式1:在SDL中直接标注
修改schema.graphqls中的Hero类型:
type Hero { id: ID! name: String! location: String! @customDirective(arg: "默认参数") # 客户端传参时会覆盖默认值 }
方式2:在Java实体类上用注解标注
在Hero实体类的对应字段添加@Directive注解:
import io.smallrye.graphql.api.Directive; public class Hero { private String id; private String name; @Directive(name = "customDirective") private String location; // getter、setter省略 }
4. 测试指令效果
启动Quarkus应用后,发送你提供的示例查询:
query GetHero($id: ID!, $argValue: String!) { hero(id: $id) { name location @customDirective(arg: $argValue) } }
假设Hero的location原始值为"哥谭市",当$argValue传入"测试参数"时,返回的location会变为"哥谭市 [处理标记:测试参数]",说明指令逻辑已生效。
内容的提问来源于stack exchange,提问作者user2805089
相关产品推荐
相关产品推荐

