GraphQL入门和结合MyBatis使用

在当今的软件开发领域,API 已经成为了连接不同系统和应用之间的重要桥梁。随着技术的不断发展和创新,API 的设计和使用方式也在不断演变。其中,GraphQL 作为一种新兴的 API 查询语言,引起了广泛的关注和讨论。那么,我们是否一定要学习 GraphQL 呢?本文将从多个角度探讨 GraphQL 的学习必要性和应用场景,帮助大家更好地理解和评估 GraphQL 的价值。

GraphQL 与传统 API 的区别

GraphQL 和传统 REST API 在设计和功能方面存在显著的差异。首先,GraphQL 是一种查询语言,而 REST 是一种基于网络的软件架构概念。它们在处理客户端与服务器间数据请求的方式上也存在很大的不同。

在传统的 RESTful 架构下,后端开发人员定义在各个 URL 的资源上返回的数据,而不是由前端开发人员来提出数据需求。这经常会导致前端需要请求一个资源中所有的信息,即便实际上只需要其中的一部分数据,这种问题被称为过度获取(overfetching)。此外,多个客户端应用可能需要请求多个资源,从而发起多个网络请求,这不仅会造成过度获取的问题,也会导致瀑布式的网络请求(waterfall network requests)。

相比之下,GraphQL 提供了一种更灵活的数据查询方式。它允许客户端精确地指定所需的数据,避免了过度请求和数据冗余的问题。此外,GraphQL 支持嵌套查询和关联查询,使得数据的获取更加灵活和高效。而且,GraphQL 的设计原则是渐进式的改进其 API,无论是添加新 API 或是新增字段,对现有用户都是无感知的,无需划分版本并打断使用旧版本 API 的用户。

使用

graphql-java是GraphQL的java实现形式。graphql-java-spring-boot-starter-webmvc是为了支持SpringWeb方式请求。
而graphql-java-kickstart是在这之上,不仅包含graphql-java,还有graphql-java-tools、graphql-java-servlet。支持了图形界面,我们只需要引入这一个依赖就可以了。

  <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-spring-boot-starter</artifactId>
            <version>15.1.0</version>
        </dependency>

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

增加配置:

spring:
  graphql:
    graphiql:
      enabled: true

写一个查询书和作者的api

public class Book {

    private String id;
    private String name;
    private int pageCount;
    private String authorId;

    public Book(String id, String name, int pageCount, String authorId) {
        this.id = id;
        this.name = name;
        this.pageCount = pageCount;
        this.authorId = authorId;
    }

    private static List<Book> books = Arrays.asList(
            new Book("book-1", "第1部", 223, "author-1"),
            new Book("book-2", "第2部", 635, "author-2"),
            new Book("book-3", "第3部", 371, "author-3")
    );

    public static Book getById(String id) {
        return books.stream().filter(book -> book.getId().equals(id)).findFirst().orElse(null);
    }

    public String getId() {
        return id;
    }

    public String getAuthorId() {
        return authorId;
    }
}
public class Author {
    private String id;
    private String firstName;
    private String lastName;

    public Author(String id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    private static List<Author> authors = Arrays.asList(
            new Author("author-1", "Joanne", "Rowling"),
            new Author("author-2", "Herman", "Melville"),
            new Author("author-3", "Anne", "Rice")
    );

    public static Author getById(String id) {
        return authors.stream().filter(author -> author.getId().equals(id)).findFirst().orElse(null);
    }

    public String getId() {
        return id;
    }
}

创建和编辑文件schema.graphqls:

Query {
  bookById(id: ID): Book
}

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

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

创建book api:

@Controller
public class BookController {

    @QueryMapping
    public Book bookById(@Argument String id) {
        return Book.getById(id);
    }

    @SchemaMapping
    public Author author(Book book) {
        return Author.getById(book.getAuthorId());
    }
}

其中,@QueryMapping标注的方法需要和schema.graphqls中Query中的方法一致,带有 @SchemaMapping 注解的方法则成为查询嵌套字段的处理程序。这意味着,当你需要对某个字段进行更深层次的操作时,就可以使用 @SchemaMapping
此时,我们打开http://localhost:8080/graphiql?path=/graphql,进行查询:

和MyBatis plus集成

在国内大多数场景中,开发者一般会选择使用 MyBatis 或者 MyBatis Plus 生态进行数据操作,而不是选择使用 JPA。
我们在 GraphQL Resolver 中,通过 @Autowired 注入对应的 MyBatis Service,并调用其方法来获取数据。
先引入mybatis plus:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本号</version>
</dependency>

例如,假设有一个 UserService 类,用于处理用户相关的操作:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public List<User> getAllUsers() {
        return userMapper.selectAllUsers();
    }
}

然后在 GraphQL Resolver 中注入 UserService,并调用其方法:

@Component
public class UserQuery implements GraphQLQueryResolver {
    @Autowired
    private UserService userService;

    @Override
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }
}

这样,在执行 GraphQL 查询时,就可以通过 UserQuery 类的 getAllUsers() 方法获取所有用户的数据了。

你可能感兴趣的:(graphql,mybatis,后端)