GraphQL 是由 Facebook(现 Meta)于 2015 年开源的 API 查询语言和运行时。GraphQL 允许客户端 精确指定需要的数据,解决了 RESTful API 的过获取(Over-fetching)和欠获取(Under-fetching)问题。
GraphQL 的核心定位是 灵活的 API 查询语言。它提供了:
# GraphQL Schema 定义
type Query {
user(id: ID!): User
users: [User]
}
type Mutation {
createUser(name: String!, email: String!): User
updateUser(id: ID!, name: String): User
deleteUser(id: ID!): Boolean
}
type Subscription {
userCreated: User
}
type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
author: User!
}
# 基本查询
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
age
posts {
title
content
}
}
}
# 变量
{
"id": "123"
}
# 嵌套查询
query GetUserWithPosts {
user(id: "123") {
name
email
posts {
title
content
author {
name
email
}
}
}
}
# 别名
query GetUsers {
user1: user(id: "1") { name }
user2: user(id: "2") { name }
}
# 片段(Fragments)
fragment UserFields on User {
id
name
email
}
query GetUser {
user(id: "123") {
...UserFields
age
}
}
# 创建用户
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
email
}
}
# 变量
{
"input": {
"name": "Alice",
"email": "alice@example.com",
"age": 30
}
}
# 更新用户
mutation UpdateUser($id: ID!, $name: String!) {
updateUser(id: $id, name: $name) {
id
name
email
}
}
# 删除用户
mutation DeleteUser($id: ID!) {
deleteUser(id: $id)
}
# 实时订阅
subscription OnUserCreated {
userCreated {
id
name
email
}
}
# 订阅多个事件
subscription OnUserUpdate {
userCreated { id name }
userDeleted { id }
}
# 查询 Schema 类型
query IntrospectionQuery {
__schema {
types {
name
kind
description
fields {
name
type {
name
kind
}
}
}
}
}
# 查询特定类型
query GetUserType {
__type(name: "User") {
name
fields {
name
type {
name
kind
}
}
}
}
// 使用 Apollo Server
const { ApolloServer, gql } = require("apollo-server");
// 类型定义
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
age: Int
}
type Query {
user(id: ID!): User
users: [User]
}
type Mutation {
createUser(name: String!, email: String!): User
}
`;
// 模拟数据
const users = [
{ id: "1", name: "Alice", email: "alice@example.com", age: 30 },
{ id: "2", name: "Bob", email: "bob@example.com", age: 25 },
];
// 解析器
const resolvers = {
Query: {
user: (_, { id }) => users.find(u => u.id === id),
users: () => users,
},
Mutation: {
createUser: (_, { name, email }) => {
const user = { id: String(users.length + 1), name, email };
users.push(user);
return user;
},
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
# 使用 Graphene
import graphene
class User(graphene.ObjectType):
id = graphene.ID()
name = graphene.String()
email = graphene.String()
age = graphene.Int()
class Query(graphene.ObjectType):
user = graphene.Field(User, id=graphene.ID(required=True))
users = graphene.List(User)
def resolve_user(self, info, id):
return next((u for u in users if u.id == id), None)
def resolve_users(self, info):
return users
class CreateUser(graphene.Mutation):
class Arguments:
name = graphene.String(required=True)
email = graphene.String(required=True)
user = graphene.Field(User)
def mutate(self, info, name, email):
user = User(id=str(len(users)+1), name=name, email=email)
users.append(user)
return CreateUser(user=user)
class Mutation(graphene.ObjectType):
create_user = CreateUser.Field()
schema = graphene.Schema(query=Query, mutation=Mutation)
// 使用 GraphQL-PHP
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
$userType = new ObjectType([
"name" => "User",
"fields" => [
"id" => Type::id(),
"name" => Type::string(),
"email" => Type::string(),
"age" => Type::int(),
]
]);
$queryType = new ObjectType([
"name" => "Query",
"fields" => [
"user" => [
"type" => $userType,
"args" => [
"id" => Type::nonNull(Type::id()),
],
"resolve" => function($root, $args) use ($users) {
return array_filter($users, function($u) use ($args) {
return $u["id"] === $args["id"];
})[0] ?? null;
}
],
"users" => [
"type" => Type::listOf($userType),
"resolve" => function() use ($users) {
return $users;
}
]
]
]);
$schema = new Schema([
"query" => $queryType
]);
$rawInput = file_get_contents("php://input");
$input = json_decode($rawInput, true);
$query = $input["query"] ?? "";
$variables = $input["variables"] ?? null;
$result = GraphQL::executeQuery($schema, $query, null, null, $variables);
$output = $result->toArray();
echo json_encode($output);
// Spring Boot GraphQL 控制器
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
@Controller
public class GraphQLController {
@Autowired
private UserService userService;
@QueryMapping
public User user(@Argument Long id) {
return userService.findById(id);
}
@QueryMapping
public List<User> users() {
return userService.findAll();
}
@MutationMapping
public User createUser(@Argument String name, @Argument String email) {
return userService.createUser(name, email);
}
}
// React 使用 Apollo Client
import { ApolloClient, InMemoryCache, gql, useQuery } from "@apollo/client";
const client = new ApolloClient({
uri: "http://localhost:4000/graphql",
cache: new InMemoryCache(),
});
const GET_USERS = gql`
query GetUsers {
users {
id
name
email
}
}
`;
function Users() {
const { loading, error, data } = useQuery(GET_USERS);
if (loading) return Loading...
;
if (error) return Error: {error.message}
;
return (
{data.users.map(user => (
- {user.name} - {user.email}
))}
);
}
// Vue 使用 Apollo Client
<template>
<div>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="user in users" :key="user.id">
{{ user.name }} - {{ user.email }}
</li>
</ul>
</div>
</template>
<script>
import { useQuery } from "@vue/apollo-composable";
import gql from "graphql-tag";
export default {
setup() {
const { result, loading, error } = useQuery(gql`
query GetUsers {
users {
id
name
email
}
}
`);
return {
users: result.value?.users || [],
loading,
error,
};
},
};
</script>
| 对比项 | GraphQL | RESTful |
|---|---|---|
| 数据获取 | 按需查询 | 固定端点 |
| 过/欠获取 | 不会 | 可能 |
| 端点数量 | 单个 | 多个 |
| 版本管理 | Schema 演进 | URL 版本 |
| 缓存 | 需要自定义 | HTTP 缓存 |
| 学习曲线 | 较陡 | 平缓 |
| 类型安全 | 强类型 Schema | 无内置类型 |
| 适用场景 | 复杂数据查询 | 通用 API |
GraphQL 核心概念、Schema 定义、查询语法、变量
Apollo Server(Node.js)、Graphene(Python)、GraphQL-PHP
Apollo Client(React)、Vue Apollo、URQL
订阅(Subscriptions)、缓存策略、联邦(Federation)
GraphQL 是 API 设计的"精准工具"。
它用 按需查询、强类型 Schema、单一端点 解决了 RESTful API 的多个痛点。GraphQL 是构建现代 API 的新一代标准,特别适合移动端和复杂数据查询场景。
掌握 GraphQL,意味着你能 构建更灵活、更高效、更易维护的 API。
"GraphQL 让 API 从被动服务变成了按需响应。" 📡