RequestBody 和 RequestParam

如果 params 对象中还包含嵌套对象,那么在构建查询字符串和解析参数时需要更复杂的处理。以下是如何在前端和后端处理这种情况的示例。

前端代码

假设我们有一个包含嵌套对象的 params

const params = {
  name: "John",
  age: 30,
  address: {
    city: "New York",
    zip: "10001"
  },
  cities: ["New York", "Los Angeles", "Chicago"]
};
 
const buildQueryString = (params, parentKey) => {
  if(params === null) {return ""}
  const queryString = Object.keys(params).map(key => {
    const fullKey = parentKey ? `${parentKey}[${key}]` : key;
    if (Array.isArray(params[key])) {
      return params[key].map(item => `${encodeURIComponent(fullKey)}=${encodeURIComponent(item)}`).join('&');
    } else if (typeof params[key] === 'object') {
      return buildQueryString(params[key], fullKey);
    } else {
      return `${encodeURIComponent(fullKey)}=${encodeURIComponent(params[key])}`;
    }
  }).join('&');
  return queryString;
};
 
const queryString = buildQueryString(params);
const baseUrl = 'https://api.example.com/data';
const url = `${baseUrl}?${queryString}`;
 
fetch(url, {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

这个 buildQueryString 函数会递归地处理嵌套对象,并将它们转换为查询字符串。

后端代码(使用 Spring Boot 和 @ModelAttribute

创建模型类

首先,定义模型类来表示你的参数,包括嵌套对象:

public class Address {
    private String city;
    private String zip;
 
    // Getters and Setters
    public String getCity() {
        return city;
    }
 
    public void setCity(String city) {
        this.city = city;
    }
 
    public String getZip() {
        return zip;
    }
 
    public void setZip(String zip) {
        this.zip = zip;
    }
}
 
public class UserRequest {
    private String name;
    private int age;
    private Address address;
    private List<String> cities;
 
    // Getters and Setters
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Address getAddress() {
        return address;
    }
 
    public void setAddress(Address address) {
        this.address = address;
    }
 
    public List<String> getCities() {
        return cities;
    }
 
    public void setCities(List<String> cities) {
        this.cities = cities;
    }
}

控制器代码

使用 @ModelAttribute 注解来绑定查询参数到模型对象:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class MyController {
 
    @GetMapping("/data")
    public UserRequest getData(@ModelAttribute UserRequest userRequest) {
        return userRequest;
    }
}

在这个示例中:

  • @ModelAttribute 用于将查询参数绑定到 UserRequest 对象。
  • Spring 会自动解析查询字符串并将参数值填充到 UserRequestAddress 对象中。

启动 Spring Boot 应用

确保你的 Spring Boot 应用已经正确配置和启动。通常,你的 Spring Boot 应用主类看起来像这样:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

测试

启动 Spring Boot 应用后,前端代码会发送一个 GET 请求到 http://localhost:8080/data(假设默认端口为 8080),后端会自动解析查询参数并返回填充后的 UserRequest 对象作为 JSON 响应。

注意事项

  1. 参数名称匹配 :确保前端传递的参数名称与后端模型类的字段名称匹配。例如,嵌套对象的参数名应为 address[city]address[zip]
  2. 类型匹配 :确保前端传递的参数类型与后端模型类的字段类型匹配。
  3. 数组处理 :Spring 会自动将重复的查询参数绑定到一个列表中,无需额外处理。

结论

通过在前端构建查询字符串并在 Spring 后端使用 @ModelAttribute 注解,可以使用 GET 请求传递包含嵌套对象和数组的复杂参数。@ModelAttribute 提供了一种简洁的方式来将查询参数绑定到模型对象,使得参数处理更加简便和结构化。如果数据量较大或包含敏感信息,推荐使用 POST 请求。