在 Spring Boot 项目中实现对 GraphQL 的支持,可借助 Spring GraphQL 库,以下是详细步骤:

1. 添加依赖

若使用 Maven,需在 pom.xml 里添加如下依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-graphql</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

spring-boot-starter-graphql 为项目提供 GraphQL 支持,spring-boot-starter-web 则提供 Web 服务能力。

2. 定义 GraphQL Schema

src/main/resources 目录下创建 schema.graphqls 文件,用于定义 GraphQL Schema。示例如下:

type Query {
    bookById(id: ID!): Book
}

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

上述代码定义了一个查询 bookById,用于依据 ID 查询书籍信息,同时定义了 Book 类型。

3. 创建实体类

创建与 GraphQL Schema 对应的 Java 实体类:

public class Book {
    private String id;
    private String name;
    private int pageCount;
    private String author;

    // 构造函数、getter 和 setter 方法
    public Book(String id, String name, int pageCount, String author) {
        this.id = id;
        this.name = name;
        this.pageCount = pageCount;
        this.author = author;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPageCount() {
        return pageCount;
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

4. 创建 DataFetcher

DataFetcher 负责从数据源获取数据。创建一个 BookDataFetcher 类:

import graphql.schema.DataFetcher;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class BookDataFetcher {
    private static final Map<String, Book> books = new HashMap<>();

    static {
        Book book1 = new Book("book-1", "Effective Java", 416, "Joshua Bloch");
        Book book2 = new Book("book-2", "Java Concurrency in Practice", 336, "Brian Goetz");
        books.put(book1.getId(), book1);
        books.put(book2.getId(), book2);
    }

    public DataFetcher<Book> getBookById() {
        return dataFetchingEnvironment -> {
            String bookId = dataFetchingEnvironment.getArgument("id");
            return books.get(bookId);
        };
    }
}

5. 创建 GraphQL 配置类

创建一个配置类,将 DataFetcher 注册到 GraphQL 执行环境中:

import graphql.schema.DataFetcher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;

@Configuration
public class GraphQLConfig {
    private final BookDataFetcher bookDataFetcher;

    public GraphQLConfig(BookDataFetcher bookDataFetcher) {
        this.bookDataFetcher = bookDataFetcher;
    }

    @Bean
    public RuntimeWiringConfigurer runtimeWiringConfigurer() {
        return wiringBuilder -> wiringBuilder
              .type("Query", typeWiring -> typeWiring
                      .dataFetcher("bookById", bookDataFetcher.getBookById()));
    }
}

6. 测试 GraphQL 接口

启动 Spring Boot 项目后,可借助 GraphQL 客户端(如 Altair、GraphiQL)来测试 GraphQL 接口。发送如下查询:

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

以下是完整代码示例,将以 doubaocanvas 形式呈现:

pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-graphql</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>    

schema.graphqls

type Query {
    bookById(id: ID!): Book
}

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

Book.java

public class Book {
    private String id;
    private String name;
    private int pageCount;
    private String author;

    // 构造函数、getter 和 setter 方法
    public Book(String id, String name, int pageCount, String author) {
        this.id = id;
        this.name = name;
        this.pageCount = pageCount;
        this.author = author;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPageCount() {
        return pageCount;
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}    

BookDataFetcher.java

import graphql.schema.DataFetcher;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class BookDataFetcher {
    private static final Map<String, Book> books = new HashMap<>();

    static {
        Book book1 = new Book("book-1", "Effective Java", 416, "Joshua Bloch");
        Book book2 = new Book("book-2", "Java Concurrency in Practice", 336, "Brian Goetz");
        books.put(book1.getId(), book1);
        books.put(book2.getId(), book2);
    }

    public DataFetcher<Book> getBookById() {
        return dataFetchingEnvironment -> {
            String bookId = dataFetchingEnvironment.getArgument("id");
            return books.get(bookId);
        };
    }
}    

GraphQLConfig.java

import graphql.schema.DataFetcher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;

@Configuration
public class GraphQLConfig {
    private final BookDataFetcher bookDataFetcher;

    public GraphQLConfig(BookDataFetcher bookDataFetcher) {
        this.bookDataFetcher = bookDataFetcher;
    }

    @Bean
    public RuntimeWiringConfigurer runtimeWiringConfigurer() {
        return wiringBuilder -> wiringBuilder
              .type("Query", typeWiring -> typeWiring
                      .dataFetcher("bookById", bookDataFetcher.getBookById()));
    }
}