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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:32:58