通过前面的博文,我们可以发现graphQL功能很强大,那么如果我们将其用到生产环境,还需要考虑更多的问题?
1.graphQL支持http接口吗?GET、POST的查询如何实现?
2.graphQL支持分页吗?
上面两个问题,在实际工作中非常普遍,通过研究发现,都是可以实现的
一、HTTP请求
根据GraphQL最佳实践的建议,在GET请求中只取query参数的内容,
而在POST请求中可以在body中支持query之外的更多参数,比如variables
实现的代码如下
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}) public Map<String, Object> graphql( @RequestParam(required = false) Map<String, Object> param, @RequestBody String body, HttpServletRequest r) { String method = r.getMethod(); log.info("method="+method); if (method.equals("GET")) { Object query = param.get("query"); log.info("query="+query); ExecutionInput executionInput = ExecutionInput.newExecutionInput() // 需要执行的查询语言 .query(query.toString()).build(); return this.graphQL.execute(executionInput).toSpecification(); } else { JSONObject req = JSON.parseObject(body); log.info(req.toJSONString()); ExecutionInput executionInput = ExecutionInput.newExecutionInput() // 需要执行的查询语言 .query(req.getString("query")) // 执行操作的名称,默认为null .operationName(req.getString("operationName")) // 获取query语句中定义的变量的值,这个必须注释掉,不然启动不起来 .variables(req.getJSONObject("variables")) .build(); // 执行并返回结果 return this.graphQL.execute(executionInput).toSpecification(); } }
二、支持分页
对应列表数据,当数据量较大是,前端一般希望进行分页处理,这个需求很合理。
graphQL的分页分为两种情况:
(一)、如果原生API支持分页只需要定义query查询时传入(page,size)信息传入原生API接口,
理论上原生api结果应该包含(total,pages),
graphQL只需要构建包含这两个字段的schema即可,无需其他设置
(二)、如果原生API不支持分页
分页就需要在graphQL自己实现,首先自定义分页请求参数(page,size)以及新的结果schema,
然后对上游的返回结果在内存中进行分页
从性能角度考虑,推荐进行第一种方式,如果原生API不支持也不愿意修改,那就只能在内存进行分页。
内容分页的实现如下:
//argument是参数,data是原始的结果 private Map<String, Object> pageProcess(Map<String, Object> arguments, Object data) { JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(data)); int total = jsonArray.size(); Integer size = (Integer) arguments.get("size"); Integer page = (Integer) arguments.get("page"); int pages = (int) Math.ceil((double)total / size); Integer fromIndex = (page - 1) * size; Integer toIndex = fromIndex + size > total ? total : fromIndex + size; List<Object> subList = jsonArray.subList(fromIndex, toIndex); Map<String, Object> map = new HashMap<>(); map.put("books", subList); map.put("total", total); map.put("pages", pages); return map; }