人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。———— 马尔科姆·格拉德威尔

不知道大家有没有遇到过这样一个情况:看着公司controller层接口,有的参数加上@RequestBody,有的参数又没有加,代码风格层出不穷。明明前端数据已经传过来,为什么总是接收不到?

在 HTTP 协议中,客户端(如浏览器、Postman、前端代码)向服务器发送请求时会携带请求头和请求体等信息,可以通过分析请求体与请求体中的信息来选择使用哪种方式接收前端数据。

存在以下几种主要方式传递数据:
1. Request Payload(JSON/XML 等结构化数据)
2. Query String Parameters(URL 参数)
3. Form Data(表单数据)
4. Path Variables(路径参数)
5. Headers(请求头)
6. Cookies
7. GraphQL(特殊请求体)
8. WebSocket(双向通信)

一、Request Payload(JSON/XML 等结构化数据)

Request Payload请求主要是向服务端发送JSON、XML等结构化数据

请求体Content-Type类型application/jsonapplication/xml, text/plain

特点:

  • 数据放在请求体(Body)中,适用于复杂结构(如嵌套对象、数组)。
  • 后端通常用 @RequestBody 接收(Spring系列 框架)。

示例:

POST /api/data HTTP/1.1
Content-Type: application/json 👈 通常在前几行

{"orderProductId": "123", "batchNumbers": ["001", "002"]}
@PostMapping("/payload")
public String handleJson(@RequestBody OrderRequest request) {
    return "Received: " + request.getOrderProductId() + ", " + request.getBatchNumbers();
}

@Data 
public static class OrderRequest {
    private String orderProductId;
    private List<String> batchNumbers;
}

二、Query String Parameters(URL 参数)

使用GET请求时常遇到,通过请求地址后面拼接参数的方式进行请求。

格式:?key1=value1&key2=value2

特点:

  • 数据附加在 URL 后,适用于简单参数。
  • 后端用 @RequestParam 接收(Spring),当方法参数名和URL参数名完全一致时可省略。

示例:

GET /query?orderProductId=123&batchNumbers=001&batchNumbers=002 HTTP/1.1
@GetMapping("/query")
public String handleQuery(@RequestParam String orderProductId,
                          @RequestParam List<String> batchNumbers) {
    return "Query: " + orderProductId + ", " + batchNumbers;
}

三、Form Data(表单数据)

常见于各种前端框架中,是所有前端框架(如 React、Vue、Angular 等)和原生 HTML 表单的基础支持特性。

请求体Content-Type类型:application/x-www-form-urlencodedmultipart/form-data

特点:

  • x-www-form-urlencoded:键值对格式,类似 Query String,但放在请求体中。
  • multipart/form-data:支持文件上传。

示例:

<!-- 原生 HTML 表单 -->
<form action="/submit" method="post" enctype="application/x-www-form-urlencoded">
  <input name="username" value="John">
  <input name="password" value="123456">
  <button type="submit">Submit</button>
</form>

<!-- Vue -->
const formData = new FormData();
formData.append('username', 'John');
formData.append('avatar', fileInput.files[0]);

fetch('/api/upload', {
  method: 'POST',
  body: formData  // 自动设置 Content-Type: multipart/form-data
});

<!-- Axios 等 HTTP 库 -->
// 发送 x-www-form-urlencoded
axios.post('/api/login', 'username=John&password=123456', {
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});

// 发送 multipart/form-data(文件上传)
const formData = new FormData();
formData.append('file', file);
axios.post('/api/upload', formData);
//  接收 x-www-form-urlencoded
@PostMapping("/login")
public String login(
    @RequestParam String username,
    @RequestParam String password) {
    return "User: " + username;
}

// 接收 multipart/form-data(文件上传)
@PostMapping("/upload")
public String upload(
    @RequestParam String description,
    @RequestPart MultipartFile file) {
    return "Uploaded: " + file.getOriginalFilename();
}

四、Path Variables(路径参数)

RESTful 风格规范,目前主流方式。

格式:/api/{orders}/{batches}

特点:

  • 用于 RESTful API 设计(如资源 ID)。
  • 后端用 @PathVariable 接收(Spring)。

示例:

GET /api/123/001 HTTP/1.1
@GetMapping("/path/{orderId}/{batchId}")
public String handlePath(
    @PathVariable String orderId,
    @PathVariable String batchId) {
    return "Path: " + orderId + ", " + batchId;
}

五、Headers(请求头)

常见于实现某些特殊功能,例如:身份认证(Authorization)跨域控制(CORS)语言本地化(Accept-Language)CSRF 防护(X-CSRF-Token)等等

特点:

  • 数据放在 HTTP 头中,适用于认证(如 Authorization)、元数据等。
  • 后端用 @RequestHeader 接收(Spring)。

示例:

## 身份认证(Authorization)##
传递 Token 或 API Key
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

axios.get('/user', {
  headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
});

@GetMapping("/user")
public String getUser(@RequestHeader("Authorization") String token) {
    // 解析 Token 获取用户信息
    return "User from token";
}
## 跨域控制(CORS)##
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST");
    }
}

六、Cookies

Cookies 在 Web 开发中主要用于客户端状态管理,通过浏览器自动存储和传递数据。

特点:

  • 数据由浏览器自动附加在请求头(Cookie: name=value)。
  • 后端用 @CookieValue 接收(Spring)。
  • 前端自动处理,浏览器后续请求能够自动携带该 Cookie。

示例:

## 用户会话管理(Session ID)##
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure

@PostMapping("/login")
public String login(HttpServletResponse response) {
    String sessionId = UUID.randomUUID().toString();
    Cookie cookie = new Cookie("sessionId", sessionId);
    cookie.setHttpOnly(true);
    cookie.setSecure(true); // 仅 HTTPS
    cookie.setPath("/");
    response.addCookie(cookie);
    return "Login success";
}
## 个性化设置(如主题/语言) ##
Set-Cookie: lang=zh-CN; Max-Age=2592000; Path=/

document.cookie = "lang=zh-CN; max-age=2592000; path=/";

@GetMapping("/news")
public String getNews(@CookieValue(value = "lang", defaultValue = "en") String lang) {
    return "Display news in " + lang;
}
## 个性化设置(如主题/语言) ##
Set-Cookie: cart=%7B%22items%22%3A%5B%7B%22id%22%3A101%7D%5D%7D; Path=/shop

@PostMapping("/add-to-cart")
public String addToCart(@CookieValue("cart") String cartJson, 
                       @RequestBody Item item) {
    Cart cart = objectMapper.readValue(cartJson, Cart.class);
    cart.addItem(item);
    // 返回更新后的 Cookie
}

七、GraphQL(特殊请求体)

GraphQL 是一种用于 API 的查询语言和运行时环境,它允许客户端精确请求所需的数据,避免了 REST API 中常见的过度获取或不足获取的问题。

GraphQL 通过其灵活的查询能力,非常适合数据关系复杂客户端需求多变的场景。

请求体Content-Type类型application/json

特点:

  • 通过 JSON 体指定查询语句,灵活获取数据。
  • 需后端单独支持 GraphQL 协议。

示例:Spring Boot 集成 GraphQL

<!-- 导入依赖 -->
<dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-spring-boot-starter</artifactId>
  <version>5.0.2</version>
</dependency>
<dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-java-tools</artifactId>
  <version>5.2.4</version>
</dependency>
# 创建 schema.graphqls 文件
# src/main/resources/schema.graphqls
type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
  email: String
  orders: [Order]
}

type Order {
  id: ID!
  totalPrice: Float
  items: [OrderItem]
}
@Component
public class UserResolver implements GraphQLQueryResolver {
    public User user(String id) {
        // 从数据库或服务获取数据
        return userService.getUserById(id);
    }
}

// 自动关联到 Schema 中的 `User.orders` 字段
@Component
public class OrderResolver implements GraphQLResolver<User> {
    public List<Order> orders(User user) {
        return orderService.getOrdersByUserId(user.getId());
    }
}
POST /graphql HTTP/1.1
Content-Type: application/json

## 默认端点为 /graphql,直接接收 POST 请求 ##
{
  "query": "query { user(id: \"123\") { name orders { id } }"
}

## 等同于下面 👇
query {
  user(id: "123") {
    name
    orders {
      id
    }
  }
}

八、WebSocket(双向通信)

WebSocket 是一种全双工通信协议,适用于需要**实时双向数据交互**的场景。

特点:

  • 建立长连接后,客户端和服务器可随时互发数据(非 HTTP 请求)。
  • 数据格式通常为 JSON 或二进制。

示例:Spring Boot 简单集成 websocket

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic", "/queue");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }
}
const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
    stompClient.subscribe('/topic/updates', (message) => {
        console.log('收到更新:', message.body);
    });
});

这里仅仅简单举例,WebSocket实际涉及的内容比较多,感兴趣的可以私下学习了解一下其实现原理以及集成第三方Mq组件和安全框架等等。

九、总结

方式 数据位置 后端接收注解(Spring) 适用场景
Request Payload 请求体(Body) @RequestBody 复杂结构(JSON/XML)
Query String URL 参数 @RequestParam 简单参数
Form Data 请求体(Body) @RequestParam 表单提交/文件上传
Path Variables URL 路径 @PathVariable RESTful 资源标识
Headers 请求头 @RequestHeader 认证、元数据
Cookies 请求头(自动附加) @CookieValue 会话管理
GraphQL 请求体(JSON) 自定义解析 灵活数据查询
WebSocket 独立协议 自定义处理器 实时双向通信

根据自己的需求选择合适的方式,大多数 API 优先使用 JSON Payload 或 Query String

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐