当前位置: 首页 > news >正文

SpringMVC 进阶:核心组件详解与参数绑定全攻略

引言

上一篇我们通过 HelloWorld 案例入门了 SpringMVC,但实际开发中,你可能会遇到 “如何接收复杂参数?”“不同组件有哪些实现选择?” 等问题。本文将带你深入 SpringMVC 的核心组件,拆解其底层逻辑,并详细讲解 “参数绑定” 这一高频开发场景,帮你解决 80% 的日常开发需求。

一、SpringMVC 核心组件深度解析

上一篇提到 5 个核心组件,本节将聚焦 “最关键的 3 个组件”,讲解其实现类、配置方式及适用场景。

1. HandlerMapping:请求与 Controller 的 “桥梁”

HandlerMapping的作用是 “根据请求 URL 找到对应的 Controller 方法”,SpringMVC 提供了多种实现,最常用的有 2 种:

(1)RequestMappingHandlerMapping(推荐,注解驱动)

基于@RequestMapping注解实现,支持 URL、请求方法(GET/POST)、请求参数等多维度匹配,是 SpringMVC 3.1 + 的默认选择。无需手动配置:只要在spring-mvc.xml中开启 “注解驱动”(如下),Spring 会自动注册该组件:

xml

<!-- 开启SpringMVC注解驱动(替代手动配置HandlerMapping和HandlerAdapter) -->
<mvc:annotation-driven/>
(2)BeanNameUrlHandlerMapping(传统,XML 配置)

基于 “Bean 名称” 映射请求,例如:

xml

<!-- 1. 配置HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/><!-- 2. 配置Controller Bean,名称以/开头 -->
<bean name="/user/list" class="com.example.controller.UserController"/>

适用场景:老项目维护,新项目优先用注解驱动。

2. HandlerAdapter:Controller 的 “执行者”

HandlerAdapter负责 “调用 Controller 方法”,并处理 “参数绑定、类型转换” 等前置工作。与HandlerMapping对应,常用实现类也分 2 种:

(1)RequestMappingHandlerAdapter(注解驱动配套)

RequestMappingHandlerMapping配对使用,支持@RequestMapping注解的 Controller 方法,自动处理参数绑定(如@RequestParam)、返回值解析(如ModelAndView)。无需手动配置:开启mvc:annotation-driven后自动注册。

(2)SimpleControllerHandlerAdapter(传统)

适配实现Controller接口的传统 Controller,例如:

java

运行

// 传统Controller(需实现Controller接口)
public class UserController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();mv.addObject("msg", "传统Controller");mv.setViewName("user/list");return mv;}
}

缺点:一个 Controller 只能处理一个请求,灵活性低,新项目不推荐。

3. ViewResolver:视图的 “定位器”

ViewResolver负责 “将视图名解析为实际视图对象”,常用实现类有 3 种,覆盖 JSP、Thymeleaf 等主流视图技术:

(1)InternalResourceViewResolver(JSP 视图,最常用)

解析 JSP 文件,配置方式如下(上一篇已用过):

xml

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"/> <!-- 视图目录 --><property name="suffix" value=".jsp"/> <!-- 视图后缀 --><property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <!-- 支持JSTL -->
</bean>

逻辑:若 Controller 返回视图名"user/list",则解析为/WEB-INF/views/user/list.jsp

(2)ThymeleafViewResolver(Thymeleaf 视图)

若项目用 Thymeleaf 替代 JSP,需配置该解析器(需导入 Thymeleaf-Spring 依赖):

xml

<!-- 1. 导入Thymeleaf依赖(pom.xml) -->
<dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.1.2.RELEASE</version>
</dependency><!-- 2. 配置Thymeleaf视图解析器 -->
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><property name="templateEngine" ref="templateEngine"/><property name="order" value="1"/> <!-- 解析顺序,越小越优先 -->
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver" ref="templateResolver"/>
</bean>
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"><property name="prefix" value="/WEB-INF/templates/"/> <!-- Thymeleaf文件目录 --><property name="suffix" value=".html"/> <!-- 后缀 --><property name="templateMode" value="HTML5"/>
</bean>
(3)FreeMarkerViewResolver(FreeMarker 视图)

类似 Thymeleaf,适用于 FreeMarker 模板引擎,配置逻辑一致,此处不展开。

二、参数绑定全攻略:接收请求参数的 9 种场景

“参数绑定” 是 SpringMVC 接收前端请求参数的核心能力,支持基本类型、对象、集合等多种场景,以下按 “常用程度” 排序讲解。

1. 场景 1:基本类型参数(int、String、boolean 等)

直接在 Controller 方法中声明参数,SpringMVC 会自动匹配请求参数名与方法参数名(大小写敏感)。

示例 1:接收单个参数
  • 请求 URL:http://localhost:8080/springmvc/user/query?id=1
  • Controller 方法:

java

运行

@RequestMapping("/user/query")
public String queryUser(int id) { // 参数名id与请求参数id一致System.out.println("查询用户ID:" + id);return "user/info";
}
示例 2:用 @RequestParam 指定参数名(参数名不一致时)

若请求参数名是userId,但方法参数名是id,需用@RequestParam映射:

java

运行

@RequestMapping("/user/query")
// required=true(默认):表示该参数必须传;defaultValue:默认值
public String queryUser(@RequestParam(name = "userId", required = true) int id) {System.out.println("查询用户ID:" + id);return "user/info";
}

2. 场景 2:POJO 对象参数(实体类参数)

若请求参数较多(如用户注册:姓名、年龄、邮箱),可将参数封装为 POJO 类,SpringMVC 会自动将请求参数注入到 POJO 的属性中(要求:POJO 属性名与请求参数名一致)。

示例:接收用户注册参数
    1. 定义 POJO 类User

java

运行

public class User {private String username;private Integer age;private String email;// 必须有默认无参构造器(SpringMVC反射创建对象)// Getter和Setter方法(必须,SpringMVC通过Setter注入参数)public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }// 其他Getter/Setter省略...
}
    1. Controller 方法:

java

运行

@RequestMapping("/user/register")
public String register(User user) { // 直接接收User对象System.out.println("用户名:" + user.getUsername());System.out.println("年龄:" + user.getAge());return "success";
}
    1. 前端请求(表单示例):

html

预览

<form action="/springmvc/user/register" method="post">用户名:<input type="text" name="username"><br> <!-- 与User属性名一致 -->年龄:<input type="text" name="age"><br>邮箱:<input type="text" name="email"><br><button type="submit">注册</button>
</form>

3. 场景 3:嵌套 POJO 参数(如用户 - 地址)

若 POJO 中包含另一个 POJO(如User包含Address),请求参数名需用 “.” 分隔层级。

示例:
    1. 定义Address类:

java

运行

public class Address {private String province;private String city;// Getter/Setter省略
}
    1. 改造User类,添加Address属性:

java

运行

public class User {private String username;private Address address; // 嵌套POJO// Getter/Setter省略
}
    1. 前端表单参数名:

html

预览

<!-- 参数名用address.province,对应User.address.province -->
地址-省份:<input type="text" name="address.province"><br>
地址-城市:<input type="text" name="address.city"><br>

4. 场景 4:集合参数(List、Map)

接收多个同类型参数(如批量删除用户 ID),需将集合封装到 POJO 中(直接接收 List 需特殊处理)。

示例 1:List 参数(批量删除)
    1. 定义 POJOUserList

java

运行

public class UserList {private List<Integer> ids; // 存储多个用户ID// Getter/Setter省略
}
    1. Controller 方法:

java

运行

@RequestMapping("/user/batchDelete")
public String batchDelete(UserList userList) {System.out.println("批量删除ID:" + userList.getIds()); // 如[1,2,3]return "success";
}
    1. 前端表单(参数名用ids[0]ids[1]):

html

预览

<!-- 批量选择用户ID -->
<input type="checkbox" name="ids[0]" value="1">用户1<br>
<input type="checkbox" name="ids[1]" value="2">用户2<br>
<input type="checkbox" name="ids[2]" value="3">用户3<br>
示例 2:Map 参数(灵活键值对)
    1. 定义 POJOUserMap

java

运行

public class UserMap {private Map<String, String> userInfo; // key=参数名,value=参数值// Getter/Setter省略
}
    1. 前端表单参数名(用userInfo['key']):

html

预览

<input type="text" name="userInfo['username']" value="张三"><br>
<input type="text" name="userInfo['age']" value="20"><br>

5. 场景 5:@PathVariable(URL 路径参数)

用于接收 URL 路径中的参数(如 RESTful 风格的/user/1中的1),示例:

  • 请求 URL:http://localhost:8080/springmvc/user/1
  • Controller 方法:

java

运行

// @PathVariable("id"):将URL中的{id}绑定到方法参数id
@RequestMapping("/user/{id}")
public String getUserById(@PathVariable("id") Integer id) {System.out.println("RESTful风格:查询用户ID=" + id);return "user/info";
}

6. 场景 6:@RequestBody(接收 JSON 参数)

前后端分离项目中,前端常发送 JSON 格式的请求体,需用@RequestBody接收(需开启mvc:annotation-driven,SpringMVC 会自动用 Jackson 解析 JSON)。

示例:
    1. 导入 Jackson 依赖(pom.xml):

xml

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version>
</dependency>
    1. Controller 方法:
// @RequestBody:将请求体的JSON解析为User对象
@RequestMapping(value = "/user/add", method = RequestMethod.POST)
@ResponseBody // 表示返回JSON(下一篇讲)
public String addUser(@RequestBody User user) {System.out.println("新增用户:" + user.getUsername());return "success";
}
    1. 前端发送 JSON 请求(Axios 示例):
axios.post('/springmvc/user/add', {username: '李四',age: 25,email: 'lisi@xxx.com'
}).then(res => {console.log(res.data);
});

7. 特殊场景:日期类型参数绑定

SpringMVC 默认不支持java.util.Date类型的参数绑定,需自定义类型转换器或用@DateTimeFormat注解。

示例:用 @DateTimeFormat 指定日期格式

@RequestMapping("/order/query")
public String queryOrder(@DateTimeFormat(pattern = "yyyy-MM-dd") Date orderDate) {System.out.println("订单日期:" + orderDate);return "order/list";
}
  • 请求参数:http://localhost:8080/springmvc/order/query?orderDate=2024-05-20

三、参数绑定常见问题与解决方案

  1. 中文乱码问题:原因:Tomcat 默认编码是 ISO-8859-1,无法处理中文;解决方案:在web.xml中配置编码过滤器(必须放在所有过滤器之前):

    <filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value> <!-- 强制响应编码为UTF-8 --></init-param>
    </filter>
    <filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern>
    </filter-mapping>
    
  2. 参数类型不匹配(400 错误):原因:请求参数类型与方法参数类型不匹配(如传字符串 “abc” 给 int 类型);解决方案:前端确保参数类型正确,或后端用@RequestParam(required = false)允许参数为空,并添加参数校验。

  3. List 参数无法直接接收:原因:SpringMVC 不支持直接将请求参数绑定到 List(需封装到 POJO);解决方案:参考 “场景 4”,将 List 封装到 POJO 中,或用@RequestBody接收 JSON 格式的 List。

四、进阶小结

  1. 核心组件选择:新项目优先用mvc:annotation-driven开启注解驱动,无需手动配置 HandlerMapping 和 HandlerAdapter;
  2. 参数绑定口诀:
    • 简单参数用@RequestParam,路径参数用@PathVariable
    • 多参数用 POJO,嵌套参数用 “.”;
    • JSON 参数用@RequestBody,日期参数加@DateTimeFormat
  3. 下一篇预告:SpringMVC 实战整合 MyBatis,实现完整的 CRUD 功能,带你打通 “前端 - Controller-Service-DAO - 数据库” 全链路。
http://www.dtcms.com/a/414199.html

相关文章:

  • SpringMVC 实战:整合 MyBatis 实现完整 CRUD
  • Interleaving-Reasoning-Generation - 交错推理生成技术
  • 【C++】:继承全面解析
  • 大良营销网站建设机构设计专业所需网站
  • Spark专题-第二部分:Spark SQL 入门(8)-算子介绍-sort
  • 知识体系_分布式内存计算框架_spark
  • 银行 网站开发 干什么wordpress路径错误
  • QML 语法基础详解
  • ExcelVBA一键生成智能散点趋势图
  • ✨WPF编程基础【1.4】:类型转换器(含示例及源码)
  • 公链分析报告 - 模块化区块链2
  • 数图实战项目(十五-2:第一阶段:从RAW数据到ISP管道,听不懂在说啥?---> 那就盘它):从奥运大屏,到手机小屏,快来挖一挖里面都有什么
  • 网站开发常见面试东莞网站优化关键词推广
  • GauGAN详解与实现
  • Word如何一次性合并多个文档
  • 互联网技术服务优化大师优化项目有
  • 状态管理库 Zustand 的接入流程与注意点
  • 河北网站建设推广电话wordpress网址导航主题
  • NFS 服务器 iSCSI 服务器
  • display this 概念、故障排错及题目
  • whisper-large-v3部署详细步骤,包括cpu和gpu方式,跟着做一次成功
  • 个人用云计算学习笔记 --16(DHCP 服务器)
  • 【Linux】基础IO与文件描述符
  • ​​FFmpeg 教程:从入门到精通,探索多媒体处理的瑞士军刀​
  • 使用ffmpeg8.0的whisper模块语音识别
  • 免费版Markdown 编辑器:Typora
  • 个人建网站有什么好处网站运营需要 做哪些工作
  • MySQL库、表的操作
  • FileProvider 配置必须针对 Android 7.0+(API 24+)做兼容
  • 混合止损策略在加密货币交易中的应用