安阳市文章资讯

前后端ajax和json数据交换方式

2026-03-25 11:42:02 浏览次数:3
详细信息

一、基础概念

1. AJAX (Asynchronous JavaScript and 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 格式化工具

这种数据交换方式已成为现代 Web 开发的标准,理解并掌握这些技术对于全栈开发至关重要。

相关推荐