====== 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 文档]]