0

GraphQL服务实现

 2 years ago
source link: https://perkins4j2.github.io/posts/522360011/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

GraphQL服务实现

发表于

2020-09-01

| 分类于 架构

| 阅读次数: 38

本文字数: 7.8k

|

阅读时长 ≈ 7 分钟

GraphQL是一种用于API或数据的查询语言。

  • 发出一个GraphQL请求就能准确获得想要的数据,不多不少。 - GraphQL查询总是返回可预测的结果。
  • REST API请求多个资源时,GraphQL可以通过一次请求就获取所需的所有数据。
  • GraphQL基于类型和字段的方式进行查询语言定义。

    Maven引入

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

Schema定义

schema {
query: Query
}

type Query {
shops: [Shop]
expensiveShops: [Shop]
}

type Shop {
id: ID!
name: String!
departments: [Department]
expensiveDepartments: [Department]
}

type Department {
id: ID!
name: String!
products: [Product]
expensiveProducts: [Product]
}

type Product {
id: ID!
name: String!
}

GraphQL实例化

@Component
@Slf4j
public class GraphQLService {

private GraphQL graphQL;
public GraphQLSchema graphQLSchema;

private boolean cache = true;

@Autowired
DataFetchers dataFetchers;

@Bean
public GraphQL graphQL() {
return graphQL;
}

Cache<String, PreparsedDocumentEntry> sdlCache = Caffeine
.newBuilder()
.maximumSize(1_000)
.initialCapacity(100)
.build();

/**
* To avoid the need for re-parse/validate the GraphQL.Builder
* allows an instance of PreparsedDocumentProvider to reuse Document instances.
*/
PreparsedDocumentProvider preparsedCache = (executionInput, function) -> {
Function<String, PreparsedDocumentEntry> mapCompute = key -> function.apply(executionInput);
return sdlCache.get(executionInput.getQuery(), mapCompute);
};

@PostConstruct
public void init() {
graphQLSchema = buildSchema();

GraphQL.Builder builder = GraphQL.newGraphQL(graphQLSchema);

if (cache) {
builder.preparsedDocumentProvider(preparsedCache);
}

this.graphQL = builder.build();
}

private GraphQLSchema buildSchema() {
SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();

Map<String, InputStream> streamMap = ClassFilesUtils.getInputStreams("schema", ".graphqls");

streamMap.forEach((k, v) -> {
try {
String str = CharStreams.toString(new InputStreamReader(v, StandardCharsets.UTF_8));

typeRegistry.merge(schemaParser.parse(str));
} catch (IOException e) {
log.error("error", e);
} finally {
try {
v.close();
} catch (IOException e) {
log.error("error", e);
}
}
});

RuntimeWiring runtimeWiring = buildWiring();

SchemaGenerator schemaGenerator = new SchemaGenerator();

return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
}

private RuntimeWiring buildWiring() {
//扩展类型
return RuntimeWiring.newRuntimeWiring()
.scalar(ExtendedScalars.GraphQLByte)
.scalar(ExtendedScalars.GraphQLShort)
.scalar(ExtendedScalars.GraphQLMap)
.type(newTypeWiring("Query").dataFetcher("xxx", dataFetchers.findXXX())).build();
}
}
@PublicApi
public class ExtendedScalars {
/**
* This represents the "Long" type which is a representation of java.lang.Long
*/
public static final GraphQLScalarType GraphQLLong = JavaPrimitives.GraphQLLong;

/**
* This represents the "Short" type which is a representation of java.lang.Short
*/
public static final GraphQLScalarType GraphQLShort = JavaPrimitives.GraphQLShort;

/**
* This represents the "Byte" type which is a representation of java.lang.Byte
*/
public static final GraphQLScalarType GraphQLByte = JavaPrimitives.GraphQLByte;

/**
* This represents the "BigDecimal" type which is a representation of java.math.BigDecimal
*/
public static final GraphQLScalarType GraphQLBigDecimal = JavaPrimitives.GraphQLBigDecimal;

/**
* This represents the "BigInteger" type which is a representation of java.math.BigInteger
*/
public static final GraphQLScalarType GraphQLBigInteger = JavaPrimitives.GraphQLBigInteger;

/**
* This represents the "Char" type which is a representation of java.lang.Character
*/
public static final GraphQLScalarType GraphQLChar = JavaPrimitives.GraphQLChar;

public static final GraphQLScalarType GraphQLMap = JavaPrimitives.GraphQLMap;
}

支持Map

public static final GraphQLScalarType GraphQLMap = new GraphQLScalarType("Map", "A custom map scalar type", new Coercing() {
@Override
public Map serialize(Object dataFetcherResult) throws CoercingSerializeException {
Map map;
try {
map = (Map) dataFetcherResult;
} catch (ClassCastException exception) {
throw new CoercingSerializeException("Could not convert " + dataFetcherResult + " into a Map", exception);
}
return map;
}

@Override
public Map parseValue(Object input) throws CoercingParseValueException {
Map map;
try {
map = (Map) input;
} catch (ClassCastException exception) {
throw new CoercingParseLiteralException("parseValue called");
}
return map;
}

@Override
public Map parseLiteral(Object input) throws CoercingParseLiteralException {
Map map;
try {
map = (Map) input;
} catch (ClassCastException exception) {
throw new CoercingParseLiteralException("parseLiteral called");
}
return map;
}
});

扩展类型定义

scalar Short
scalar Byte
scalar Map

schema {
query: Query
mutation: Mutation
}

type Person {
id: Int
extras: [Map!]
img: Short
type: Byte
}

GraphQL调用

@Service
@Slf4j
public class GraphQLFetchService {
@Autowired
GraphQL graphQL;

public Map<String, Object> executeGraphQL(ExecutionInput executionInput) {

//执行ql
CompletableFuture<ExecutionResult> resultCompletableFuture = graphQL.executeAsync(executionInput);

Map<String, Object> resultMap = null;
try {
ExecutionResult executionResult = resultCompletableFuture.get();

resultMap = getExecutionResult(executionResult);

} catch (Exception e) {
log.error("error", e);
}

return resultMap;
}

public Map<String, Object> getExecutionResult(ExecutionResult executionResult) {
return executionResult.toSpecification();
}

public CompletableFuture<ExecutionResult> executeGraphQLCompletionStage(ExecutionInput executionInput) {
//执行ql
return graphQL.executeAsync(executionInput);
}
}

DataFetcher定义

public DataFetcher find(ILoader loader, String idName){
return new AsyncDataFetcher(environment -> {
//标识名称
String id = environment.getArgument(idName);
Integer version = environment.getArgument("version");

Map<String, Object> map = new HashMap<>();
map.put(idName, id);

return map;
}, ThreadPool.dataPool);
}
------ 本文结束------

本文标题:GraphQL服务实现

文章作者:Perkins

发布时间:2020年09月01日

原始链接:https://perkins4j2.github.io/posts/522360011/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK