一、基础概念
1. AJAX (Asynchronous JavaScript and XML)
- 异步 JavaScript 和 XML
- 实现无需刷新页面的数据交换
- 现多用 JSON 替代 XML
2. JSON (JavaScript Object Notation)
{
"name": "张三",
"age": 25,
"isStudent": false,
"hobbies": ["阅读", "运动"],
"address": {
"city": "北京"
}
}
二、前端实现(JavaScript)
1. 使用原生 Fetch API(推荐)
// GET 请求
async function getData() {
try {
const response = await fetch('/api/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
}
});
if (!response.ok) throw new Error('请求失败');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
// POST 请求
async function postData() {
const data = { username: 'user', password: '123456' };
const response = await fetch('/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
return result;
}
// 带查询参数的 GET
fetch('/api/users?page=1&limit=10')
.then(res => res.json())
.then(data => console.log(data));
2. 使用 Axios(更简洁)
import axios from 'axios';
// GET 请求
axios.get('/api/data', {
params: { page: 1, limit: 10 },
headers: { 'Authorization': 'Bearer token' }
})
.then(response => console.log(response.data))
.catch(error => console.error(error));
// POST 请求
axios.post('/api/users', {
name: '李四',
email: 'lisi@example.com'
})
.then(response => {
console.log('创建成功:', response.data);
});
// 全局配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
3. 错误处理与拦截器
// 请求拦截器
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
// 响应拦截器
axios.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
// 跳转到登录页
window.location.href = '/login';
}
return Promise.reject(error);
}
);
三、后端实现
1. Node.js + Express
const express = require('express');
const app = express();
// 中间件:解析 JSON 请求体
app.use(express.json());
// 处理 CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
next();
});
// GET 接口
app.get('/api/users', (req, res) => {
const { page = 1, limit = 10 } = req.query;
res.json({
success: true,
data: {
users: [...],
pagination: { page, limit, total: 100 }
},
message: '获取成功'
});
});
// POST 接口
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
// 验证逻辑...
if (valid) {
res.status(200).json({
success: true,
data: { token: 'jwt_token', userInfo: {...} },
message: '登录成功'
});
} else {
res.status(401).json({
success: false,
message: '用户名或密码错误'
});
}
});
// 统一的错误处理
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
success: false,
message: '服务器内部错误',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
});
2. Spring Boot(Java)
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public ResponseEntity<ApiResponse> getUsers(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int limit) {
List<User> users = userService.getUsers(page, limit);
return ResponseEntity.ok(
ApiResponse.success()
.data("users", users)
.data("pagination", pagination)
.message("获取成功")
);
}
@PostMapping("/login")
public ResponseEntity<ApiResponse> login(@RequestBody LoginRequest request) {
User user = userService.login(request);
return ResponseEntity.ok(
ApiResponse.success()
.data("token", token)
.data("user", user)
.message("登录成功")
);
}
}
// 统一响应格式
@Data
class ApiResponse {
private boolean success;
private Object data;
private String message;
public static ApiResponse success() {
ApiResponse response = new ApiResponse();
response.setSuccess(true);
return response;
}
}
3. Django(Python)
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
@csrf_exempt
def api_users(request):
if request.method == 'GET':
page = request.GET.get('page', 1)
limit = request.GET.get('limit', 10)
data = {
'success': True,
'data': {
'users': [...],
'pagination': {...}
},
'message': '获取成功'
}
return JsonResponse(data)
elif request.method == 'POST':
try:
data = json.loads(request.body)
# 处理数据...
return JsonResponse({'success': True, 'message': '创建成功'})
except Exception as e:
return JsonResponse({'success': False, 'message': str(e)}, status=400)
四、最佳实践
1. 统一的响应格式
{
"success": true/false,
"data": {}, // 成功时的数据
"message": "", // 提示信息
"code": "200", // 业务状态码
"timestamp": "2024-01-01T00:00:00Z"
}
2. 错误码规范
// HTTP 状态码 + 业务状态码
const ErrorCodes = {
SUCCESS: 200,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
INTERNAL_ERROR: 500,
// 业务错误码
USER_NOT_EXIST: 1001,
PASSWORD_ERROR: 1002,
TOKEN_EXPIRED: 1003
};
3. 安全性考虑
// 1. CSRF 防护
// 后端生成 token,前端携带
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken;
// 2. 请求防抖
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// 3. 数据验证
const validateData = (data) => {
if (!data.username || data.username.length < 3) {
throw new Error('用户名至少3位');
}
// 更多验证...
};
4. 文件上传
// 前端
const formData = new FormData();
formData.append('file', file);
formData.append('userId', '123');
axios.post('/api/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
// 后端(Express)
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.post('/api/upload', upload.single('file'), (req, res) => {
const file = req.file;
// 处理文件...
});
五、现代化方案
1. 使用 React Hooks
import { useState, useEffect } from 'react';
function useApi(url, options = {}) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url, options);
const result = await response.json();
setData(result.data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
2. 使用 TypeScript 类型定义
interface ApiResponse<T = any> {
success: boolean;
data: T;
message: string;
code: number;
}
interface User {
id: number;
name: string;
email: string;
}
// 类型安全的请求
async function getUser(id: number): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
六、调试工具
浏览器开发者工具:Network 标签页
Postman:API 测试
curl 命令:命令行测试
curl -X GET "https://api.example.com/users" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123"
JSON 格式化工具:
- JSON.stringify(obj, null, 2)
- 浏览器 JSON 格式化扩展
这种数据交换方式已成为现代 Web 开发的标准,理解并掌握这些技术对于全栈开发至关重要。