版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
API接口设计指南
RESTful·GraphQL分风格含范例
从设计原则到工程落地的完整实战手册
10大章节·80+代码示例·100+设计要点
API设计实战系列
目录
第一章API设计概述与设计哲学
第二章RESTfulAPI设计原则
第三章RESTfulAPI实战范例
第四章GraphQL设计原则
第五章GraphQL实战范例
第六章RESTfulvsGraphQL深度对比
第七章认证、授权与安全设计
第八章版本管理、错误处理与限流
第九章性能优化与缓存策略
第十章文档、测试与最佳实践速查
API接口设计指南·RESTful/GraphQL分风格含范例
第一章API设计概述与设计哲学
1.1API的本质与价值
API(ApplicationProgrammingInterface,应用程序编程接口)是软件系统之间交互的契约。它定义了"谁可以调
用、调用什么、传什么参数、返回什么结果"的完整规则。API设计质量直接决定了系统的可用性、可维护性和可扩
展性。
在微服务、移动应用、开放平台等场景下,API是系统对外的唯一入口。一个设计良好的API能让调用方快速
上手、减少沟通成本、降低集成难度;一个设计糟糕的API则会导致调用方频繁出错、需要大量文档、维护成本高
昂。API设计不是技术炫技,而是以使用者为中心的工程实践。
1.2API设计的三层目标
层次目标评判标准
可用性调用方能够正确使用接口语义清晰、参数直观、错误可理解
一致性所有接口遵循统一风格命名、结构、错误码、版本管理统一
演进性支持平滑升级和兼容版本策略、废弃机制、向后兼容
1.3主流API风格对比
风格核心思想代表适用场景
REST资源导向,使用HTTP动词操作资源GitHubAPI、TwitterAPI通用业务API
GraphQL查询语言,客户端声明需要什么数据GitHubGraphQL、Shopify复杂数据聚合、多端复用
gRPC基于Protobuf的高性能RPC微服务内部通信内部高性能场景
WebSocket双向实时通信聊天、实时推送实时交互
Webhook反向通知,服务端主动推送支付回调、事件通知异步事件通知
1.4优秀API的六个特征
特征一:语义清晰。从URL、方法、参数名就能理解接口的用途,无需看文档就能猜到大致功能。例如GET
/users/123一看就知道是获取ID为123的用户。
特征二:资源导向。把系统抽象为资源集合,URL是资源的标识,HTTP方法是对资源的操作。这是REST的
核心思想,也是好的API设计的通用原则。
特征三:状态无关。每个请求都包含处理所需的全部信息,服务端不存储客户端状态。这让系统易于水平扩
展、便于调试和测试。
特征四:错误友好。错误响应包含明确的错误码、可读的错误信息和修复建议,让调用方能够快速定位和解
决问题。
特征五:版本可控。支持平滑的版本升级,新版本上线后旧版本仍可正常工作,给调用方充分的迁移时间。
特征六:安全可靠。支持认证、授权、限流、加密,防止未授权访问和恶意攻击。有完善的监控、日志和审
计能力。
1.5API设计流程
API设计标准流程:
第1步:需求分析
-明确业务场景和使用者
-梳理数据模型和资源
-分析调用模式(读多写少、实时性要求)
第2步:资源建模
-识别核心资源
-定义资源之间的关系
-确定资源的唯一标识
第3步:接口设计
-定义URL结构
-定义HTTP方法和语义
-定义请求和响应结构
第4步:错误处理
-定义错误码规范
-定义错误响应结构
-定义重试和幂等策略
第5步:安全设计
-认证方案(JWT/OAuth2.0)
-授权模型(RBAC/ABAC)
-限流策略
-加密传输
第6步:版本管理
-版本策略(URL/Header/Content-Type)
-版本生命周期
-废弃策略
第7步:文档与测试
-OpenAPI/Swagger文档
-接口测试用例
-契约测试
第8步:评审与发布
-设计评审
-灰度发布
-监控与迭代
API设计的基本原则:第一,以使用者为中心——API是给别人用的,不是给自己看的;第二,保持一致性
——风格统一比单个接口的完美更重要;第三,面向未来——为扩展预留空间,避免破坏性变更;第四,简单
优先——能用简单方式解决的不引入复杂机制;第五,文档即契约——文档与代码同步,用工具自动化生成。
第二章RESTfulAPI设计原则
2.1REST的核心思想
REST(RepresentationalStateTransfer,表述性状态转移)是RoyFielding在2000年博士论文中提出的架构风
格。它的核心思想是把系统抽象为资源(Resource),通过统一的接口操作资源,使用标准的HTTP方法表达操作
语义。
REST不是标准,也不是协议,而是一种设计约束。满足这些约束的API称为RESTfulAPI。REST的核心约束包
括:客户端-服务器分离、无状态、可缓存、统一接口、分层系统、按需代码(可选)。
2.2资源命名规范
规范示例反例
使用名词,不用动词GET/usersGET/getUsers
使用复数形式GET/users/123GET/user/123
使用小写和连字符/user-profiles/userProfiles、/UserProfiles
层级关系用嵌套/users/123/orders/getUserOrders?userId=123
避免过深嵌套(≤3层)/users/123/orders/users/123/orders/456/items/789
使用查询参数过滤/users?status=active/users/active
2.3HTTP方法语义
方法语义幂等安全示例
GET获取资源是是GET/users/123
POST创建资源否否POST/users
PUT全量更新资源是否PUT/users/123
PATCH部分更新资源否否PATCH/users/123
DELETE删除资源是否DELETE/users/123
HEAD获取资源元数据是是HEAD/users/123
OPTIONS获取资源支持的方法是是OPTIONS/users
2.4HTTP状态码使用
状态码含义使用场景
200OK请求成功GET/PUT/PATCH成功
201Created资源创建成功POST创建资源成功
204NoContent成功但无返回内容DELETE成功
400BadRequest请求参数错误参数缺失、格式错误
401Unauthorized未认证缺少Token或Token无效
403Forbidden无权限已认证但无权访问
404NotFound资源不存在查询的资源不存在
409Conflict资源冲突唯一约束冲突
429TooManyRequests请求过于频繁触发限流
500InternalServerError服务器内部错误未预期的异常
503ServiceUnavailable服务不可用服务过载或维护
2.5请求与响应设计
#标准请求结构
GET/api/v1/users/123HTTP/1.1
Host:
Authorization:Bearer
Accept:application/json
X-Request-Id:req_abc123
#标准响应结构(成功)
HTTP/1.1200OK
Content-Type:application/json
X-Request-Id:req_abc123
{
"code":0,
"message":"success",
"data":{
"id":123,
"username":"alice",
"email":"alice@",
"created_at":"2026-09-19T10:30:00Z"
},
"request_id":"req_abc123"
}
#标准响应结构(错误)
HTTP/1.1400BadRequest
Content-Type:application/json
{
"code":10001,
"message":"参数校验失败",
"errors":[
{
"field":"email",
"message":"邮箱格式不正确"
}
],
"request_id":"req_abc123"
}
#分页响应结构
HTTP/1.1200OK
{
"code":0,
"message":"success",
"data":{
"items":[
{"id":1,"name":"Alice"},
{"id":2,"name":"Bob"}
],
"pagination":{
"page":1,
"page_size":20,
"total":100,
"total_pages":5
}
}
}
2.6RESTful设计原则速查
URL用名词,不用动词
使用复数形式表示资源集合
层级关系通过URL路径表达
过滤、排序、分页通过查询参数
HTTP方法表达操作语义
GET安全幂等、POST创建、PUT全量更新、PATCH部分更新、DELETE删除
使用标准HTTP状态码
响应结构统一,包含code、message、data
错误响应包含错误码和详细信息
支持分页、过滤、排序
版本号放在URL或Header
使用HTTPS加密传输
第三章RESTfulAPI实战范例
3.1电商订单API设计
#==========资源设计==========
#订单资源
GET/api/v1/orders#查询订单列表
POST/api/v1/orders#创建订单
GET/api/v1/orders/{id}#查询订单详情
PUT/api/v1/orders/{id}#全量更新订单
PATCH/api/v1/orders/{id}#部分更新订单
DELETE/api/v1/orders/{id}#删除订单
#订单子资源
GET/api/v1/orders/{id}/items#查询订单明细
POST/api/v1/orders/{id}/items#添加订单项
#订单操作
POST/api/v1/orders/{id}/cancel#取消订单
POST/api/v1/orders/{id}/pay#支付订单
POST/api/v1/orders/{id}/ship#发货
#用户订单
GET/api/v1/users/{userId}/orders#查询用户的订单
#==========请求示例==========
#查询订单列表(带分页、过滤、排序)
GET/api/v1/orders?status=paid&page=1&page_size=20&sort=-created_at
Authorization:Bearer
#创建订单
POST/api/v1/orders
Content-Type:application/json
Authorization:Bearer
{
"user_id":123,
"items":[
{
"product_id":456,
"quantity":2
},
{
"product_id":789,
"quantity":1
}
],
"receiver":{
"name":"张三",
"phone":,
"address":"北京市朝阳区某某路1号"
},
"remark":"请尽快发货"
}
#查询订单详情
GET/api/v1/orders/12345
Authorization:Bearer
#部分更新订单
PATCH/api/v1/orders/12345
Content-Type:application/json
Authorization:Bearer
{
"remark":"已修改备注",
"receiver":{
"phone":
}
}
#取消订单
POST/api/v1/orders/12345/cancel
Content-Type:application/json
{
"reason":"不想要了"
}
#==========响应示例==========
#订单列表响应
{
"code":0,
"message":"success",
"data":{
"items":[
{
"id":12345,
"order_no":"ORD20260919001",
"user_id":123,
"total_amount":299.00,
"status":"paid",
"created_at":"2026-09-19T10:30:00Z"
}
],
"pagination":{
"page":1,
"page_size":20,
"total":100,
"total_pages":5
}
}
}
#订单详情响应
{
"code":0,
"message":"success",
"data":{
"id":12345,
"order_no":"ORD20260919001",
"user_id":123,
"items":[
{
"id":1,
"product_id":456,
"product_name":"iPhone16",
"quantity":2,
"unit_price":100.00,
"total_price":200.00
}
],
"total_amount":299.00,
"discount_amount":0.00,
"pay_amount":299.00,
"status":"paid",
"receiver":{
"name":"张三",
"phone":"138****0000",
"address":"北京市朝阳区某某路1号"
},
"created_at":"2026-09-19T10:30:00Z",
"paid_at":"2026-09-19T10:32:00Z"
}
}
3.2用户管理API设计
#==========资源设计==========
#用户资源
GET/api/v1/users#用户列表
POST/api/v1/users#创建用户
GET/api/v1/users/{id}#用户详情
PUT/api/v1/users/{id}#全量更新
PATCH/api/v1/users/{id}#部分更新
DELETE/api/v1/users/{id}#删除用户
#用户子资源
GET/api/v1/users/{id}/profile#用户资料
GET/api/v1/users/{id}/orders#用户订单
GET/api/v1/users/{id}/addresses#用户地址列表
#认证相关
POST/api/v1/auth/login#登录
POST/api/v1/auth/logout#登出
POST/api/v1/auth/refresh#刷新Token
POST/api/v1/auth/register#注册
#==========认证示例==========
#登录
POST/api/v1/auth/login
Content-Type:application/json
{
"username":"alice",
"password":"********"
}
#登录响应
{
"code":0,
"message":"success",
"data":{
"access_token":"eyJhbGciOiJIUzI1NiIs...",
"refresh_token":"eyJhbGciOiJIUzI1NiIs...",
"token_type":"Bearer",
"expires_in":3600
}
}
#刷新Token
POST/api/v1/auth/refresh
Content-Type:application/json
{
"refresh_token":"eyJhbGciOiJIUzI1NiIs..."
}
#==========查询示例==========
#用户列表(带过滤、排序、分页)
GET/api/v1/users?status=active&sort=-created_at&page=1&page_size=20
Authorization:Bearer
#用户列表响应
{
"code":0,
"message":"success",
"data":{
"items":[
{
"id":123,
"username":"alice",
"email":"alice@",
"status":"active",
"created_at":"2026-01-01T00:00:00Z"
}
],
"pagination":{
"page":1,
"page_size":20,
"total":1000,
"total_pages":50
}
}
}
#搜索用户
GET/api/v1/users?keyword=alice
#多条件过滤
GET/api/v1/users?status=active&city=beijing&age_min=18&age_max=60
#字段选择
GET/api/v1/users?fields=id,username,email
#排序
GET/api/v1/users?sort=-created_at,+username
3.3文件上传API设计
#==========资源设计==========
#文件资源
POST/api/v1/files#上传文件
GET/api/v1/files/{id}#获取文件信息
DELETE/api/v1/files/{id}#删除文件
#==========上传示例==========
#方式一:直接上传(小文件)
POST/api/v1/files
Content-Type:multipart/form-data
Authorization:Bearer
WebKitFormBoundary
Content-Disposition:form-data;name="file";filename="image.jpg"
Content-Type:image/jpeg
WebKitFormBoundary--
#上传响应
{
"code":0,
"message":"success",
"data":{
"id":"f_abc123",
"filename":"image.jpg",
"size":102400,
"mime_type":"image/jpeg",
"url":"/f_abc123.jpg",
"created_at":"2026-09-19T10:30:00Z"
}
}
#方式二:分片上传(大文件)
#1.初始化上传
POST/api/v1/files/multipart/init
{
"filename":"video.mp4",
"size":104857600,
"chunk_size":5242880,
"total_chunks":20
}
#响应
{
"upload_id":"upload_abc123",
"chunks":[
{"chunk_index":0,"url":"..."},
...
]
}
#2.上传分片
PUT/api/v1/files/multipart/{upload_id}/chunks/{index}
Content-Type:application/octet-stream
#3.完成上传
POST/api/v1/files/multipart/{upload_id}/complete
{
"parts":[
{"chunk_index":0,"etag":"etag0"},
...
]
}
3.4RESTfulAPI完整示例
#使用SpringBoot实现RESTfulAPI
@RestController
@RequestMapping("/api/v1/orders")
publicclassOrderController{
@Autowired
privateOrderServiceorderService;
//查询订单列表
@GetMapping
publicApiResponse>listOrders(
@RequestParam(required=false)Stringstatus,
@RequestParam(required=false)LonguserId,
@RequestParam(defaultValue="1")Integerpage,
@RequestParam(defaultValue="20")@Max(100)IntegerpageSize,
@RequestParam(defaultValue="-created_at")Stringsort){
OrderQueryquery=OrderQuery.builder()
.status(status)
.userId(userId)
.page(page)
.pageSize(pageSize)
.sort(sort)
.build();
PageResultresult=orderService.queryOrders(query);
returnApiResponse.success(result);
}
//查询订单详情
@GetMapping("/{id}")
publicApiResponsegetOrder(@PathVariableLongid){
OrderDetailVOorder=orderService.getOrderDetail(id);
returnApiResponse.success(order);
}
//创建订单
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
publicApiResponsecreateOrder(
@Valid@RequestBodyCreateOrderRequestrequest){
OrderVOorder=orderService.createOrder(request);
returnApiResponse.success(order);
}
//全量更新订单
@PutMapping("/{id}")
publicApiResponseupdateOrder(
@PathVariableLongid,
@Valid@RequestBodyUpdateOrderRequestrequest){
OrderVOorder=orderService.updateOrder(id,request);
returnApiResponse.success(order);
}
//部分更新订单
@PatchMapping("/{id}")
publicApiResponsepatchOrder(
@PathVariableLongid,
@RequestBodyPatchOrderRequestrequest){
OrderVOorder=orderService.patchOrder(id,request);
returnApiResponse.success(order);
}
//删除订单
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
publicvoiddeleteOrder(@PathVariableLongid){
orderService.deleteOrder(id);
}
//取消订单
@PostMapping("/{id}/cancel")
publicApiResponsecancelOrder(
@PathVariableLongid,
@RequestBodyCancelOrderRequestrequest){
orderService.cancelOrder(id,request.getReason());
returnApiResponse.success();
}
}
//统一响应包装
@Data
publicclassApiResponse{
privateintcode;
privateStringmessage;
privateTdata;
privateStringrequestId;
publicstaticApiResponsesuccess(Tdata){
ApiResponseresponse=newApiResponse<>();
response.setCode(0);
response.setMessage("success");
response.setData(data);
response.setRequestId(MDC.get("requestId"));
returnresponse;
}
publicstaticApiResponseerror(intcode,Stringmessage){
ApiResponseresponse=newApiResponse<>();
response.setCode(code);
response.setMessage(message);
response.setRequestId(MDC.get("requestId"));
returnresponse;
}
}
//全局异常处理
@RestControllerAdvice
publicclassGlobalExceptionHandler{
@ExceptionHandler(BusinessException.class)
publicResponseEntity>handleBusiness(
BusinessExceptione){
returnResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.error(e.getCode(),e.getMessage()));
}
@ExceptionHandler(MethodArgumentNotValidException.class)
publicResponseEntity>>
handleValidation(MethodArgumentNotValidExceptione){
Listerrors=e.getBindingResult()
.getFieldErrors()
.stream()
.map(fe->newFieldError(fe.getField(),fe.getDefaultMessage()))
.collect(Collectors.toList());
ApiResponse>response=
ApiResponse.error(10001,"参数校验失败");
response.setErrors(errors);
returnResponseEntity.badRequest().body(response);
}
@ExceptionHandler(Exception.class)
publicResponseEntity>handleUnknown(Exceptione){
log.error("未预期的异常",e);
returnResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.error(50000,"服务器内部错误"));
}
}
第四章GraphQL设计原则
4.1GraphQL的核心思想
GraphQL是Facebook于2015年开源的API查询语言。它允许客户端精确声明需要的数据结构,服务端返回客
户端所需的数据,不多也不少。这解决了REST中的两个核心问题:过度获取(返回不需要的字段)和获取不足
(需要多个请求才能拿到完整数据)。
GraphQL的核心概念包括:Schema(模式)、Query(查询)、Mutation(变更)、Subscription(订阅)、
Resolver(解析器)。Schema定义了API的能力边界,Query用于读取数据,Mutation用于修改数据,Subscription
用于实时数据推送,Resolver定义了每个字段如何获取数据。
4.2GraphQLvsREST核心差异
维度RESTGraphQL
端点多个端点,每个资源一个单一端点/graphql
数据获取服务端决定返回什么客户端声明需要什么
过度获取常见问题不存在
请求次数可能需要多次一次请求获取所有数据
类型系统可选(OpenAPI)强制(Schema)
缓存HTTP缓存成熟需要客户端缓存
学习曲线低中等
适用场景简单CRUD复杂数据聚合
4.3Schema设计规范
#GraphQLSchema定义示例
#标量类型
scalarDateTime
scalarURL
scalarJSON
#枚举类型
enumOrderStatus{
PENDING
PAID
SHIPPED
DELIVERED
CANCELLED
}
#对象类型
typeUser{
id:ID!
username:String!
email:String!
phone:String
avatar:URL
status:UserStatus!
createdAt:DateTime!
updatedAt:DateTime!
orders(first:Int=20,after:String):OrderConnection!
}
typeOrder{
id:ID!
orderNo:String!
user:User!
items:[OrderItem!]!
totalAmount:Float!
status:OrderStatus!
receiver:Receiver!
createdAt:DateTime!
paidAt:DateTime
}
typeOrderItem{
id:ID!
product:Product!
quantity:Int!
unitPrice:Float!
totalPrice:Float!
}
typeReceiver{
name:String!
phone:String!
address:String!
}
#连接类型(分页)
typeOrderConnection{
edges:[OrderEdge!]!
pageInfo:PageInfo!
totalCount:Int!
}
typeOrderEdge{
node:Order!
cursor:String!
}
typePageInfo{
hasNextPage:Boolean!
hasPreviousPage:Boolean!
startCursor:String
endCursor:String
}
#输入类型
inputCreateOrderInput{
userId:ID!
items:[OrderItemInput!]!
receiver:ReceiverInput!
remark:String
}
inputOrderItemInput{
productId:ID!
quantity:Int!
}
inputReceiverInput{
name:String!
phone:String!
address:String!
}
#查询类型
typeQuery{
#用户查询
user(id:ID!):User
users(
first:Int=20,
after:String,
filter:UserFilter,
orderBy:UserOrderBy
):UserConnection!
#订单查询
order(id:ID!):Order
orders(
first:Int=20,
after:String,
filter:OrderFilter
):OrderConnection!
#当前用户
me:User
}
#变更类型
typeMutation{
#用户操作
createUser(input:CreateUserInput!):UserPayload!
updateUser(id:ID!,input:UpdateUserInput!):UserPayload!
deleteUser(id:ID!):DeletePayload!
#订单操作
createOrder(input:CreateOrderInput!):OrderPayload!
cancelOrder(id:ID!,reason:String):OrderPayload!
payOrder(id:ID!,payMethod:PayMethod!):OrderPayload!
}
#订阅类型
typeSubscription{
orderCreated(userId:ID!):Order!
orderStatusChanged(orderId:ID!):Order!
}
#输入过滤类型
inputUserFilter{
keyword:String
status:UserStatus
createdAfter:DateTime
createdBefore:DateTime
}
inputUserOrderBy{
field:UserOrderField!
direction:SortDirection!
}
enumUserOrderField{
CREATED_AT
USERNAME
ID
}
enumSortDirection{
ASC
DESC
}
#响应Payload类型
typeUserPayload{
user:User
errors:[Error!]
}
typeOrderPayload{
order:Order
errors:[Error!]
}
typeDeletePayload{
success:Boolean!
errors:[Error!]
}
typeError{
code:String!
message:String!
field:String
}
4.4GraphQL设计原则
原则一:Schema优先。先设计Schema,再实现Resolver。Schema是API的契约,应该由前后端共同设计,
作为协作的基础。
原则二:字段命名清晰。使用小驼峰命名法(camelCase),字段名要表达明确的语义,避免缩写和歧义。
原则三:避免深层嵌套。嵌套层级过深会导致查询复杂、性能问题。一般不超过4-5层。
原则四:使用连接类型分页。遵循Relay规范,使用Connection类型实现分页,支持游标分页。
原则五:输入和输出分离。使用Input类型定义输入,使用Payload类型定义输出。
原则六:错误处理规范化。业务错误放在Payload的errors字段中,系统错误通过GraphQL的标准错误机
制返回。
4.5GraphQL查询示例
#基础查询
query{
user(id:"123"){
id
username
createdAt
}
}
#嵌套查询
query{
user(id:"123"){
id
username
orders(first:10){
edges{
node{
id
orderNo
totalAmount
status
items{
product{
name
price
}
quantity
}
}
}
}
}
}
#带变量的查询
queryGetUserWithOrders($userId:ID!,$orderCount:Int!){
user(id:$userId){
id
username
orders(first:$orderCount){
edges{
node{
orderNo
totalAmount
}
}
}
}
}
#变量
{
"userId":"123",
"orderCount":5
}
#带别名的查询(同一字段多次查询)
query{
firstUser:user(id:"123"){
username
}
secondUser:user(id:"456"){
username
}
}
#片段复用
fragmentUserBasiconUser{
id
username
}
query{
user(id:"123"){
...UserBasic
orders(first:5){
edges{
node{
orderNo
}
}
}
}
}
#变更
mutationCreateOrder($input:CreateOrderInput!){
createOrder(input:$input){
order{
id
orderNo
totalAmount
status
}
errors{
code
message
field
}
}
}
#变量
{
"input":{
"userId":"123",
"items":[
{"productId":"456","quantity":2}
],
"receiver":{
"name":"张三",
"phone":,
"address":"北京市朝阳区某某路1号"
}
}
}
#订阅
subscription{
orderStatusChanged(orderId:"12345"){
id
orderNo
status
updatedAt
}
}
第五章GraphQL实战范例
5.1GraphQL服务端实现(Node.js)
//使用ApolloServer实现GraphQL服务
const{ApolloServer,gql}=require('apollo-server-express');
constexpress=require('express');
//1.定义Schema
consttypeDefs=gql`
scalarDateTime
typeUser{
id:ID!
username:String!
email:String!
orders(first:Int=20,after:String):OrderConnection!
}
typeOrder{
id:ID!
orderNo:String!
user:User!
totalAmount:Float!
status:OrderStatus!
createdAt:DateTime!
}
enumOrderStatus{
PENDING
PAID
SHIPPED
DELIVERED
CANCELLED
}
typeOrderConnection{
edges:[OrderEdge!]!
pageInfo:PageInfo!
totalCount:Int!
}
typeOrderEdge{
node:Order!
cursor:String!
}
typePageInfo{
hasNextPage:Boolean!
endCursor:String
}
typeQuery{
user(id:ID!):User
users(first:Int=20,after:String):UserConnection!
me:User
}
typeMutation{
createOrder(input:CreateOrderInput!):OrderPayload!
}
inputCreateOrderInput{
items:[OrderItemInput!]!
}
inputOrderItemInput{
productId:ID!
quantity:Int!
}
typeOrderPayload{
order:Order
errors:[Error!]
}
typeError{
code:String!
message:String!
}
typeUserConnection{
edges:[UserEdge!]!
pageInfo:PageInfo!
totalCount:Int!
}
typeUserEdge{
node:User!
cursor:String!
}
`;
//2.实现Resolver
constresolvers={
Query:{
user:async(_,{id},{dataSources,user})=>{
if(!user)thrownewAuthenticationError('未登录');
returndataSources.userAPI.getUser(id);
},
users:async(_,{first,after},{dataSources})=>{
constusers=awaitdataSources.userAPI.getUsers({
first,
after
});
return{
edges:users.map(u=>({
node:u,
cursor:Buffer.from(`user:${u.id}`).toString('base64')
})),
pageInfo:{
hasNextPage:users.length===first,
endCursor:users.length>0
?Buffer.from(`user:${users[users.length-1].id}`)
.toString('base64')
:null
},
totalCount:awaitdataSources.userAPI.countUsers()
};
},
me:async(_,__,{user})=>{
if(!user)returnnull;
returnuser;
}
},
Mutation:{
createOrder:async(_,{input},{dataSources,user})=>{
if(!user){
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年初中成语故事《困兽犹斗》左传战争思辨教案
- 2026年初中成语故事《当仁不让》论语担当精神教案
- 2026年秋季开学消防安全教育第一课
- 2026年初中《行香子》漫步田园闲适自在词教案
- 三上语文阅读理解考点与答题模板
- 2026中学班主任工作经验分享课件-青春期学生的心理疏导
- 机械行业维修部技师机械故障维修手册
- 安防行业指挥中心队长现场指挥调度手册
- 2026年秋班级感恩父母主题教育课件
- 基于神经过程的关系推理结题报告
- 2026年甘肃省金昌市规划建筑设计院招聘专业技术人员笔试备考试题及答案详解
- 2026年市场监管政务案例分析题专项真题及答案
- 2026年微电子科学与工程专业保研高频面试题包含详细解答
- 新版2025秋湘科版科学二年级上册教学设计(附目录)合集5
- 2026年中医康复理疗师考试题及答案
- 2026年度全省动物检疫技能大比武考试复习题库及答案
- 2026庐陵新区禾埠街道办事处面向社会公开招聘编外工作人员6人笔试模拟试题及答案详解
- 《课堂碎嘴子的代价》主题班会课件
- 2026年保安证考试全面提升试题及答案
- 2026-2027学年统编版九年级语文上册第一次月考综合检测卷(含答案)
- 五上5.1《中国人民站起来了-新中国的成立》教学课件
评论
0/150
提交评论