====== Nop 平台的 GraphQL 和 REST API ====== Nop 平台的 API 层有独特的设计:**同一个引擎同时提供 GraphQL 和 REST 两种协议**,不需要额外适配。 ===== 为什么需要两套协议 ===== GraphQL 适合复杂查询场景——客户端可以精确指定需要哪些字段,避免过度获取。REST 适合简单调用场景——用 curl 就能测试,调试方便。 传统做法是维护两套端点,各有各的路由、序列化、权限控制。Nop 用一套模型同时暴露两种协议。 ===== 基础概念:BizModel ===== Nop 中每个业务对象对应一个 **BizModel**(业务模型)。它定义了该对象的 CRUD 操作以及自定义方法。 自动生成的 BizModel(以 Article 为例)包含以下内建操作: save — 新增/修改 get — 按 ID 查询 delete — 删除 findPage — 分页查询 findList — 列表查询 这些操作同时注册为 GraphQL Mutation/Query 和 REST 端点。 ===== REST 端点 ===== 每个 BizModel 自动注册以下 REST 端点: POST /ArticleBizModel__save 保存 GET /ArticleBizModel__get?id=xxx 查询单个 POST /ArticleBizModel__findPage 分页查询 POST /ArticleBizModel__batchModify 批量修改 URL 格式为 ''%%/{BizModel}__{method}%%''。请求体统一为 JSON。 **查询示例:** curl "http://localhost:8080/ArticleBizModel__get?id=abc123" \ -H "nop-tenant: 0" **分页查询:** curl -X POST "http://localhost:8080/ArticleBizModel__findPage" \ -H "Content-Type: application/json" \ -H "nop-tenant: 0" \ -d '{ "query": { "title__contains": "Nop", "orderBy": [{"field": "createTime", "desc": true}] }, "limit": 20 }' 支持丰富的筛选条件: ^ 后缀 ^ 含义 ^ | __contains | 包含 | | __gt | 大于 | | __ge | 大于等于 | | __lt | 小于 | | __le | 小于等于 | | __in | 在列表中 | | __exists | 子查询存在 | | __isNull | 为空 | ===== GraphQL 端点 ===== GraphQL 端点在''http://localhost:8080/graphql''。支持 introspection,可以用 GraphiQL 探索。 **查询单个文章:** query { ArticleBizModel__get(id: "abc123") { title content author createTime } } **创建文章:** mutation { ArticleBizModel__save(data: { title: "Hello Nop", content: "文章内容", author: "test" }) { articleId title } } **GraphQL 的优势在于可以跨对象查询:** query { ArticleBizModel__findPage(query: {author__contains: "test"}) { items { title createTime # 关联对象自动可查 tags { name } } total } } 关联对象不需要手写 join——ORM 层自动处理。 ===== 自定义业务方法 ===== 通过继承 BizModel 添加自定义操作: @BizModel("Article") public class ArticleBizModelEx extends _ArticleBizModel { @BizQuery public List
getTopArticles( @Name("limit") int limit ) { return dao().findTopByViews(limit); } @BizAction public void publishArticle( @Name("id") String id ) { Article article = dao().get(id); article.setStatus("published"); dao().update(article); } } @BizQuery 标记的方法注册为 GraphQL Query + REST GET。 @BizAction 标记的方法注册为 GraphQL Mutation + REST POST。 自定义方法自动获得端点: REST: GET /ArticleBizModel__getTopArticles?limit=10 REST: POST /ArticleBizModel__publishArticle GraphQL: query { ArticleBizModel__getTopArticles(limit: 10) { ... } } GraphQL: mutation { ArticleBizModel__publishArticle(id: "xxx") { ... } } ===== 权限控制 ===== 每个方法都可以通过 acl.xml 配置权限: 未授权的调用返回 403。 ===== 协议对比 ===== ^ 特性 ^ REST ^ GraphQL ^ | 端点 URL | /{BizModel}__{method} | /graphql | | 客户端 | curl、浏览器 | GraphiQL、Apollo | | 字段选择 | 固定返回 | 客户端指定 | | 关联对象 | 单独请求 | 同一请求中 | | 批量操作 | 逐个请求 | 同一请求中 | | 自省 | 无 | 有(Introspection) | 两套协议由同一套 BizModel 定义驱动,不需要各自维护一份代码。 ===== 进一步阅读 ===== * [[.:first_api_guide|编写第一个 API]] * [[.:setup_guide|配置开发环境指南]] * [[https://gitee.com/canonical-entropy/nop-entropy/tree/master/docs/dev-guide/graphql.md|官方 GraphQL 文档]]