Demo到产品化还有很长的路要走,尤为是要在尽可能小的影响当前框架的前提下引入新的方法。html
GraphiQL是整个GraphQL优点的重要一环,然而默认的GraphiQL不容许配置graphql服务的地址(就是点击GraphiQL上的运行按钮去请求数据的地址),要弄明白这一点很容易,找到graphiql-spring-boot-autoconfigure包,里面有graphiql.html文件,请求数据的endpoint是硬编码的:java
function graphQLFetcher(graphQLParams) {
// This example expects a GraphQL server at the path /graphql.
// Change this to point wherever you host your GraphQL server.
return fetch('/graphql', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(graphQLParams),
credentials: 'include',
}).then(function (response) {
return response.text();
}).then(function (responseBody) {
try {
return JSON.parse(responseBody);
} catch (error) {
return responseBody;
}
});
}
复制代码
显然这不能知足项目工程化的要求,解决这个问题有两种比较简单的方式:git
强大的实体关系图生成工具 github
GitHub已经提供了GraphQL的接口,实体关系图能够在GraphQL Voyager里查看,Custom Schema容许提供本身的实体关系数据生成实体关系图,简直不能更好用。spring
在GraphQL(三):GraphQL集成SpringBoot原理中提到GraphQL自己不带身份认证和权限控制(这也确实不是它该作的事儿),可是它对查询提供了回调方法(Instrumentation接口),在GraphQL.java文件中能够看到这部分逻辑:sql
public ExecutionResult execute(String requestString, String operationName, Object context, Map<String, Object> arguments) {
//执行回调
InstrumentationContext<ExecutionResult> executionCtx = instrumentation.beginExecution(new ExecutionParameters(requestString, operationName, context, arguments));
assertNotNull(arguments, "arguments can't be null");
log.debug("Executing request. operation name: {}. Request: {} ", operationName, requestString);
//解析回调
InstrumentationContext<Document> parseCtx = instrumentation.beginParse(new ExecutionParameters(requestString, operationName, context, arguments));
Parser parser = new Parser();
Document document;
try {
document = parser.parseDocument(requestString);
parseCtx.onEnd(document);
} catch (ParseCancellationException e) {
RecognitionException recognitionException = (RecognitionException) e.getCause();
SourceLocation sourceLocation = new SourceLocation(recognitionException.getOffendingToken().getLine(), recognitionException.getOffendingToken().getCharPositionInLine());
InvalidSyntaxError invalidSyntaxError = new InvalidSyntaxError(sourceLocation);
return new ExecutionResultImpl(Collections.singletonList(invalidSyntaxError));
}
//验证回调
InstrumentationContext<List<ValidationError>> validationCtx = instrumentation.beginValidation(new ValidationParameters(requestString,operationName,context,arguments,document));
Validator validator = new Validator();
List<ValidationError> validationErrors = validator.validateDocument(graphQLSchema, document);
validationCtx.onEnd(validationErrors);
if (validationErrors.size() > 0) {
return new ExecutionResultImpl(validationErrors);
}
ExecutionId executionId = idProvider.provide(requestString, operationName, context);
Execution execution = new Execution(queryStrategy, mutationStrategy, subscriptionStrategy, instrumentation);
ExecutionResult result = execution.execute(executionId, graphQLSchema, context, document, operationName, arguments);
executionCtx.onEnd(result);
return result;
}
复制代码
经过对每次执行GraphQL查询进行拦截能够实现相似SpringMVC拦截器的效果,可是须要本身实现SpringMVC中 @RequiredRole 注解的功能。json
在GraphQL(二):GraphQL服务搭建中提到有两种搭建GraphQL服务的方式,当时并无考虑身份认证和权限控制的问题,假如要在那两种方法的基础上加入身份认证和权限控制,有哪些成本呢?api
综合来看: bash
ok,再想一想咱们的需求是什么。app
这么一看的话能够得出这样的方案:
能够同时使用SpringMVC的拦截器和graphql-java-tools的优点。
彷佛这种方案能知足咱们的需求,可是有一个潜在的风险:
“A用户容许访问ApiA,ApiA可以访问到实体A,可是A用户没有权限访问实体A”
这时工程上就难以控制了,若是非要控制须要对实体进行权限,能作到,可是须要另一套设计,工做量也不小。
工程化实践时风险是必需要考虑的问题,GraphQL强大的自省功能(查询整个实体图的结构)能方便开发,也带来了相应的风险,同时嵌套循环查询、sql注入等问题也是须要防范的。