Initial learning of GraphQL interface query language

A query language for your API

Recently, the company often uses this thing. I learned something out of interest, and recorded it as follows. If anything is wrong, I hope you can give me more advice.

I. Overview

GraphQL is a query language for api, a way to query existing data when the project is running. GraphQL provides a complete and understandable description of the data in the API, allows clients to ask for what they really need, makes the API easier to evolve over time, and supports powerful development tools.

APIJson can be compared at the same level. I personally feel that apiJson is more practical and simple in Java development. For example, permission verification can add role to table operation permissions through @ MethodAccess annotation Model, and support remote function calls. In contrast, graphql learning difficulty and cost And the standard is relatively high. But if you have too much skill, let's take a look today.
(APIjson personal feeling can refer to the blog, I feel pretty good https://blog.csdn.net/u014618954/article/details/107021638/)

Two preliminary display

Graphql is an api query language, which makes development more efficient and convenient to a certain extent. The following is an example.
For example, a GraphQL service users who log on to tell us (me) as well as the user's name might look like this:
① create
defined types and fields on these types and provides functions of each type for each field.

type Query {
  me: User
}
 
type User {
  id: ID
  name: String
}
function Query_me(request) {
  return request.auth.user;
}
 
function User_name(user) {
  return user.getName();
}

②Query

{
  me {
    name
  }
}

③Back

{
  "me": {
    "name": "Luke Skywalker"
  }
}

The above is a query query, you can query all the names of the corresponding names according to the name, as well as the advantages of querying by type, multiple parameters, etc., not much to say, you can refer to the official document of graphql. The simple explanation is divided into three points, as follows.

Application scenarios :
①Field redundancy due to multiple platforms and other reasons
②Multiple calls to aggregate data on one page
③Frequent interface changes and simplified logic

Three practical applications

After talking about it for a long time, let’s get some dry goods. This time we demonstrate the basic use of Java and go.

3.1 java+spring boot+graphql

Our sample application will be a simple API to get the detailed information of a specific book.

① Build the directory

Select:
	Gradle Project
	Java
	Spring Boot 2.1.x
Project metadata
	Group: com.graphql-java.tutorial
	Artifact: book-details
Dependency
	web

② Add basic dependencies


com.graphql-java:graphql-java:11.0 // NEW
com.graphql-java:graphql-java-spring-boot-starter-webmvc:1.0 // NEW
com.google.guava:guava:26.0-jre // NEW
org.springframework.boot:spring-boot-starter-web
org.springframework.boot:spring-boot-starter-test
}

③ Create related files
Create schema.graphqls in the src/main/resources directory

//该部分是一个关于书籍的基本类型的定义,并与后续类型的查询有关
type Query {
  bookById(id: ID): Book 
}

type Book {
  id: ID
  name: String
  pageCount: Int
  author: Author
}

type Author {
  id: ID
  firstName: String
  lastName: String
}

Create GraphQLProvider.class in the com.graphqljava.tutorial.bookdetails directory, and create a GraphQL instance:

@Component
public class GraphQLProvider {

    private GraphQL graphQL;

    @Bean
    public GraphQL graphQL() { 
        return graphQL;
      //  这个GraphQL实例通过使用@Bean注释的GraphQL()方法公开为一个Spring Bean
    }

    @PostConstruct
    public void init() throws IOException {
   		 //使用Guava资源从类路径读取文件
        URL url = Resources.getResource("schema.graphqls");
        //GraphQL Java Spring适配器将使用该GraphQL实例使我们的模式通过HTTP在默认url / 
        String sdl = Resources.toString(url, Charsets.UTF_8);
        //创建一个GraphQLSchema和GraphQL实例
        GraphQLSchema graphQLSchema = buildSchema(sdl);
        this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
    }

    @Autowired
    GraphQLDataFetchers graphQLDataFetchers;

	//抓取数据
    private GraphQLSchema buildSchema(String sdl) {
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }
    
	/*buildWiring使用graphQLDataFetchers bean实际注册两个DataFetchers:
	一个用于检索具有特定ID的图书
	一个用于获取特定书籍的作者*/
	
    private RuntimeWiring buildWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type(newTypeWiring("Query")
                        .dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher()))
                .type(newTypeWiring("Book")
                        .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher()))
                .build();
    }
}

Important interface (do not create your own):
DataFetcher is an interface with a single method, it only accepts a single parameter of type DataFetcherEnvironment;
when GraphQL Java executes a query, it will call the appropriate for each field encountered in the query Data table device.

public interface DataFetcher<T> {
    T get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception;
}

Let us assume that there is a mismatched book mapping that has a key totalPages instead of pageCount. This will result in an empty pageCount value for each book, because PropertyDataFetcher cannot get the correct value. In order to solve this problem, you must register a new DataFetcher for Book (not needed in this case)

 // 在 GraphQLDataFetchers class
    // 实现 DataFetcher
    public DataFetcher getPageCountDataFetcher() {
        return dataFetchingEnvironment -> {
            Map<String,String> book = dataFetchingEnvironment.getSource();
            return book.get("totalPages");
        };
    }

Create a new class GraphQLDataFetchers, which contains a list of examples of books and authors

@Component
public class GraphQLDataFetchers {

    private static List<Map<String, String>> books = Arrays.asList(
            ImmutableMap.of("id", "book-1",
                    "name", "Harry Potter and the Philosopher's Stone",
                    "pageCount", "223",
                    "authorId", "author-1"),
            ImmutableMap.of("id", "book-2",
                    "name", "Moby Dick",
                    "pageCount", "635",
                    "authorId", "author-2"),
            ImmutableMap.of("id", "book-3",
                    "name", "Interview with the vampire",
                    "pageCount", "371",
                    "authorId", "author-3")
    );

    private static List<Map<String, String>> authors = Arrays.asList(
            ImmutableMap.of("id", "author-1",
                    "firstName", "Joanne",
                    "lastName", "Rowling"),
            ImmutableMap.of("id", "author-2",
                    "firstName", "Herman",
                    "lastName", "Melville"),
            ImmutableMap.of("id", "author-3",
                    "firstName", "Anne",
                    "lastName", "Rice")
    );

    public DataFetcher getBookByIdDataFetcher() {
        return dataFetchingEnvironment -> {
            String bookId = dataFetchingEnvironment.getArgument("id");
            return books
                    .stream()
                    .filter(book -> book.get("id").equals(bookId))
                    .findFirst()
                    .orElse(null);
        };
    }

    public DataFetcher getAuthorDataFetcher() {
        return dataFetchingEnvironment -> {
            Map<String,String> book = dataFetchingEnvironment.getSource();
            String authorId = book.get("authorId");
            return authors
                    .stream()
                    .filter(author -> author.get("id").equals(authorId))
                    .findFirst()
                    .orElse(null);
        };
    }
}

Add the main method of application to start the project test

package com.graphqljava.tutorial.bookdetails;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BookDetailsApplication {

    public static void main(String[] args) {
        SpringApplication.run(BookDetailsApplication.class, args);
    }

}

The results can be obtained
Insert picture description here
clearly through the web version test https://cpq-dev.ext.hp.com/playground
(the playground can install the corresponding test software, such as postman, altair, this article uses the web version, if any For questions, please refer to the source code: https://github.com/graphql-java/tutorials)

3.2 Golang + graphql

① Install corresponding support

go get github.com/graphql-go/graphql

(This directory is under the path directory. There was a problem with the guide package in the previous blog. You can browse it. If you don’t know the path directory of your project, you can use the go Current GOPATH command to find it)

② Application example
The following is a simple example, which defines a pattern with a hello string type field and a Resolve method that returns the string world. Execute GraphQL query on this mode, and print the result output in JSON format

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/graphql-go/graphql"
)

func main() {
	// Schema
	fields := graphql.Fields{
		"hello": &graphql.Field{
			Type: graphql.String,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return "world", nil
			},
		},
	}
	rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
	schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
	schema, err := graphql.NewSchema(schemaConfig)
	if err != nil {
		log.Fatalf("failed to create new schema, error: %v", err)
	}

	// Query
	query := `
		{
			hello
		}
	`
	params := graphql.Params{Schema: schema, RequestString: query}
	r := graphql.Do(params)
	if len(r.Errors) > 0 {
		log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
	}
	rJSON, _ := json.Marshal(r)
	fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}}
}

The above is a simple example. For more interesting and complex case recommendations, please go to
https://github.com/graphql-go/graphql/tree/master/examples/
https://github.com/graphql-go/graphql/blob/master /graphql_test.go learn

I also have a preliminary study of graphql, and I also hope that the big guys can give more suggestions

This article refers to learning from
https://graphql.org/ official website and related git source code

Personal recommendation https://blog.csdn.net/qq_41882147/article/details/82966783, very detailed, the introduction is also more practical, suitable for advanced learning

Guess you like

Origin blog.csdn.net/MatChen/article/details/111516086