当前位置: 首页>移动开发>正文

janusgraph gremlin 后台执行 graphql教程java

本篇主要使用graphql-java来演示如何使用Java来构建GraphQL API,文中使了Gradle作为构建工具,但未使用其特性,因此你也可以使用Maven,只是简单添加依赖即可。主要涉及到枚举(enum)、输入类型(input)、参数(argument)、接口(interface)、联合(union)等服务端,以及客户端查询测试。本例代码存放在 https://github.com/zhaiqianfeng/GraphQL-Demo/tree/master/java


添加依赖

gradle

compile 'com.graphql-java:graphql-java:3.0.0'

maven

<dependency>     
      <groupId>com.graphql-java</groupId>     
      <artifactId>graphql-java</artifactId>     
      <version>3.0.0</version>     
      </dependency>

本文示例使用的构建工具是Gradle。

示例代码结构

示例结构目录如下

├── advance 高级示例     
      │   ├── GraphQL_argument.java 传入参数示例     
      │   ├── GraphQL_interface.java 接口示例     
      │   └── GraphQL_union.java 联合示例     
      ├── get_start 入门示例     
      │   └── GraphQL_Simple.java 简单入门示例     
      └── model Java实体     
      ├── Dog4Interface.java 为接口示例准备的Dog实现     
      ├── Dog4Union.java 为联合示例准备的Dog     
      ├── Fish4Interface.java 为接口示例准备的Fish实现     
      ├── Fish4Union.java 为联合示例准备的Fish     
      ├── IAnimal.java 为接口示例准备的Animal接口     
      └── User.java 为示例准备的User

每个示例基本遵循流程:提供带查询的示例数据-> 定义GrapQL数据类型 -> 定义暴露给客户端的query api和mutaion api -> 创建GraphQL Schema -> 测试输出

简单示例

示例代码如下

// com.zqf.get_start.GraphQL_Simple     
      //服务端示例数据     
      User user=new User();     
      user.setName("zhaiqianfeng");     
      user.setSex("男");     
      user.setIntro("博主,专注于Linux,Java,nodeJs,Web前端:Html5,JavaScript,CSS3");     
      //定义GraphQL类型     
      GraphQLObjectType userType = newObject()     
      .name("User")     
      .field(newFieldDefinition().name("name").type(GraphQLString))     
      .field(newFieldDefinition().name("sex").type(GraphQLString))     
      .field(newFieldDefinition().name("intro").type(GraphQLString))     
      .build();     
      //定义暴露给客户端的查询query api     
      GraphQLObjectType queryType = newObject()     
      .name("userQuery")     
      .field(newFieldDefinition().type(userType).name("user").staticValue(user))     
      .build();     
      //创建Schema     
      GraphQLSchema schema = GraphQLSchema.newSchema()     
      .query(queryType)     
      .build();     
      //测试输出     
      GraphQL graphQL = GraphQL.newGraphQL(schema).build();     
      Map<String, Object> result = graphQL.execute("{user{name,sex,intro}}").getData();     
      System.out.println(result);

执行输出

{user={name=zhaiqianfeng, sex=男, intro=博主,专注于Linux,Java,nodeJs,Web前端:Html5,JavaScript,CSS3}}
参数(argument)示例

参数示例代码比较多,请参考github上的源码:GraphQL_argument.java,做如下几点说明。

定义形参

传输参数是通过argument方法传入并指定类型,如

.argument(newArgument()     
      .name("id")     
      .type(new GraphQLNonNull(GraphQLInt)))
接收参数

获取参数使用DataFetchingEnvironment,如

int id=environment.getArgument("id");

获取参数有如下两个重构

Map<String, Object> getArguments();     
      <T> T getArgument(String name);

但当我使用后者把传入的userInfo转换为User时,异常

java.util.LinkedHashMap cannot be cast to com.zqf.model.User

因此不得不如下蹩脚书写

Map<String,Object> userInfoMap=environment.getArgument("userInfo");     
      User userInfo=new User();     
      for (String key : userInfoMap.keySet()){     
      switch (key){     
      case "name":     
      userInfo.setName(userInfoMap.get("name").toString());     
      break;     
      case "sex":     
      userInfo.setSex(userInfoMap.get("sex").toString());     
      break;     
      case "intro":     
      userInfo.setIntro(userInfoMap.get("intro").toString());     
      break;     
      case "skills":     
      ArrayList<String> skillsList=(ArrayList<String>) userInfoMap.get("skills");     
      String[] skills=new String[skillsList.size()];     
      userInfo.setSkills(skillsList.toArray(skills));     
      break;     
      }     
      }
Resolver

解析数据使用的是DataFetcher,如

.dataFetcher(new DataFetcher() {     
      @Override     
      public Object get(DataFetchingEnvironment environment) {     
      int id=environment.getArgument("id");     
      return users.get(id);     
      }     
      }))

为了简洁,你可以使用lambda表达式

.dataFetcher(environment -> {     
      int id=environment.getArgument("id");     
      return users.get(id);     
      }))
联合(union)示例

这部分没说明好说的,如果了解了union的概念代码示例非常清晰,请参考github上的源码:GraphQL_union.java。使用GraphQLUnionType定义union类型,其中possibleType指定可以union的类型,重点是关注typeResolver来做类型转换,但个人觉得这里实现有待改进,对于Java这种强类型语言自动处理比较人性化。

GraphQLUnionType animalUnion = newUnionType()//定义联合类型(union)     
      .name("IAnimal")     
      .possibleType(dogType)     
      .possibleType(fishType)     
      .description("动物联合")     
      .typeResolver(env -> {     
      if(env.getObject() instanceof Dog4Union){     
      return dogType;     
      }if(env.getObject() instanceof Fish4Union){     
      return fishType;     
      }     
      return null;     
      })     
      .build();
接口(interface)示例

graphql-java对GraphQL的接口实现确实使用的Java接口,但个人觉得使用集成或许更合适。定义接口使用的GraphQLInterfaceType关键字,实现接口使用的withInterface关键字。

坑:对象为定义

上面的关键字都不难理解,蛋疼的是把如下的定义放在方法体中却提示为定义

GraphQLInterfaceType animalInterface = newInterface()//定义接口(interface)类型     
      .name("IAnimal")     
      .description("动物接口")     
      .field(newFieldDefinition()     
      .name("name")     
      .type(GraphQLString))     
      .typeResolver(new TypeResolver() {     
      @Override     
      public GraphQLObjectType getType(TypeResolutionEnvironment env) {     
      if (env.getObject() instanceof Dog4Interface) {     
      return dogType; //提示 dogType 未定义     
      }     
      if (env.getObject() instanceof Fish4Interface) {     
      return fishType; //提示 fishType 未定义     
      }     
      return null;     
      }     
      })     
      .build();     
      GraphQLObjectType dogType = newObject()//定义Dog类型     
      .name("Dog4Interface")     
      .field(newFieldDefinition().name("name").type(GraphQLString))     
      .field(newFieldDefinition().name("legs").type(GraphQLInt))     
      .withInterface(animalInterface)     
      .build();     
      GraphQLObjectType fishType = newObject()//定义Fish类型     
      .name("Fish4Interface")     
      .field(newFieldDefinition().name("name").type(GraphQLString))     
      .field(newFieldDefinition().name("tailColor").type(GraphQLString))     
      .withInterface(animalInterface)     
      .build();

也看到了有开发者提了issue:Circularity between object and interface type definitions,但依然没看到有效的解决方案,只好顺着作者愿意,把上面的定义作为字段才能解决,具体代码可参考github上的源码:GraphQL_interface.java

Schema加入额外类型

最后还要提示下,由于查询返回的接口,但实现并没有自动添加到Schema中,因此需要在创建Schema时间,将其手动加入

//额外的GraphQL类型     
      Set<GraphQLType> types=new HashSet<>();     
      types.add(dogType);     
      types.add(fishType);     
      //创建Schema     
      GraphQLSchema schema = GraphQLSchema.newSchema()     
      .query(queryType)     
      .build(types);
结束语

虽然遇到了许多坑,但最后还是把需要的功能演示出来了,但无论是那种类库,基本的流程一般不会改变:基本遵循流程:定义GrapQL数据类型 -> 定义暴露给客户端的query api和mutaion api -> 创建GraphQL Schema


https://www.xamrdz.com/mobile/4qv1961450.html

相关文章: