发布于2021-05-29 21:38 阅读(538) 评论(0) 点赞(16) 收藏(2)
说实话,网上这玩意资料太少了,用的人也挺少的,不是因为技术需求,估计大家都不会想用,这次来把这个小东西稍微记录一下
官方解释:一种用于 API 的查询语言
看了这句话之后我是懵逼的,没看懂,如果你也没看懂看看下面这句话
请求你所要的数据,不多不少
什么意思呢,很简单,假如我有一个查询用户信息的 restful 接口,里面会返回一些信息,用户名,密码,头像,等等,现在前端和我说,
前端:我只要用户名和头像,其他的都不要,你别查出来给我了
我:what?你不要的数据你不用不就行了,这接口不止你 web 端用,还有 app 接口也在用呢
前端:那我不管,现在需求就是这样
我:……
这个时候 GraphQL 出现了,你想要用户名和头像是吧,行,你自己来取,你要什么自己取什么,后端就会给你返回什么,后端也不用单独来给你写接口,说到这里,你可能似懂非懂,没关系,接着看下去
别着急,继续往下看
新建文件可以选择新建 graphql 文件
工具栏也会出现 graphql
这里面会自动去检查我们写的 graphql 文件中语法是否正确
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 必需:包含了默认配置、graphql-java 和 graphql-java-tools,可以简化配置 -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>11.0.0</version>
</dependency>
<!-- 可选:用于调试 GraphQL,功能类似 Restful 中的 Swagger -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>playground-spring-boot-starter</artifactId>
<version>11.0.0</version>
</dependency>
# 端口
server:
port: 7002
# 应用名称
spring:
application:
name: graphql-demo
# graphql 相关配置
graphql:
servlet:
mapping: /graphql
enabled: true
corsEnabled: false # 关闭跨域,仅使用浏览器插件调试时设置为false
playground:
cdn:
enabled: true # playground 使用 cdn 的静态文件
# if you want to @ExceptionHandler annotation for custom GraphQLErrors
exception-handlers-enabled: true
contextSetting: PER_REQUEST_WITH_INSTRUMENTATION
tools:
#扫描 resource 下 .graphql 后缀的文件
schema-location-pattern: "**/*.graphql"
#定义查询类型和更改类型
schema {
query: Query
mutation: Mutation
}
#查询方法, 类型来源于上面定义的 Query
type Query{
#查询所有班级,返回 list<Clazz>
listClazz: [Clazz]
#根据名称查询班级,返回单个 Clazz 对象
listClazzByName(name:String!): Clazz
}
#变更方法 , 类型来源于上面定义的 Mutation
type Mutation{
# 新增班级(返回 Result 对象)
add(code:String!,name:String!,description:String!): Result
# 修改班级(返回 Result 对象)
edit(id:String!,code:String!,name:String!,description:String!): Result
# 删除班级(返回 Result 对象)
del(id:String!): Result
# 创建班级(入参类型为对象 ClazzInput)
addByInput(input: ClazzInput!): Result
}
#班级实体
type Clazz{
#id
id : String
#编号
code : String!
#名称
name : String!
#描述
description : String!
}
#班级 input 对象
input ClazzInput{
#id
id : String
#编号
code : String!
#名称
name : String!
#描述
description : String!
}
type Result{
#状态码
code : Int!
#状态信息
msg : String!
}
.graphql 文件中注释用: #注释内容
Query下定义的是查询相关接口,Mutation下定义的是修改相关接口
Query 和 Mutation 方法格式
Query中方法格式为 : 方法名:返回类型 例如:listClazz: [Clazz]
方法名(参数名:参数类型):返回类型 例如:listClazzByName(name:String!): Clazz 参数类型后面加 !
代表这个参数不能为空,可为空则不加 ! 即可
Mutation 中方法格式基本和 Query 一致
type Clazz 你可以理解为定义一个名为 Clazz 的 java 实体类,里面就是它的一些属性,type Result 也一样
input ClazzInput 则是定义一个输入类型,可以看到属性基本和 Clazz 一致,只是定义时将 type 改成了 input,作用我们可以理解为,我们可以直接传输这个对象,稍后来进行讲解
先把两个对应的 java 实体类写好,属性同 graphql 文件中对象一致
package com.wxw.notes.graphql.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author wuxiongwei
* @date 2021/5/25 16:38
* @Description
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Clazz {
private String id;
private String code;
private String name;
private String description;
}
package com.wxw.notes.graphql.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author wuxiongwei
* @date 2021/5/25 16:38
* @Description
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ClazzInput {
private String id;
private String code;
private String name;
private String description;
}
package com.wxw.notes.graphql.demo.response;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Result {
private Integer code;
private String msg;
}
package com.wxw.notes.graphql.demo.resolver;
import com.wxw.notes.graphql.demo.entity.Clazz;
import com.wxw.notes.graphql.demo.entity.ClazzInput;
import com.wxw.notes.graphql.demo.response.Result;
import com.wxw.notes.graphql.demo.service.ClazzService;
import graphql.kickstart.tools.GraphQLMutationResolver;
import graphql.kickstart.tools.GraphQLQueryResolver;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author wuxiongwei
* @date 2021/5/25 16:37
* @Description
*/
@Component
public class ClazzResolver implements GraphQLQueryResolver, GraphQLMutationResolver {
private final ClazzService clazzService;
public ClazzResolver(ClazzService clazzService) {
this.clazzService = clazzService;
}
public List<Clazz> listClazz(){
return clazzService.list();
}
public Clazz listClazzByName(String name){
return clazzService.listByName(name);
}
public Result add(String code, String name, String description){
return clazzService.add(code,name,description);
}
public Result del(String id){
return clazzService.del(id);
}
public Result edit(String id,String code, String name, String description){
return clazzService.edit(id,code,name,description);
}
public Result addByInput(ClazzInput cla){
return clazzService.addByInput(cla);
}
}
GraphQLQueryResolver 顾名思义就是 Query 查询相关的解析器了
GraphQLMutationResolver 就是 Mutation 更改相关的解析器了
我这里就直接写在一个类里面了(可以选择分开写两个类去分别实现),同时实现
GraphQLQueryResolver 和 GraphQLMutationResolver
在 service 层,我们一般是查询数据库数据,之前怎么查现在还是怎么查,在这里我就简单在内存里面初始化一些数据了
package com.wxw.notes.graphql.demo.service;
import com.wxw.notes.graphql.demo.entity.Clazz;
import com.wxw.notes.graphql.demo.entity.ClazzInput;
import com.wxw.notes.graphql.demo.response.Result;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author wuxiongwei
* @date 2021/5/25 16:38
* @Description
*/
@Service
public class ClazzService {
private List<Clazz> clazzList = new ArrayList<Clazz>(){{
add(Clazz.builder().id(UUID.randomUUID().toString()).code("001").name("三年二班").description("加里顿第一班").build());
}};
public Clazz listByName(String name){
Optional<Clazz> first = clazzList.stream().filter(clazz -> clazz.getName().equals(name)).findFirst();
return first.orElse(null);
}
public List<Clazz> list(){
return clazzList;
}
public Result add(String code, String name, String description){
Clazz clazz = new Clazz();
clazz.setId(UUID.randomUUID().toString());
clazz.setCode(code);
clazz.setName(name);
clazz.setDescription(description);
clazzList.add(clazz);
return Result.builder().code(200).msg("success").build();
}
public Result del(String id){
clazzList = clazzList.stream().filter(clazz -> !clazz.getId().equals(id)).collect(Collectors.toList());
return Result.builder().code(200).msg("success").build();
}
public Result edit(String id,String code, String name, String description){
del(id);
add(code, name, description);
return Result.builder().code(200).msg("success").build();
}
public Result addByInput(ClazzInput cla){
Clazz clazz = new Clazz();
clazz.setId(UUID.randomUUID().toString());
clazz.setCode(cla.getCode());
clazz.setName(cla.getName());
clazz.setDescription(cla.getDescription());
clazzList.add(clazz);
return Result.builder().code(200).msg("success").build();
}
}
一切准备工作就绪之后,我们用 playground 图形化工具来看看 graphql 到底怎么来进行使用
启动我们的工程,访问 localhost:7002/playground
就可以看到下面这个界面了,默认界面风格是黑色,如果你想要修改成我这颜色,点击右上角设置
“editor.theme” 的值修改成 “light” 然后点击右上角保存即可
左边的查询语句,可能大家一进来就是空的,截图的查询语句是我这边之前测试写的
接下来,我们依次来调用下我们写的 graphql 方法,看看怎么调用
首先调用查询所有班级的方法,可以点开右侧 DOCS 文档,对照来写,我们想查询哪些信息,我左边就写哪些字段,我先查询所有字段
# listClazz 调用的方法名
# id,code,name,description 调用后想要得到的返回值
{
listClazz {
id
code
name
description
}
}
这个时候我们来解决前端给我的问题,假如小伙子不要 id 了,简单,你自己查询的时候直接去掉就行了,这样我就不给你 id 了,如下
# listClazz 调用的方法名
# code,name,description 调用后想要得到的返回值
{
listClazz {
code
name
description
}
}
再调用根据名称查询班级的方法,直接放入参数
# listClazzByName 调用的方法名
# name 参数属性名,三年二班 参数值
# code,name,description 调用后想要得到的返回值
listClazzByName(name:"三年二班"){
code
name
description
}
再调用根据名称查询班级的方法,使用变量 Variables 传入参数
# query 查询关键字
# listClazzByName 别名
# $name:String! name 为声明变量,String 类型,不为空(变量前加 $)
# listClazzByName 方法名,name 属性名,$name 引用上面声明的变量
# code,name,description 查询后想要的返回值
query listClazzByName($name:String!){
listClazzByName(name:$name){
code
name
description
}
}
# json 格式
{
"name":"三年二班"
}
我们来单独写变更中的 新增
# mutation 变更关键字
# add 方法名
# code,name,description 参数
# code,msg 请求后想要返回的返回值
mutation{
add(code: "001"
name: "三年三班"
description: "加里顿第二班级"){
code
msg
}
}
新增之后,再查询所有看看,可以看到已经成功添加了
接下来我们看看上文说到的输入类型怎么使用
# mutation 变更关键字
# addByInput 别名
# $clazzInput:ClazzInput! ,声明变量 $clazzInput ,类型为 ClazzInput ,不为空
# addByInput 接口名,input:$clazzInput input 入参类型, $clazzInput 引用变量
# code,msg 调用接口后想要的返回值
mutation addByInput($clazzInput:ClazzInput!){
addByInput(input:$clazzInput){
code
msg
}
}
# 参数
{
"clazzInput": {
"code": "003",
"name": "三年四班",
"description": "加里顿第三班"
}
}
新增之后,再查询所有看看,可以看到已经成功添加了
好了,基本用法就分享到这里了,大家有兴趣可以自行查阅官网
是不是觉得不过瘾,感觉还没有看到你想要的,想了解更多的可以进入下一篇深入了解,源码地址也会在下一篇进行分享
下一篇传送门:SpringBoot 中集成 GraphQL:深入篇
作者:我是一个射手
链接:http://www.javaheidong.com/blog/article/207378/7b8acd9e11fcfc3ebd1b/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!