外观
扩展与覆盖
扩展点是 QueryEngine 自己的类,不是其他项目的解析器拷贝。
继承
FieldParser 解析 NestQL。覆盖 afterParse:
java
public class HidePasswordParser extends FieldParser {
@Override
protected TableRequest afterParse(TableRequest request, JsonNode body, Method method) {
for (SelectItem column : request.columns()) {
if ("password".equalsIgnoreCase(column.name())) {
throw new BadRequestException("列不可查询: password");
}
}
return request;
}
}SqlPlanner 渲染参数化 SQL。覆盖 select 时请保留参数列表,不要把值拼进语句。dialect 字段是 protected。
DefaultAccessRegistry 管白名单。覆盖 require 可以拒绝某个 method。
完整例子在 queryengine-demo 的 dev.queryengine.demo.ext。
java
QueryEngine.builder()
.dataSource(dataSource)
.dialect(new MySqlDialect())
.fieldParser(new HidePasswordParser())
.sqlPlanner(new CommentedSqlPlanner(new MySqlDialect()))
.accessRegistry(new NoDeleteRegistry())
.tableNameMapper(name -> name.toLowerCase(Locale.ROOT))
.registerTable("User")
.build();TableNameMapper 只决定物理表名。MySQL 仍会把表名折成小写,达梦在引用时折成大写。
Spring
声明即生效,不用改自动配置:
java
@Bean
FieldParser fieldParser() {
return new HidePasswordParser();
}
@Bean
ResponseCustomizer stamp() {
return body -> {
body.put("engine", "queryengine");
return body;
};
}
@Bean
GraphQLSchemaCustomizer schemaCustomizer() {
return (schema, callSchema) -> {
// access 名单生成之后、build 之前
};
}ResponseCustomizer 看到的是已经写好 code / message 的信封。GraphQLSchemaCustomizer 不要把列参数改成 ID 或 Int:运行时只注册了 Long 和 String。