带有 Netflix DGS 和 Spring Boot 的 GraphQL 服务器
*定义*: GraphQL 是一种用于 API 的查询语言,也是一种使用现有数据完成这些查询的运行时。GraphQL 为您的 API 中的数据提供了完整且易于理解的描述,使客户能够准确地询问他们需要什么,仅此而已,使 API 更容易随着时间的推移而发展,并支持强大的开发人员工具。
什么是 Netflix DGS?
Netflix DGS (Domain Graph Service) 是一个基于 Spring Boot 用 Kotlin 编写的 GraphQL 服务器框架,旨在将 Spring 框架之外的外部依赖降至最低。
DGS 还附带了代码生成插件,用于从 GraphQL Schema 生成 Java 或 Kotlin 代码。
GraphQL API 开发
GraphQL API 开发有以下两种方法
- Schema First API 开发*:这里我们使用 GraphQL 模式文件定义 API,并为 Query/Mutation*操作提供服务实现。
- Code First API 开发*:与上面相反,这里 GraohQL 模式是在运行时从代码定义生成的。*
Netflix DGS 更喜欢 Schema-first 开发而不是 code-first 方法。
GraphQL Schema Types(来自 GraphQL — 不特定于 DGS)
- 查询类型:定义只读操作(例如:GET)
- 突变类型:定义数据更改操作(例如:PUT、POST、DELETE、PATCH)
- 输入类型:定义用户定义的 json 类型,用作 Query/Mutation 操作的请求参数。
- 输出类型:定义用户定义的 json 类型,用作 Query/Mutation 操作的响应类型。
- 枚举类型:定义常量 — 可用于输入/输出类型中的属性。
- 标量类型:所有 GraphQL 默认基元类型都被视为标量。
- 接口类型:我们可以使用接口类型作为响应参数。
让我们从一个简单的例子开始:
[Spring初始化器Initializr 使用您快速启动所需的内容生成 spring boot 项目!start.spring.io](https://start.spring.io/#!type=maven-project&language=kotlin&platformVersion=2.4.5.RELEASE&packaging=jar&jvmVersion=11&groupId=com.shashir&artifactId=graphql-netflixdgs-springboot-app&name=graphql-netflixdgs-springboot-app&description=Build GraphQL server with Netflix DGS framework and Spring Boot&packageName=com.shashir.graphql-netflixdgs-springboot-app&dependencies=lombok,web,data-mongodb)
DGS 框架依赖项:(超链接附加)
- 马文:
<dependency>
<groupId>com.netflix.graphql.dgs</groupId>
<artifactId>graphql-dgs-spring-boot-starter</artifactId>
<!-- Set the latest framework version! -->
<version>3.11.0</version>
</dependency>
- 摇篮:
repositories {
mavenCentral()
}dependencies {
implementation "com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:latest.release"
}
- Gradle + Kotlin:
repositories {
mavenCentral()
}dependencies {
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:latest.release")
}
让我们从 GraphQL 模式文件开始
在这里,我们使用几个模型对象——Account 和 Customer 来理解一些 GraphQL 概念及其在我们有多个具有休眠映射的实体时的用法。
这里我们有 Query、Mutation、Input、Enum 和 Scalar 类型
type Query {
customers: [Customer]
}
type Mutation {
customer(customerInput: CustomerInput): Customer
}
type Customer {
customerNumber: String!
name: String!
gender: String!
contact: Int!
mail: String
accounts: [Account]
}
type Account {
accountId: String
accountNumber: Int
accountStatus: AccountStatus
accountBalance: Float
}
input CustomerInput {
name: String!
gender: String!
contact: Int!
mail: String
accounts: [AccountInput]
}
input AccountInput {
accountNumber: Int
accountStatus: AccountStatus
accountBalance: Float
}
enum AccountStatus {
Active, Inactive, Closed
}
使用 @DgsComponent 实现数据提取器
@DgsComponent — 它的作用类似于 @RestController 注释。
@DgsComponent
public class CustomerDataFetcher {
@Autowired
CustomerRepository customerRepository;
@Autowired
AccountRepository accountRepository; @DgsData methods @DgsMutation methods @DgsQuery methods
}
*带有 @DgsQuery 和 @DgsData 注释的 GraphQL 查询*
*@DgsQuery* — 与 ‘@GetMapping’ 注释相同
它是一个方法级别的注释,用于使该方法成为数据提取器。它只有一个参数——“字段”。它将用于执行获取操作。
这里的 parentType 是“Query”——派生自注解本身和“field”——如果指定从提供的值中选取,否则它将派生自方法名称。
@DgsQuery(field = "customers")
public List<Customer> customers() {
return customerRepository.findAll();
}
***@DgsData —***与 ‘@RequestMapping’ 注释相同
它是一个方法级别的注释,用于使该方法成为数据提取器。它有两个参数——“parentType”和“field”。
- parentType — 它是一个包含字段的类型。
- field — 表示 datafetcher 负责的字段。
这里要注意,参数’field’是一个可选参数,它会从方法名派生而来。
我们不能在单个方法中定义@DgsQuery 和@DgsMutation,而是可以将@DgsData 与parentType 一起使用为’Query’ 或’Mutation’。
@DgsData(parentType = "Query", field = "customers")
public List<Customer> customers() {
return customerRepository.findAll();
}@DgsData(parentType = "Customer", field = "accounts")
public List<Account> accounts(DgsDataFetchingEnvironment dgsDataFetchingEnvironment) {
Customer customer = dgsDataFetchingEnvironment.getSource();
List<Account> accountList = new ArrayList<>();
for (Account account : customer.getAccounts()) {
Account accountResponse = accountRepository.findById(account.getAccountId()).get();
accountList.add(accountResponse);
}
return accountList;
}
*带有@DgsMutation 注解的GraphQL Mutation*
***@DgsMutation —***与 ‘@PostMapping、@PutMapping、@DeleteMapping’ 注释相同
它是一个方法级别的注释,用于使该方法成为数据提取器。它只有一个参数——“字段”。它将用于执行持久化/更新/删除操作。
这里的 parentType 是“Mutation”——派生自注解本身和“field”——如果指定从提供的值中选取,否则它将派生自方法名称。
@DgsMutation
public Customer customer(CustomerInput customerInput) {
Customer customer = Customer.builder()
.contact(customerInput.getContact())
.name(customerInput.getName())
.gender(customerInput.getGender())
.mail(customerInput.getMail())
.accounts(mapCustomerAccounts(customerInput.getAccounts()))
.build();
Customer customerResponse = customerRepository.save(customer);
return customerResponse;
}
让我们从 GraphiQL Web 控制台开始测试应用程序:
模型类——账户
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "account")
public class Account { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String accountId;
private Long accountNumber;
private String accountStatus;
private Double accountBalance;
}
模型类——客户
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Customer")
public class Customer { @Id
@Column(name = "CUSTOMER_NUMBER")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String customerNumber;
private String name;
private String gender;
private Long contact;
private String mail; @OneToMany(cascade = CascadeType.ALL)
private List<Account> accounts;
}
JPA 存储库 - 帐户和客户
@Repository
public interface CustomerRepository extends JpaRepository<Customer, String> {}@Repository
public interface AccountRepository extends JpaRepository<Account, String> {}
让我们从 GraphiQL Web 控制台开始测试应用程序:
通过选择“CustomerMutation”,我们正在执行 POST 操作,该操作会进入我们的 H2 数据库。
通过选择“CustomerQuery”,我们正在执行 GET 操作,我们正在从 H2 数据库中获取所有客户。
从 Netflix DGS 的基础知识开始,以及如何使用它来编写 GraphQL 组件以及如何使用它来实现查询和变异,并通过一个示例从 H2 DB 中持久化和读取数据。
上述示例的完整代码可以在 GitHub 上找到
https://github.com/shashirl9/neflixdgs-graphql-javaapp
https://github.com/Netflix/dgs-framework/blob/master/CONTRIBUTING.md
- 原文作者:知识铺
- 原文链接:https://geek.zshipu.com/post/graphql/%E5%B8%A6%E6%9C%89-Netflix-DGS-%E5%92%8C-Spring-Boot-%E7%9A%84-GraphQL-%E6%9C%8D%E5%8A%A1%E5%99%A8/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com