原文地址java
GraphQL 是一種用於 API 的查詢語言,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘。GraphQL是一種強類型協議,全部數據操做都會根據 GraphQL Schema 來進行校驗。git
建立示例Spring Boot應用程序並添加如下依賴項。github
graphql-spring-boot-starterweb
用於啓用 GraphQL 控制器,並使其在 path/graphql 中可用。它將初始化GraphQL Schema bean。
複製代碼
graphql-javaspring
可使用易於理解的Graphql Schema 語言來編寫 schema。
複製代碼
graphiql-spring-boot-starterapache
提供圖形界面,咱們可使用它來測試 GraphQL 查詢和查看查詢定義。
複製代碼
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
複製代碼
如下完整的POM文件內容。瀏覽器
<?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>com.techshard.graphql</groupId>
<artifactId>springboot-graphql</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
複製代碼
接下來讓咱們建立一個名爲Vehicle的簡單實體和相應的JPA存儲庫。咱們將使用Lombok來編寫,這樣能夠避免編寫諸如getter和setter等等的樣板文件。springboot
package com.techshard.graphql.dao.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDate;
@Data
@EqualsAndHashCode
@Entity
public class Vehicle implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "type", nullable = false)
private String type;
@Column(name = "model_code", nullable = false)
private String modelCode;
@Column(name = "brand_name")
private String brandName;
@Column(name = "launch_date")
private LocalDate launchDate;
private transient String formattedDate;
// Getter and setter
public String getFormattedDate() {
return getLaunchDate().toString();
}
}
複製代碼
而後是相應的JPA存儲庫。bash
package com.techshard.graphql.dao.repository;
import com.techshard.graphql.dao.entity.Vehicle;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface VehicleRepository extends JpaRepository<Vehicle, Integer> {
}
複製代碼
GraphQL 用有本身的獨特語言來編寫GraphQL Schema,稱爲Schema Definition Language(SDL)。schema 的定義,是由端點上全部可用的 API 功能組成的。服務器
GraphQL架構的典型示例以下所示:
type Vehicle {
id: ID!,
type: String,
modelCode: String,
brandName: String,
launchDate: String
}
type Query {
vehicles(count: Int):[Vehicle]
vehicle(id: ID):Vehicle
}
type Mutation {
createVehicle(type: String!, modelCode: String!, brandName: String, launchDate: String):Vehicle
}
複製代碼
接下來,在 src/main/resources 下建立一個文件夾,名爲 graphql,並在該文件夾下建立vehicleql.graphqls文件。複製上面的內容並將其粘貼到vehicleql.graphqls文件中。須要注意的是,文件名稱是可自定義的。以.graphqls做爲文件擴展名便可。
在上面的 schema 中,每一個對象都是用類型定義的。 GraphQL 中的類型系統是最基本的組件,它表示能夠從服務獲取的對象以及該對象所包含的字段。
在咱們的 schema 中,咱們有一個名爲 Vehicle 的對象,做爲域對象。 Query 類型表示可經過 GraphQL 服務器獲取數據的查詢。query 是交互式的,可修改,修改後便可看到新的結果。query 和結果的結構是同樣的。這一點在 GraphQL 中很重要,由於所見即所得。
在稍後的文章中,咱們能夠看到一些真正運行的例子。
Mutation 類型用來表示那些用於對數據執行寫入操做的 query。
Query 或 Mutation對象是基本 GraphQL 對象,它們沒有任何關聯的數據類。在這種狀況下,解析器類將實現 GraphQLQueryResolver 或 GraphQLMutationResolver。These resolvers will be searched for methods that map to fields in their respective root types.(這段不是很懂,因此先貼原文)
接下來,讓咱們爲Vehicle定義根解析器。
package com.techshard.graphql.query;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class VehicleQuery implements GraphQLQueryResolver {
@Autowired
private VehicleService vehicleService;
public List<Vehicle> getVehicles(final int count) {
return this.vehicleService.getAllVehicles(count);
}
public Optional<Vehicle> getVehicle(final int id) {
return this.vehicleService.getVehicle(id);
}
}
複製代碼
在這個類中,咱們有方法來獲取單個Vehicle對象和Vehicle對象列表。請注意,咱們在上面的模式中定義了這些方法。
如今,讓咱們定義一個Mutation解析器。
package com.techshard.graphql.mutation;
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.service.VehicleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
@Component
public class VehicleMutation implements GraphQLMutationResolver {
@Autowired
private VehicleService vehicleService;
public Vehicle createVehicle(final String type, final String modelCode, final String brandName, final String launchDate) {
return this.vehicleService.createVehicle(type, modelCode, brandName, launchDate);
}
}
複製代碼
在這個類中,咱們只有一個方法來建立一個Vehicle對象,這對應於咱們的模式定義中的Mutation類型。
咱們如今將定義一個能夠進行實際交互的服務。
package com.techshard.graphql.service;
import com.techshard.graphql.dao.entity.Vehicle;
import com.techshard.graphql.dao.repository.VehicleRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class VehicleService {
private final VehicleRepository vehicleRepository ;
public VehicleService(final VehicleRepository vehicleRepository) {
this.vehicleRepository = vehicleRepository ;
}
@Transactional
public Vehicle createVehicle(final String type,final String modelCode, final String brandName, final String launchDate) {
final Vehicle vehicle = new Vehicle();
vehicle.setType(type);
vehicle.setModelCode(modelCode);
vehicle.setBrandName(brandName);
vehicle.setLaunchDate(LocalDate.parse(launchDate));
return this.vehicleRepository.save(vehicle);
}
@Transactional(readOnly = true)
public List<Vehicle> getAllVehicles(final int count) {
return this.vehicleRepository.findAll().stream().limit(count).collect(Collectors.toList());
}
@Transactional(readOnly = true)
public Optional<Vehicle> getVehicle(final int id) {
return this.vehicleRepository.findById(id);
}
}
複製代碼
如今,咱們能夠來測試一下這個應用了。運行Spring Boot 應用程序。在瀏覽器中打開 http//localhost8080/graphiql 連接。咱們將看到一個友好的圖形見面,以下圖所示。
在用戶界面的右側,咱們還能夠看到文檔。
如今,咱們能夠嘗試運行如下查詢。
mutation {
createVehicle(type: "car", modelCode: "XYZ0192", brandName: "XYZ", launchDate: "2016-08-16")
{
id
}
}
複製代碼
這將在Vehicle表中建立一行數據。結果爲:
{
"data": {
"createVehicle": {
"id": "1"
}
}
}
複製代碼
如今讓咱們運行查詢來獲取數據。
query {
vehicles(count: 1)
{
id,
type,
modelCode
}
}
複製代碼
而後咱們將獲得結果
{
"data": {
"vehicles": [
{
"id": "1",
"type": "bus",
"modelCode": "XYZ123"
}
]
}
}
複製代碼
請注意,咱們僅請求有限數量的字段。咱們能夠經過添加或刪除字段來更改查詢,並查看新結果。
在本文中,咱們研究了GraphQL的基本概念。查看詳細文檔。
能夠在GitHub上找到本教程的完整源代碼。