GraphQL Java - Schema
schema 만 들 기
GraphQL API 는 하나의 Schema 를 가지 고 있 으 며, 이 Schema 는 Query (조회) 나 Mutation (변경) 이 가능 한 필드 와 이 필드 의 종 류 를 정의 합 니 다.
graphql - java 는 schema 를 정의 하 는 두 가지 방식 을 제공 합 니 다. 프로 그래 밍 방식 으로 작성 하고 graphql dsl 문법 (SDL 이 라 고도 함) 으로 작성 합 니 다.
예 를 들 면:
SDL 예제:
type Foo {
bar: String
}
Java 코드 예제:
GraphQLObjectType fooType = newObject()
.name("Foo")
.field(newFieldDefinition()
.name("bar")
.type(GraphQLString))
.build();
DataFetcher 와 TypeResolver
DataFetcher 는 필드 (field) 에 대응 하 는 데 이 터 를 가 져 오 는 데 사 용 됩 니 다.또 뮤 테 이 션 (변경) 유형 이 라면 데 이 터 를 업데이트 하 는 데 사용 할 수 있다.
GraphQL 의 필드 (Field Definition) 마다 DataFetcher 가 있 습 니 다.DataFetcher 가 지정 되 지 않 으 면 이 필드 에 서 는 기본 Property DataFetcher 를 사용 합 니 다.
Property DataFetcher 는 Map 과 자바 빈 에서 데 이 터 를 가 져 옵 니 다.필드 이름 이 맵 의 key 나 bean 대상 의 속성 과 함께 DataFetcher 를 명시 적 으로 지정 할 필요 가 없습니다.
TypeResolver (형식 해석 기) 는 graphql - 자바 가 데이터 의 실제 유형 을 판단 하 는 데 도움 을 줍 니 다.예 를 들 어 인터페이스 와 Union 유형 에 대해 TypeResolver 는 최종 적 으로 얻 은 대상 이 인터페이스 (인터페이스) 의 어느 실현 에 속 하 는 지, 또는 Union (연합) 의 어떤 구체 적 인 유형 에 속 하 는 지 확인 하 는 데 사용 된다.
예 를 들 어 인터페이스 유형 을 MagicUserType 이 라 고 가정 하면 이 인 터 페 이 스 를 실현 하 는 구체 적 인 유형 이 있 습 니 다. Wizard, Witch, Necomancer.TypeResolver (형식 해석 기) 는 실행 할 때 데이터 의 구체 적 인 유형 (Type) 을 식별 하여 어떤 DataFetcher 와 필드 를 호출 할 지 결정 합 니 다.
new TypeResolver() {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
Object javaObject = env.getObject();
if (javaObject instanceof Wizard) {
return env.getSchema().getObjectType("WizardType");
} else if (javaObject instanceof Witch) {
return env.getSchema().getObjectType("WitchType");
} else {
return env.getSchema().getObjectType("NecromancerType");
}
}
};
SDL 로 schema 만 들 기
SDL 정의 모드 를 통 해 DataFetcher 와 TypeResolver 를 제공 해 야 합 니 다.
예 를 들 어 다음 schema 에 대한 정의: (starWarsSchema. graphqls)
schema {
query: QueryType
}
type QueryType {
hero(episode: Episode): Character
human(id : String) : Human
droid(id: ID!): Droid
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
homePlanet: String
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
primaryFunction: String
}
이 schema 정 의 는 필드 (field) 와 형식 (type) 정 의 를 포함 하지만 '실행 시 바 인 딩' (runtime wiring) 이 필요 합 니 다. 자바 방법 에 연결 하여 실행 가능 한 schema 로 만 듭 니 다.
다음 코드 를 사용 하여 귀속 (wiring) 과정 을 완성 할 수 있 습 니 다.
RuntimeWiring buildRuntimeWiring() {
return RuntimeWiring.newRuntimeWiring()
.scalar(CustomScalar)
// this uses builder function lambda syntax
.type("QueryType", typeWiring -> typeWiring
.dataFetcher("hero", new StaticDataFetcher(StarWarsData.getArtoo()))
.dataFetcher("human", StarWarsData.getHumanDataFetcher())
.dataFetcher("droid", StarWarsData.getDroidDataFetcher())
)
.type("Human", typeWiring -> typeWiring
.dataFetcher("friends", StarWarsData.getFriendsDataFetcher())
)
// you can use builder syntax if you don't like the lambda syntax
.type("Droid", typeWiring -> typeWiring
.dataFetcher("friends", StarWarsData.getFriendsDataFetcher())
)
// or full builder syntax if that takes your fancy
.type(
newTypeWiring("Character")
.typeResolver(StarWarsData.getCharacterTypeResolver())
.build()
)
.build();
}
마지막 으로 schema 파일 과 '바 인 딩' (wiring) 을 결합 하여 실행 가능 한 schema 를 만들어 야 합 니 다.예 는 다음 과 같다.
SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();
File schemaFile = loadSchema("starWarsSchema.graphqls");
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFile);
RuntimeWiring wiring = buildRuntimeWiring();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, wiring);
위의 build 방식 을 사용 하 는 것 외 에 TypeResolver 와 DataFetcher 도 WiringFactory 인터페이스 로 바 인 딩 을 완료 할 수 있 습 니 다.
예제 코드 는 다음 과 같다.
RuntimeWiring buildDynamicRuntimeWiring() {
WiringFactory dynamicWiringFactory = new WiringFactory() {
@Override
public boolean providesTypeResolver(TypeDefinitionRegistry registry, InterfaceTypeDefinition definition) {
return getDirective(definition,"specialMarker") != null;
}
@Override
public boolean providesTypeResolver(TypeDefinitionRegistry registry, UnionTypeDefinition definition) {
return getDirective(definition,"specialMarker") != null;
}
@Override
public TypeResolver getTypeResolver(TypeDefinitionRegistry registry, InterfaceTypeDefinition definition) {
Directive directive = getDirective(definition,"specialMarker");
return createTypeResolver(definition,directive);
}
@Override
public TypeResolver getTypeResolver(TypeDefinitionRegistry registry, UnionTypeDefinition definition) {
Directive directive = getDirective(definition,"specialMarker");
return createTypeResolver(definition,directive);
}
@Override
public boolean providesDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) {
return getDirective(definition,"dataFetcher") != null;
}
@Override
public DataFetcher getDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) {
Directive directive = getDirective(definition, "dataFetcher");
return createDataFetcher(definition,directive);
}
};
return RuntimeWiring.newRuntimeWiring()
.wiringFactory(dynamicWiringFactory).build();
}
프로 그래 밍 식 구축 schema
프로 그래 밍 방식 으로 모드 를 만 들 때, 형식 을 만 들 때 DataFetcher 와 TypeResolver 를 제공 합 니 다.
예제 코드 는 다음 과 같다.
DataFetcher fooDataFetcher = new DataFetcher() {
@Override
public Foo get(DataFetchingEnvironment environment) {
// environment.getSource() is the value of the surrounding
// object. In this case described by objectType
Foo value = perhapsFromDatabase(); // Perhaps getting from a DB or whatever
return value;
}
};
GraphQLObjectType objectType = newObject()
.name("ObjectType")
.field(newFieldDefinition()
.name("foo")
.type(GraphQLString)
)
.build();
GraphQLCodeRegistry codeRegistry = newCodeRegistry()
.dataFetcher(
coordinates("ObjectType", "foo"),
fooDataFetcher)
.build();
유형 (유형)
Graphql 형식 시스템 은 다음 과 같은 몇 가지 유형 을 지원 합 니 다.
Scalar
graphql - java 는 다음 과 같은 Scalars 를 지원 합 니 다.
확 장 된 스칼라 의 의 미 는 graphql 클 라 이언 트 에 의 해 정확하게 이해 되 지 않 을 수 있 습 니 다.예 를 들 어 자바 랭 (최대 값 263 - 1) 을 자바 스 크 립 트 숫자 (최대 값 253 - 1) 로 변환 하면 문제 가 발생 할 수 있 습 니 다. Object
SDL 예 는 다음 과 같다.
type SimpsonCharacter {
name: String
mainCharacter: Boolean
}
자바 예제:
GraphQLObjectType simpsonCharacter = newObject()
.name("SimpsonCharacter")
.description("A Simpson character")
.field(newFieldDefinition()
.name("name")
.description("The name of the character.")
.type(GraphQLString))
.field(newFieldDefinition()
.name("mainCharacter")
.description("One of the main Simpson characters?")
.type(GraphQLBoolean))
.build();
Interface
인터페이스 는 추상 적 인 유형의 정의 이다.
SDL 예 는 다음 과 같다.
interface ComicCharacter {
name: String;
}
자바 예제:
GraphQLInterfaceType comicCharacter = newInterface()
.name("ComicCharacter")
.description("An abstract comic character.")
.field(newFieldDefinition()
.name("name")
.description("The name of the character.")
.type(GraphQLString))
.build();
Union
SDL 예 는 다음 과 같다.
type Cat {
name: String;
lives: Int;
}
type Dog {
name: String;
bonesOwned: int;
}
union Pet = Cat | Dog
자바 예제:
TypeResolver typeResolver = new TypeResolver() {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
if (env.getObject() instanceof Cat) {
return CatType;
}
if (env.getObject() instanceof Dog) {
return DogType;
}
return null;
}
};
GraphQLUnionType PetType = newUnionType()
.name("Pet")
.possibleType(CatType)
.possibleType(DogType)
.build();
GraphQLCodeRegistry codeRegistry = newCodeRegistry()
.typeResolver("Pet", typeResolver)
.build();
Enum
SDL 예제:
enum Color {
RED
GREEN
BLUE
}
자바 예제:
GraphQLEnumType colorEnum = newEnum()
.name("Color")
.description("Supported colors.")
.value("RED")
.value("GREEN")
.value("BLUE")
.build();
ObjectInputType
SDL 예제:
input Character {
name: String
}
자바 예제:
GraphQLInputObjectType inputObjectType = newInputObject()
.name("inputObjectType")
.field(newInputObjectField()
.name("field")
.type(GraphQLString))
.build();
Type References (형식 참조, 재 귀적 형식 생 성 에 사용)
GraphQL 은 재 귀적 형식 을 지원 합 니 다. 예 를 들 어 Person 클래스 는 같은 유형의 friends 를 포함 할 수 있 습 니 다.
이러한 유형 을 지원 하기 위해 graphql - java 는 GraphQLtype Reference 클래스 를 제공 합 니 다.
schema 가 생 성 될 때 GraphQLtype Reference 는 실제 형식 으로 대 체 됩 니 다.
예 를 들 면:
GraphQLObjectType person = newObject()
.name("Person")
.field(newFieldDefinition()
.name("friends")
.type(GraphQLList.list(GraphQLTypeReference.typeRef("Person"))))
.build();
schema 가 SDL 로 만 들 면 name 재 귀적 형식 은 표시 되 지 않 아 도 됩 니 다. graphql 은 자동 으로 검 측 됩 니 다.
Schema SDL 모듈 화
비교적 큰 schema 파일 을 유지 하 는 것 은 가능 하지 않 습 니 다. graphql - 자바 도 두 가지 방식 을 제공 하여 schema 에 대해 모듈 화 할 수 있 습 니 다.
첫 번 째 방법 은 여러 개의 Schema SDL 파일 을 하나의 논리 단위 로 통합 하 는 것 입 니 다. 아래 의 경우 Schema 는 여러 개의 파일 로 나 누 어 Schema 가 생 성 되 기 전에 합 칩 니 다.
SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();
File schemaFile1 = loadSchema("starWarsSchemaPart1.graphqls");
File schemaFile2 = loadSchema("starWarsSchemaPart2.graphqls");
File schemaFile3 = loadSchema("starWarsSchemaPart3.graphqls");
TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();
// each registry is merged into the main registry
typeRegistry.merge(schemaParser.parse(schemaFile1));
typeRegistry.merge(schemaParser.parse(schemaFile2));
typeRegistry.merge(schemaParser.parse(schemaFile3));
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, buildRuntimeWiring());
Graphql SDL 형식 시스템 은 모듈 화 모드 에 사용 할 다른 방법 을 가지 고 있 습 니 다. 형식 확장 을 사용 하여 형식 에 추가 필드 와 인 터 페 이 스 를 추가 할 수 있 습 니 다.
모드 파일 에서 이러한 형식 으로 시작한다 고 가정 합 니 다.
type Human {
id: ID!
name: String!
}
시스템 의 다른 부분 은 이 형식 을 확장 하고 더 많은 필드 를 추가 할 수 있 습 니 다. 예 를 들 어:
extend type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
가능 한 한 많은 확장 을 사용 할 수 있 습 니 다. 발 견 된 순서 로 합 쳐 집 니 다. 중 복 된 필드 는 하나 로 합 쳐 집 니 다.
extend type Human {
homePlanet: String
}
이상 의 여러 schema 파일 은 실행 할 때 Human 형식 으로 합 쳐 집 니 다. 다음 과 같 습 니 다.
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
homePlanet: String
}
이것 은 schema 의 맨 위 에 디자인 할 때 매우 중요 합 니 다. 확장 형식 을 사용 하여 맨 위 에 있 는 schema 의 "query"에 새로운 필드 를 추가 할 수 있 습 니 다.
팀 은 최상 위 graphql 조 회 를 위해 각자 의 모듈 기능 을 독립 적 으로 수행 할 수 있 습 니 다.
schema {
query: CombinedQueryFromMultipleTeams
}
type CombinedQueryFromMultipleTeams {
createdTimestamp: String
}
# maybe the invoicing system team puts in this set of attributes
extend type CombinedQueryFromMultipleTeams {
invoicing: Invoicing
}
# and the billing system team puts in this set of attributes
extend type CombinedQueryFromMultipleTeams {
billing: Billing
}
# and so and so forth
extend type CombinedQueryFromMultipleTeams {
auditing: Auditing
}
구독 지원
구독 은 조 회 를 허용 하고 관련 조회 의 백 엔 드 대상 이 변경 되면 업 데 이 트 된 대상 은 실시 간 으로 추 송 됩 니 다.
subscription foo {
# normal graphql query
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.