说明:
GraphQL是API规范,实现需要什么数据时就获取什么数据,避免垃圾数据的返回,能整合多个接口的数据一起返回,提高客户端用户体验。
一、查询规范:
请求接口时,用GQL客户端或浏览器GQL插件发送如下"查询字符串格式",接口会返回相应json格式。
1.字段:
查询字符串格式:
{
user {
name
}
}
返回json格式:
{
“data”: {
“user”: {
“name”: “X先生”
}
}
}
2.传参数:
查询字符串格式:
{
user(id: 1) { //参数: 值
name
}
}
返回json格式:
{
“data”: {
“user”: {
“name”: “X先生”
}
}
}
3.别名(有多个相同类型的,要定别名):
查询字符串格式:
{
别名1: user {
name
}
别名2: user {
name
}
}
返回json格式:
{
“data”: {
“ 别名1:”: {
“name”: “X先生1”
},
“ 别名2:”: {
“name”: “X先生2”
}
}
}
4.片段 :
查询字符串格式:
{
别名1: user {
…通用名 //引入通用片段
}
别名2: user {
…通用名 //引入通用片段
}
}
fragment 通用名 on Character {//通用片段
name
}
返回json格式:
{
“data”: {
“ 别名1:”: {
“name”: “X先生1” //引入通用片段
},
“ 别名2:”: {
“name”: “X先生2” //引入通用片段
}
}
}
二、类型规范:
1.Schema定义:
schema { //定义一个查询的Schema规范
query: FindUser //定义查询类型
}
type FindUser {//定义查询类型
user(id:ID): User //指定查询参数类型与返回值类型
}
type User { //定义User对象
id:ID! //!规定值不能为空
}
2.变量类型:
Int:有符号 32 位整数类型
Float:有符号双精度浮点类型。
String:UTF‐8 字符串类型。
Boolean : 布尔类型,true 或者 false 。
ID:唯一标识符
3.枚举 :
enum Status { //定义枚举
ONE //定义值
TOW //定义值
}
使用:
type A {
b : [Status]! //使用
}
4.接口:
定义接口:
interface 接口名 {
name: String
}
实现接口:
type 子类名 implements 接口名 {
name: String //必须写上接口中的变量
}
三、使用GraphQL:
IDEA安装JS GraphQL插件。
1.IDEA的settings.xml中添加第三方仓库(idea目录/plugins/maven/lib/maven3/conf/settings.xml):
<!-- graphql -->
<profiles>
<profile>
<id>bintray</id>
<repositories>
<repository>
<id>bintray</id>
<url>http://dl.bintray.com/andimarek/graphql-java</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>bintray</id>
<url>http://dl.bintray.com/andimarek/graphql-java</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>bintray</activeProfile>
</activeProfiles>
2.工程pom.xml中导入graphql-java依赖包:
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>15.0</version>
</dependency>
3.在工程resources下创建user.graphqls,定义Schema:
schema { #定义一个查询的Schema规范
query: FindUser #定义一个查询
}
type FindUser { #定义一个查询
user(userNo: String): User #指定查询参数类型与返回值类型
}
type User { #定义User对象
userNo: String #定义参数列表
name: String
}
4.实体类:
//用户实体类
public class User {
private String userNo; //用户编号
private String name; //用户名
public User(String userNo, String name) {
this.userNo = userNo;
this.name = name;
}
public String getUserNo() {
return userNo;
}
public void setUserNo(String userNo) {
this.userNo = userNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5.1.使用Java客户端查询GQL接口获取数据:
//java-GQL客户端
public class GQLClient {
public static void main(String[] args) {
//1.读了文件内容
String content = readFile("user.graphqls");
//2.得到注册器
TypeDefinitionRegistry registry = getRegistry(content);
//3.得到运行时连接
RuntimeWiring wiring = getWiring();
//4.得到Schema
GraphQLSchema schema = getSchema(registry, wiring);
//5.执行查询
GraphQL gql = GraphQL.newGraphQL(schema).build();
Object data = gql.execute("{user(id:1001){id,name}}").getData(); //查询语句,传入GQL格式的字符串
System.out.println("查询结果为:" + data);
}
//1.读取文件内容
public static String readFile(String fileName) {
try {
return streamToStr(GQLClient.class.getClassLoader().getResourceAsStream(fileName));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//将流转字符串
public static String streamToStr(InputStream in) {
if (in != null) {
try {
BufferedReader bufRead = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String line;
while ((line = bufRead.readLine()) != null) {
sb.append(line);
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
//2.得到注册器
public static TypeDefinitionRegistry getRegistry(String fileContent) {
return new SchemaParser().parse(fileContent);
}
//3.得到运行时连接
public static RuntimeWiring getWiring() {//FindUser为user.graphqls中自定义类型,user为user.graphqls文件名
return RuntimeWiring.newRuntimeWiring().type("FindUser",
typeWiring -> typeWiring.dataFetcher("user", environment -> {
String userNo = environment.getArgument("userNo"); //获取用户编号
return new User(userNo, "X先生");
})
).build();
}
//4.得到Schema
public static GraphQLSchema getSchema(TypeDefinitionRegistry registry, RuntimeWiring wiring) {
return new SchemaGenerator().makeExecutableSchema(registry, wiring);
}
}
5.2.与Spring整合部署GQL接口,使用插件请求GQL接口获取数据:
(1)定义通用GQL查询接口:
public interface GQLInterface {
//查询名称
String fieldName();
//由子类实现具体查询
Object dataFetcher(DataFetchingEnvironment env);
}
(2)实现通用GQL查询接口:
@Component //通用GQL查询接口的实现类之一,会自动注入List<GQLInterface> gqlImplList
public class UserGQLImpl implements GQLInterface {
@Autowired
private UserBiz userBiz; //用户相关的增删改查业务类
@Override
public String fieldName() {//实现GQL接口,返回实现名称
return "UserGQL";
}
@Override
public Object dataFetcher(DataFetchingEnvironment environment) {//实现具体查询业务
String userNo = environment.getArgument("userNo"); //获取请求参数userNo
return userBiz.query(userNo); //执行真正的查询业务
}
}
@Service //用户增删改查业务类
public class UserBiz {
public User query(String userNo){
//查询代码...
return new User("1001", "X先生");
}
}
(3)创建自动加载的GQL配置类,装载GQL文件进行初始化等操作:
@Component //Spring-GQL配置类
public class GQLConfig {
private GraphQL graphQL; //查询对象
@Bean
public GraphQL graphQL() {
return graphQL;
}
@Autowired
private List<GQLInterface> gqlImplList; //实现类列表
@PostConstruct
public void init() throws IOException {
//1.得到File对象
File file = ResourceUtils.getFile("classpath:user.graphqls");
//2.得到注册器
TypeDefinitionRegistry registry = getRegistry(file);
//3.得到运行时连接
RuntimeWiring wiring = getWiring();
//4.得到Schema
GraphQLSchema schema = getSchema(registry, wiring);
//5.1 得到GraphQL查询对象
this.graphQL = GraphQL.newGraphQL(schema).build();
}
//2.得到注册器
public static TypeDefinitionRegistry getRegistry(File file) {
return new SchemaParser().parse(file);
}
//3.得到运行时连接
private RuntimeWiring getWiring() {//FindUser为user.graphqls中自定义类型,user为user.graphqls文件名
return RuntimeWiring.newRuntimeWiring().type("FindUser",
builder -> {
for (GQLInterface item : gqlImplList) {//遍历实现类列表,执行每个子类中的查询方法
builder.dataFetcher(item.fieldName(), environment -> item.dataFetcher(environment));
}
return builder;
}).build();
}
//4.得到Schema
public static GraphQLSchema getSchema(TypeDefinitionRegistry registry, RuntimeWiring wiring) {
return new SchemaGenerator().makeExecutableSchema(registry, wiring);
}
}
(4)创建GQL接口请求处理类:
@RequestMapping
@Controller
public class UserController {
@Autowired
private GraphQL graphQL; //GQL查询对象
@GetMapping("/getUserInfo")
@ResponseBody
public Map<String, Object> getUserInfo(String query) {
return graphQL.execute(query).toSpecification(); //执行graphQL查询
}
}
(5)安装Altair GraphQL Client,请求GQL接口获取数据:
http://www.electronjs.org/apps/altair