JavaEE 进阶第八期:Spring MVC - Web开发的“交通枢纽”(二)

专栏:JavaEE 进阶跃迁营

个人主页:手握风云

目录

一、请求

[1.1. 传递单个参数](#1.1. 传递单个参数)

[1.2. 传递多个参数](#1.2. 传递多个参数)

[1.3. 传递对象](#1.3. 传递对象)

[1.4. 后端参数重命名(@RequestParam)](#1.4. 后端参数重命名(@RequestParam))

[1.5. 传递数组](#1.5. 传递数组)

[1.6. 传递集合](#1.6. 传递集合)

[1.7. 传递 JSON 数据](#1.7. 传递 JSON 数据)

[1. JSON 的概念](#1. JSON 的概念)

[2. JSON 的语法规则](#2. JSON 的语法规则)

[3. JSON 与 Java 对象的互转(基于 Spring MVC)](#3. JSON 与 Java 对象的互转(基于 Spring MVC))

[4. 传递 JSON 对象](#4. 传递 JSON 对象)


一、请求

在 Spring MVC 中,"请求" 核心是实现前端与后端的参数传递与接收,即前端通过浏览器或接口测试工具(如 Postman)传递参数,后端通过特定语法和注解接收参数。

后端开发人员无需过度关注如何传递参数,了解即可,实际开发中以Postman测试为主。比如餐厅的厨师,不关注用户是在店里下单,还是外卖平台下单,或者小程序下单,只需要知道如何接收订单,根据订单做出对应的菜肴就可以了。

1.1. 传递单个参数

接收方式:直接在 Controller 方法中定义与前端参数名一致的形参,Spring MVC 自动匹配赋值。

java 复制代码
package com.yang.test1_1;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r1")
    public String r1(String name) {
        return "接收的参数 name = " + name;
    }

    @RequestMapping("/r2")
    public String r2(Integer age) {
        return "接收的参数 age = " + age;
    }
}

注意事项:

  • 若参数名不一致,后端接收为 null
  • 基本类型(如 int)参数必传 ,否则报 500 错误;建议用包装类型(如 Integer),非必传时默认 null
  • 参数类型不匹配(如 age = abc)时,报 400 错误。

1.2. 传递多个参数

接收方式 :方法中定义多个形参,Spring MVC 按 参数名 匹配(与参数顺序无关)。

java 复制代码
package com.yang.test1_2;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r3")
    public String r3(String name, String password, int age) {
        return "接收到的参数 name:" + name + ",password:" + password + ",age:" + age;
    }
}

1.3. 传递对象

  • 适用场景:参数较多时(如用户注册、表单提交),将参数封装为 Java 对象。
  • 接收方式 :方法形参直接定义为封装后的对象,Spring MVC 按 对象属性名 与前端参数名匹配赋值。
java 复制代码
package com.yang.test1_2_1;

public class Person {
    String name;
    String password;
    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}
java 复制代码
package com.yang.test1_2_1;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r4")
    public String r4(Person person) {
        return person.toString();
    }
}
  • 注意事项 :未传递的属性,基本类型默认赋值(如 int 为 0),引用类型为 null

1.4. 后端参数重命名(@RequestParam)

前端传递的参数名与后端接收的参数名不一致的情况下可以使用这种方式。@RequestParam,通过 value 指定前端参数名,required 控制是否必传(默认 true)。

java 复制代码
package com.yang.test1_5_1;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r6")
    public String r6(@RequestParam("sa") String resource) {
        return "接收到的参数 resource: " + resource; // 把参数 sa 绑定给 resource
    }
}

但是我们如果把参数 sa 改成 resource,再次启动就会发现报错"400 Bad Request",我们同时查看 IntelliJ IDEA 的控制台区域会发现,参数 sa 不存在。我们查看一下 RequestParam 的源码会发现里面的 required 默认值为 true。如果我们只是想改名又不是必须传参数,就可以把 required 指定为 false。

java 复制代码
package com.yang.test1_5_1;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r6")
    public String r6(@RequestParam(value = "sa", required = false) String resource) {
        return "接收到的参数 resource: " + resource;
    }
}

1.5. 传递数组

方法形参定义为数组类型,前端传递多个相同参数名的参数,Spring MVC 自动封装为数组。

java 复制代码
package com.yang.test1_5_2;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r7")
    public String r7(String[] names) {
        return "接收到的参数 names: " + Arrays.toString(names);
    }
}

1.6. 传递集合

不光是数组,集合也可以接收。但是一点击 Send 会出现 "500 Internal Server Error"。我们查看控制台会出现 "No primary or single unique constructor found for interface java.util.List"。这是因为 List 是一个接口,不能进行实例化对象。这时我们就可以使用 @RequestParam 注解绑定成 List 类型。

java 复制代码
package com.yang.test1_5_2;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r8")
    public String r8(List<String> names) {
        return "接收到的参数 names: " + names;
    }
}
java 复制代码
package com.yang.test1_5_2;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r8")
    public String r8(@RequestParam(value = "names", required = false) List<String> names) {
        return "接收到的参数 names: " + names;
    }
}

1.7. 传递 JSON 数据

1. JSON 的概念

JSON(JavaScript Object Notation,JavaScript 对象表示法)是一种轻量级的数据交互格式,核心用于不同编程语言、不同平台间的数据传递与交换,其设计初衷是简化数据存储与表示,同时具备跨语言、易解析的特性,是当前 Web 开发(尤其是前后端分离架构)中主流的数据交换格式之一。

JSON 本质是字符串,通过特定语法的文本描述对象或数组信息,并非编程语言中的 "对象" 或 "数组"。

2. JSON 的语法规则

JSON 有严格的语法规范,不符合规范的 JSON 会被判定为无效,无法正常解析,核心规则如下:

  1. 数据以键值对(Key/Value) 形式存在,键(Key)必须用双引号 " 包裹(单引号无效),值(Value)支持多种类型(字符串、数字、布尔值、null、对象、数组);

  2. 多个键值对 / 值之间用逗号 , 分隔(最后一个元素后不能加逗号);

  3. 对象大括号 {} 包裹,代表无序的键值对集合;

  4. 数组中括号 [] 包裹,代表有序的值集合(值的类型可不同,如 ["hello", 3.14, true]);

  5. 值(Value)的合法类型:

    • 基本类型:字符串(双引号包裹)、数字(整数 / 浮点数,如 183.14)、布尔值(true/false)、null(无 undefined);
    • 复杂类型:对象(嵌套对象,如 {"user": {"name": "zhangsan", "age": 18}})、数组(嵌套数组,如 {"hobbies": ["reading", ["basketball", "football"]]})。

    // 1. 对象格式
    {"name": "admin", "age": 18, "isStudent": false, "address": {"city": "Beijing"}}

    // 2. 数组格式
    ["hello", 3.14, null, {"key": "value"}]

    // 3. 对象数组格式(最常用场景)
    [{"name": "zhangsan", "age": 20}, {"name": "lisi", "age": 22}]

3. JSON 与 Java 对象的互转(基于 Spring MVC)

在 Java 开发中,JSON 需与 Java 对象(如实体类)互相转换才能实现业务逻辑,Spring MVC 已集成 jackson-databind 工具包(无需额外引入依赖),通过 ObjectMapper 类实现转换。

XML 复制代码
<!-- 核心依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.5</version> 
</dependency>

ObjectMapper 提供两个核心方法,实现 JSON 与 Java 对象的双向转换:writeValueAsString():将 Java 对象转为 JSON 字符串;readValue():将 JSON 字符串转为 Java 对象。

java 复制代码
package com.yang.test1_5_3;

public class Person {
    private String name;
    private String password;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }
}
java 复制代码
package com.yang.test1_5_3;

import org.springframework.boot.test.context.SpringBootTest;
import tools.jackson.databind.ObjectMapper;

@SpringBootTest
public class JSONUtils {

    private static ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) {
        Person person = new Person();

        person.setAge(24);
        person.setName("Nash");
        person.setPassword("12345");

        String value = objectMapper.writeValueAsString(person);
        System.out.println(value);

        String json = "{\"age\":24,\"name\":\"Nash\",\"password\":\"12345\"}";
        Person person1 = objectMapper.readValue(json, Person.class);
        System.out.println(person1.toString());
    }
}

4. 传递 JSON 对象

关键注解:@RequestBody,表示从 请求体 中获取 JSON 数据,绑定到 Java 对象。

java 复制代码
package com.yang.test1_6_1;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/request")
@RestController
public class RequestController {
    @RequestMapping("/r9")
    public String r9(@RequestBody Person person) {
        return "接收到的参数 person: " + person.toString();
    }
}
相关推荐
pas1368 分钟前
28-mini-vue customRender
前端·javascript·vue.js
REDcker12 分钟前
web 端 H265 软解码实现原理与使用说明
前端·音视频·播放器·h265·解码·软解码
倚栏听风雨16 分钟前
深度拆解:从 npm install 到手写一个全局 CLI 工具
前端
攀登的牵牛花17 分钟前
前端向架构突围系列 - 架构方法(二):UML前端建模的一般方法和工具
前端·前端框架·uml
代码猎人18 分钟前
Object.assign和扩展运算符是深拷贝还是浅拷贝,两者有什么区别
前端
秋天的一阵风19 分钟前
🎥解决前端 “复现难”:rrweb 录制回放从入门到精通
前端·javascript·开源
意法半导体STM3219 分钟前
【文末送NUCLEO-G431RB】一文说明白STM32G4双Bank启动与升级 LAT1596
前端·数据库·stm32·单片机·嵌入式硬件·mcu·stm32开发
前端一课19 分钟前
分享:基于Next.js的企业级提示词AI平台
前端
小高00721 分钟前
🔥「从零到一」我用 Node BFF 手撸一个 Vue3 SSR 项目(附源码)
前端·javascript·vue.js
SailingCoder23 分钟前
AI 流式对话该怎么做?SSE、fetch、axios 一次讲清楚
前端·javascript·人工智能·ai·node.js