GraphQL学习,Java简单实现

2020-05-07  本文已影响0人  insomniaLee

简介

是一种查询语言,类似前端与后端之间通过sql语言进行交互。用类似json的语言来查询需要的数据。
如在以下查询语句

{
  bookById(id: "1") {
    id
    name
    pageCount
    author {
      name
    }
  }
}

可以得到一下结果

{
  "data": {
    "bookById": {
      "id": "1",
      "name": "风雪追击",
      "pageCount": 233,
      "author": {
        "name": "东野圭吾"
      }
    }
  }
}

maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java</artifactId>
    <version>11.0</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-spring-boot-starter-webmvc</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>26.0-jre</version>
</dependency>

定义schema

上面的查询语句我们事先定义了一下schema,放置在src/main/resources/schema.graphqls

type Query {
  bookById(id: ID): Book
  authors:[Author]
  books:[Book]
  authorAndBooks:[Author]
}

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

type Author {
  id: ID
  name: String
  books:[Book]
}

其中类型为Query的表示为查询,类似CURD中的R;除了Query还有Mutation来表示对数据进行修改,相当于CURD中的CUD操作。在schema中定义了4跳query语句如上所示。我们还定义了Book和Author的类型,其中Book中包含一个Author,Author中包含Book的列表。

定义GraphQLProvider

GraphQLProvider类将会创建一个GraphQL的实例,这里通过@Bean的方式暴露出去可以通过/graphql的url访问到(由依赖graphql-java-spring-boot-starter-webmvc实现的功能)

@Component
public class GraphQLProvider {

    private GraphQL graphQL;

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

    @Autowired
    GraphQLDataFetchers graphQLDataFetchers;

    @PostConstruct
    public void init() throws IOException {
        URL url = Resources.getResource("schema.graphqls");
        String sdl = Resources.toString(url, Charsets.UTF_8);
        GraphQLSchema graphQLSchema = buildSchema(sdl);
        this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
    }

    private GraphQLSchema buildSchema(String sdl) {
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }

    private RuntimeWiring buildWiring() {
        Map<String, DataFetcher> map = new HashMap<String,DataFetcher>();
        map.put("bookById",graphQLDataFetchers.getBookByIdDataFetcher());
        map.put("books",graphQLDataFetchers.getBooksDataFetcher());
        map.put("authors",graphQLDataFetchers.getAuthorsDataFetcher());
        return RuntimeWiring.newRuntimeWiring()
                .type(newTypeWiring("Query")
                        .dataFetchers(map))
                .type(newTypeWiring("Book")
                        .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher())
                        .dataFetcher("pageCount",graphQLDataFetchers.getPageCountDataFetcher()))
                .type(newTypeWiring("Author")
                        .dataFetcher("books",graphQLDataFetchers.getBooksByAUthorDataFetcher()))
                .build();
    }
}

DataFetchers

GraphQL在执行查询时,是通过Datafetcher来获取一个字段的数据。DataFetcher是一个接口

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

新建一个类用于存放所有的datafetcher(小型项目)

@Component
public class GraphQLDataFetchers {

    private static List<Map<String, String>> books = Arrays.asList(
            ImmutableMap.of("id", "1",
                    "name", "风雪追击",
                    "totalPages", "233",
                    "authorId", "a1"),
            ImmutableMap.of("id", "4",
                    "name", "解忧杂货店",
                    "totalPages", "342",
                    "authorId", "a1"),
            ImmutableMap.of("id", "2",
                    "name", "达芬奇密码",
                    "totalPages", "635",
                    "authorId", "a2"),
            ImmutableMap.of("id", "3",
                    "name", "大秦帝国",
                    "totalPages", "371",
                    "authorId", "a3")
    );

    private static List<Map<String, String>> authors = Arrays.asList(
            ImmutableMap.of("id", "a1",
                    "name", "东野圭吾"),
            ImmutableMap.of("id", "a2",
                    "name", "丹布朗"),
            ImmutableMap.of("id", "a3",
                    "name", "孙皓晖")
    );

    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);
        };
    }

    public  DataFetcher getBooksByAUthorDataFetcher(){
        return dataFetchingEnvironment -> {
            Map<String,String> author = dataFetchingEnvironment.getSource();
            String authorId = author.get("id");
            return books.stream().filter(book->book.get("authorId").equals(authorId)).toArray();
        };
    }

    public  DataFetcher getAuthorTotalCountDataFetcher(){
        return dataFetchingEnvironment -> {
            Map<String,Object> author = dataFetchingEnvironment.getSource();
            String authorId = author.get("id").toString();
            return books.stream().filter(book->book.get("authorId").equals(authorId))
                    .collect(Collectors.summingInt(map->Integer.parseInt(map.get("totalPages"))));
        };
    }

    public DataFetcher getAuthorsDataFetcher(){
        return dataFetchingEnvironment->{
            return authors;
        };
    }
    

    public DataFetcher getBooksDataFetcher(){
        return dataFetchingEnvironment -> {
            return books;
        };
    }
    
    public DataFetcher getPageCountDataFetcher() {
        return dataFetchingEnvironment -> {
            Map<String,String> book = dataFetchingEnvironment.getSource();
            return book.get("totalPages");
        };
    }
}

验证

可以使用graphql-playground工具来进行验证。我电脑的版本是macos10.15.4,使用1.8.9可以运行,1.8.10则会报错,使用前需要在顶栏输入http://localhost:8080/graphql,然后在左边输入查询语句,右边就能得到查询结果。

image.png

参考链接

java搭建graphQL demo

上一篇下一篇

猜你喜欢

热点阅读