发布于 2026-01-06 3 阅读
0

如何使用 Spring Boot 在 Java 中构建 GraphQL 服务

如何使用 Spring Boot 在 Java 中构建 GraphQL 服务

注意:请注意,本文内容现已过时,因为自 2019 年我撰写本文以来,技术已经发生了变化。

我们先快速了解一下所涉及的技术。

GraphQL

与 REST 相比,GraphQL 算是后起之秀,但我认为它的改进如此之大,以至于我打算把所有新写的 API 都迁移到它上面。我见过太多 API 返回海量数据,而用户真正需要的只是一组标识符,然后通过循环遍历这些标识符,再从第二个端点查询与这些标识符相关的其他数据,这就凸显了第二个问题。光是想想就觉得不可思议,我只想调用一次 API,就能获取所有我需要的信息。

我不会详细解释为什么 GraphQL 更好,网上有很多文章可以让你自行判断。我只想说,我决定切换到 GraphQL 的主要原因有两个:一是能够轻松地在请求中包含你想要接收的数据结构;二是能够将原本需要多个 REST 请求才能完成的任务合并成一个 GraphQL 查询。这两点都比 REST 有了巨大的改进。当然,你也可以尝试用这种方式编写 REST 端点,但那样它们就不再是 REST 了,而 GraphQL 的设计初衷就是如此。

好了,现在我们已经解决了这个问题,让我们开始编写代码吧。我们将使用Spring Boot在 Java 中构建一个简单的 GraphQL API。

Spring Boot

我之前主要用 PHP 开发,最近才发现 Spring 框架,尤其是 Spring Boot 的妙用。它让搭建新项目变得极其简单;它对如何配置和构建许多传统的样板代码(例如控制器、数据访问等)有着自己独特的见解,但当你想按照自己的方式配置时,它又会完全放手。在这个例子中,我们不需要编写任何控制器;只需要实体模型、类型和 GraphQL schema 即可。

先决条件

本项目将使用 Java 8。我尝试过 Java 10 和 9,但由于 Lombok 依赖项存在问题,本教程暂时只能使用 Java 8。问题修复后,我会更新到 Java 10。我们将使用 Spring Boot 2,它基于 Spring Framework 5,并已为您完成所有设置。为了简化操作,我们还将使用 Maven 构建框架来管理 Java 依赖项。此外,我们还将使用优秀的 GraphQL-Java 库 Spring Boot Starter 来获取 GraphQL 和 GraphIQL 端点(稍后会详细介绍)。最后,我添加了 Project Lombok,它允许您对类、方法、变量等进行注解,从而提供样板功能。

以下是我将要使用的具体版本:

我们走吧!

首先,创建一个新文件夹,然后在你选择的集成开发环境(IDE)中打开它。我用的是Microsoft Visual Studio Code。它真的是目前最好的免费代码编辑器,抱歉了,Atom。

创建一个名为 pom.xml 的新文件,并将以下内容放入其中:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>uk.co.benskin</groupId>
    <artifactId>graphql_spring_boot_tutorial</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>graphql_spring_boot_tutorial</name>
    <description>Learn how to build a graphql spring boot based java service</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>4.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
    </dependencies>
</project>
Enter fullscreen mode Exit fullscreen mode

上述文件前半部分定义了我们的项目,请将项目名称、描述等内容替换为您自己的项目详细信息。后半部分定义了六个依赖项:

  • Spring Boot Web - 提供通过 Web 协议支持我们端点的功能
  • Spring Boot DevTools——对开发、构建和调试非常有用
  • GraphQL-Java 工具 - 加载并支持我们的 GraphQL schema
  • GraphQL-Java Spring Boot Starter for GraphQL - 在我们的 Spring 上下文的 /graphql 端点托管我们的模式
  • GraphQL-Java Spring Boot Starter for GraphIQL - 一个基于 Web 的 UI,用于与 /graphql 端点交互,并了解该端点的模式。
  • Project Lombok 用于减少 Java 代码中的样板代码

请继续安装所有依赖项。

mvn install
Enter fullscreen mode Exit fullscreen mode

首次安装依赖项后,会输出一大堆信息,之后您应该会看到一条消息,内容为“构建成功”。

好了,现在我们已经准备好开始所需的一切了。

创建一个文件夹

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/
Enter fullscreen mode Exit fullscreen mode

在其中创建一个文件

GraphQLSpringBootTutorialApplication.java
Enter fullscreen mode Exit fullscreen mode

请放入以下内容

package uk.co.benskin.graphql_spring_boot_tutorial;

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

@SpringBootApplication
public class GraphQLSpringBootTutorialApplication {

    public static void main(String[] args) {
        SpringApplication.run(GraphQLSpringBootTutorialApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

这将加载一个新的 Spring 应用程序上下文,并自动将其与我们的 GraphQL-Java 启动器依赖项集成。

现在让我们尝试启动应用程序,看看会得到什么结果。

mvn spring-boot:run
Enter fullscreen mode Exit fullscreen mode

你应该会看到很多信息输出,希望其中还有几行文字说明。

INFO 64612 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
INFO 64612 --- [  restartedMain] b.g.GraphQLSpringBootTutorialApplication : Started GraphQLSpringBootTutorialApplication in 4.886 seconds (JVM
Enter fullscreen mode Exit fullscreen mode

现在打开浏览器,访问http://localhost:8080

您应该会看到类似这样的错误页面。

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

[DATE]
There was an unexpected error (type=Not Found, status=404).
No message available
Enter fullscreen mode Exit fullscreen mode

很好!服务器正在运行,但我们还没有告诉它如何响应根目录“/”的请求,所以现在尝试访问http://localhost:8080/graphiql,你应该会看到一个漂亮的界面,用于与你的(尚未构建的)端点进行交互。

构建 GraphQL Schema

现在到了有趣的部分,GraphQL schema。我不会详细介绍 GraphQL 的工作原理,请参考 GraphQL 教程。

创建此文件

src/main/resources/petshop.graphqls
Enter fullscreen mode Exit fullscreen mode

然后将以下内容填入

type Query {
    pets: [Pet]
}

type Pet {
    id: Int
    type: Animal
    name: String
    age: Int
}

enum Animal {
    DOG
    CAT
    BADGER
    MAMMOTH
}
Enter fullscreen mode Exit fullscreen mode

上面我们定义了主查询,它将返回一个名为“pets”的宠物类型数组。宠物的类型是一个枚举类型,其定义如下,枚举类型为Animal。

构建 API

现在回到 Java 代码部分。我们将创建几个文件夹来帮助我们组织代码。文件夹的名称和位置没有限制,但我强烈建议您使用子文件夹来更好地组织代码,无数未来的开发者都会感谢您的。

创建此文件夹

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/enums
Enter fullscreen mode Exit fullscreen mode

创建此文件

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/enums/Animal.java
Enter fullscreen mode Exit fullscreen mode

以下是内容

package uk.co.benskin.graphql_spring_boot_tutorial.enums;

public enum Animal {
    DOG,
    CAT,
    BADGER,
    MAMMOTH
}
Enter fullscreen mode Exit fullscreen mode

枚举类型定义完毕,现在来看宠物实体模型。

创建此文件夹

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/entities
Enter fullscreen mode Exit fullscreen mode

创建此文件

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/entities/Pet.java
Enter fullscreen mode Exit fullscreen mode

以下是内容

package uk.co.benskin.graphql_spring_boot_tutorial.entities;

import lombok.Data;
import uk.co.benskin.graphql_spring_boot_tutorial.enums.Animal;

@Data
public class Pet {
    private long id;

    private String name;

    private Animal type;

    private int age;
}
Enter fullscreen mode Exit fullscreen mode

这是一个简单的 POJO,使用 @Data 注解来处理样板式的 getter、setter 和构造函数。

现在创建 GraphQL 解析器的目录

src/main/java/uk/co/benskin/graphql-spring-boot-tutorial/resolvers
Enter fullscreen mode Exit fullscreen mode

并创建文件

src/main/java/uk/co/benskin/graphql_spring_boot_tutorial/resolvers/Query.java
Enter fullscreen mode Exit fullscreen mode

然后把它填满这个

package uk.co.benskin.graphql_spring_boot_tutorial.resolvers;

import java.util.ArrayList;
import java.util.List;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import org.springframework.stereotype.Component;
import uk.co.benskin.graphql_spring_boot_tutorial.entities.Pet;
import uk.co.benskin.graphql_spring_boot_tutorial.enums.Animal;

@Component
public class Query implements GraphQLQueryResolver {

    public List<Pet> pets() {
        List<Pet> pets = new ArrayList<>();

        Pet aPet = new Pet();
        aPet.setId(1l);
        aPet.setName("Bill");
        aPet.setAge(9);
        aPet.setType(Animal.MAMMOTH);

        pets.add(aPet);

        return pets;
    }
}
Enter fullscreen mode Exit fullscreen mode

好了,这就是调用 GraphQL 端点获取宠物列表(本例中为一只宠物)所需的一切信息。

停止 Maven(Ctrl/Cmd + C)然后使用 `mvn spring-boot:run` 重新启动构建。

要查看运行效果,请访问http://localhost:8080/graphiql,您将看到一个友好的用户界面供您体验。同样,我不会详细介绍如何使用 GraphIQL 界面。

在 GraphIQL 标题正下方、历史记录框右侧的框中,您可以输入请求。请将以下内容复制并粘贴到此处:

{
    pets {
        name
        age
        type
    }
}
Enter fullscreen mode Exit fullscreen mode

然后点击播放图标(位于 GraphIQL 标题旁边)。您应该会看到类似如下的响应:

{
    "data": {
        "pets": [
            {
                "name": "Bill",
                "age": 9,
                "type": "MAMMOTH"
            }
        ]
    }
}
Enter fullscreen mode Exit fullscreen mode

恭喜!您刚刚用 Java 和 SpringBoot 编写了一个 GraphQL 服务。好的,它目前只会返回一条记录,所以在第二部分中,我们将介绍如何通过Spring Data项目访问数据库,该项目利用了 Java 持久化 API (JPA)。

非常感谢您阅读这篇文章!如果您喜欢这篇文章,请留言告诉我您的想法,或者提出任何改进建议;也别忘了点击下方的爱心/独角兽/收藏按钮,您的支持对我意义重大 :)

文章来源:https://dev.to/sambanskin/howto-build-graphql-services-in-java-with-spring-boot---part-1-38b2