SpringMVC Day 04 : 数据绑定

前言

SpringMVC是一个非常流行的Java Web框架,它提供了很多方便的功能和工具来帮助我们构建高效、灵活的Web应用程序。其中,数据绑定就是SpringMVC中非常重要的一部分,它可以帮助我们方便地将请求参数绑定到Java对象上,从而简化了我们的开发流程。

在本篇博客中,我们将深入探讨SpringMVC中的数据绑定机制,包括如何定义绑定规则、如何处理绑定错误等内容。希望本文能够对您理解SpringMVC的数据绑定机制有所帮助。

一、什么是数据绑定

数据绑定是一种编程技术,用于将数据模型的值自动地与用户界面元素(如文本框、标签、下拉菜单等)进行同步。当数据模型中的值发生变化时,这些变化会自动地反映在用户界面元素中,反之亦然。数据绑定可以减少开发人员的工作量,提高应用程序的可维护性和可重用性。

数据绑定可以分为单向绑定和双向绑定两种类型。单向绑定是指只有在数据模型中的值发生变化时,才会更新用户界面元素的值。而双向绑定则是指在数据模型中的值发生变化时,不仅会更新用户界面元素的值,同时也会将用户界面元素中的值更新到数据模型中。

二、前期准备

1、新建项目,结构如下

2、添加依赖
    <dependencies><!-- springmvc 依赖,会将spring的核心包一并添加进来 --><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.23</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.5</version></dependency></dependencies>
3、配置 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>

用于配置 Servlet 的映射和加载。在 Spring MVC 中,它用于配置 DispatcherServlet 的初始化和请求映射。

具体来说,这段配置的作用如下:

  1. 定义了一个名为 "dispatcher" 的 Servlet,并指定了 org.springframework.web.servlet.DispatcherServlet 作为其处理类。
  2. 设置了 load-on-startup 属性为 1,表示在应用启动时就加载该 Servlet。
  3. 使用 <servlet-mapping> 元素将 "dispatcher" Servlet 映射到所有的请求路径上(即 <url-pattern>/</url-pattern>),意味着所有的请求都会经过该 Servlet 进行处理。

 这段配置的作用是将所有的请求交给 DispatcherServlet 处理,并让它成为应用的核心控制器。DispatcherServlet 将根据请求的 URL 和其他配置信息,将请求分发给相应的处理器方法进行处理,然后返回响应结果。

4、新建并配置 dispacther-servlet.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:mcv="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 启用扫描 --><context:component-scan base-package="edu.nf.ch04"/><!-- mvc 注解驱动 --><mvc:annotation-driven/><!-- 默认 servlet 处理静态资源 --><mcv:default-servlet-handler/><!-- 内部资源视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean></beans>

这段 XML 配置的作用如下:

  1. <context:component-scan>:用于扫描指定包下的组件,并将其注册为 Spring 容器中的 Bean。这样可以自动发现和管理这些组件,使它们可以在应用程序中被使用。
  2. <mvc:annotation-driven>:启用 MVC 注解驱动,使得 Spring MVC 可以处理注解相关的请求映射、参数绑定、数据转换等操作。通过这个配置,你可以使用注解来定义控制器、请求映射、请求参数等,简化了开发过程。
  3. <mvc:default-servlet-handler>:启用默认的静态资源处理器。当有静态资源请求时(如 CSS、JS 文件),Spring MVC 将不会处理这些请求,而是将其交给容器的默认 Servlet 处理。这样可以提高性能并减少不必要的开销。
  4. <mvc:resources>:将指定路径下的静态资源映射到指定的 URL 路径上。在这个例子中,mapping="page/**" 表示将以 /page/ 开头的 URL 路径映射到静态资源,location="/static/" 表示静态资源的存放路径为 /static/。这样配置后,当访问以 /page/ 开头的 URL 路径时,Spring MVC 会将对应的静态资源返回给客户端。
  5. <bean>:定义了一个内部资源视图解析器 InternalResourceViewResolver,用于将逻辑视图名称解析为具体的 JSP 视图路径。prefix 属性表示 JSP 文件的前缀路径,suffix 属性表示 JSP 文件的后缀名。通过这个配置,可以简化控制器中返回视图的处理过程。

这段配置主要是为了实现 Spring MVC 的基本功能,包括组件扫描、注解驱动、静态资源处理和视图解析等。它们共同协作,使得开发者可以更方便地开发和管理 Spring MVC 应用程序。
 

 5、在 entity 包下新建三个实体类 User、Card、address

User 

/*** @Date 2023-10-20* @Author qiu* 映射到实体的时候,字段名与请求中的 name 保持一致**/
@Data
public class User {private String userName;private Integer age;private Date birth;private List<String> tel;// 一对一关联private Card card;// 一对多关联private List<Address> addresses;}

 Card

@Data
public class Card {private String cardNum;
}

Address

@Data
public class Address {private String addr;}

二、把数据保存到作用域中

1、使用原生 servlet 

@Controller
@Slf4j
public class UserController {@PostMapping("/add")public ModelAndView add(HttpServletRequest request){String userName = request.getParameter("username");String age = request.getParameter("age");log.info(userName + "  "+ age);// 将参数当如请求作用域中request.setAttribute("username",userName);request.setAttribute("age",age);return new ModelAndView("index");}}

是一个基于Spring MVC框架的UserController类,其中包含了一个add()方法,用于处理HTTP POST请求。在该方法中,使用HttpServletRequest对象获取了请求参数(即用户名和年龄),并将它们记录在日志中。

接着,使用HttpServletRequest对象将这些参数放入请求作用域中,以便在返回视图时能够在页面上显示这些参数。最后,使用ModelAndView对象将逻辑视图名("index")返回给前端控制器DispatcherServlet,以便DispatcherServlet能够找到对应的视图并进行渲染。

2、通过 modelAndView 将参数放入请求作用域
@Controller
@Slf4j
public class UserController {@PostMapping("/add")public ModelAndView add(HttpServletRequest request){String userName = request.getParameter("username");String age = request.getParameter("age");log.info(userName + "  "+ age);// 通过 modelAndView 将参数放入请求作用域ModelAndView index = new ModelAndView("index");index.addObject("username",userName);index.addObject("age",age);return index;}}

创建了一个ModelAndView对象,将逻辑视图名("index")作为构造函数的参数传入。然后,使用ModelAndView的addObject()方法将用户名和年龄作为键值对添加到ModelAndView对象中,以便在返回视图时能够在页面上显示这些参数。

 3、运行效果
 1)、在 index.html  页面中完成一个提交表单
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>添加用户</h1>
<form action="../add2" method="post">Name:<input type="text" name="username" value="user"><br>Age:<input type="text" name="age" value="2000"><br><input type="submit" value="提交">
</form></body>
</html>

注意:这个 name 定义了以后,在控制器中就是获取这个 name 来获取它的 value 的。 

2)在 index.jsp 中获取 index.html 提交的数据

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>首页</h1>
用户名:${requestScope.username}<br>
年龄:${requestScope.age}<br>
</body>
</html>
 3) 运行效果

 4)使用原生 servlet 保存数据到作用域和 modelAndView 将参数放入请求作用域有什么区别

在使用原生 Servlet 时,可以通过不同的方式将数据保存到作用域中,包括请求作用域、会话作用域和应用程序作用域。对于保存数据到作用域的不同方式,以及将参数放入请求作用域和使用 modelAndView 的区别,可以进行如下解释:

  1. 请求作用域:

    • 使用 request.setAttribute(String name, Object value) 方法将数据保存到请求作用域中。
    • 请求作用域的生命周期仅限于一次请求,当请求完成后,作用域中的数据会被销毁。
    • 请求作用域适合在同一个请求中的多个 Servlet 或 JSP 页面之间共享数据。
  2. modelAndView:

    • modelAndView 是一种模式,通常与 MVC(Model-View-Controller)架构一起使用。
    • 在 modelAndView 中,数据被封装在一个特定的对象中,该对象包含模型数据和视图信息。
    • 模型数据是指需要传递给视图显示的数据,而视图信息则指定了要显示的视图的名称或路径。
    • modelAndView 可以通过方法参数或返回值来传递,并且可以在控制器中进行处理和操作。
    • modelAndView 适合在 MVC 架构中,将处理逻辑和数据展示分离,提供更好的代码组织和可维护性。

区别:

  • 生命周期:请求作用域的生命周期仅限于一次请求,而 modelAndView 可以在多个请求之间传递数据。
  • 使用方式:请求作用域需要手动将数据保存到作用域中,而 modelAndView 是通过方法参数或返回值来传递数据。
  • MVC 架构:modelAndView 通常与 MVC 架构一起使用,更适合于大型应用程序的开发和维护。
  • 数据封装:modelAndView 将数据封装在一个对象中,提供了更好的数据组织和管理。

总结: 如果只是在同一个请求中传递数据,可以使用请求作用域;如果是在 MVC 架构中进行数据传递和视图展示,可以选择使用 modelAndView。具体选择哪种方式取决于项目需求和架构设计。

 

三、将请求数据直接绑定到参数上

1、使用默认参数名
 @PostMapping("/add2")public ModelAndView add2(String userName , Integer userAge,String[] tel, Date birth){// 通过 modelAndView 将参数放入请求作用域ModelAndView index = new ModelAndView("index");// 将参数保存到请求作用域index.addObject("username",userName);index.addObject("age",userAge);index.addObject("tel1",tel[0]);index.addObject("tel2",tel[1]);index.addObject("birth",birth);return index;}

该方法将接收到的参数数据保存到请求作用域中,并将请求重定向到名为 "index" 的视图。

 2、使用 @RequestParam 注解
@PostMapping("/add2")public ModelAndView add2(@RequestParam(value = "username" ,required = true,defaultValue = "aaaa") String userName , @RequestParam("age") Integer userAge,String[] tel, Date birth){// 通过 modelAndView 将参数放入请求作用域ModelAndView index = new ModelAndView("index");// 将参数保存到请求作用域index.addObject("username",userName);index.addObject("age",userAge);index.addObject("tel1",tel[0]);index.addObject("tel2",tel[1]);index.addObject("birth",birth);return index;}

将请求数据直接绑定到参数上,默认参数名与请求中的 name 保持一致即可映射。否则使用 @RequestParam 注解

  1. required = true:必须提交
  2. defaultValue = "aaaa":设置默认值
1) 这里需要对日期时间进行处理
 /*** 注册自定义转换器,@InitBinder 注解标注的方法会在执行* 任何 controller 的方法之前先执行,spring 会传入* 一个 webBinder 的参数,使用这个参数可以注册任意的 Formatter* @param binder 数据绑定器,用于注册各种格式化类*/@InitBinderpublic void regFormatter(WebDataBinder binder){binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));}

 该 regFormatter 方法用于注册一个自定义的日期格式化器,将日期字符串按照格式 "yyyy-MM-dd" 进行解析和格式化。这样,在处理请求时,如果遇到需要将日期字符串转换为 Date 类型的情况,就会使用该自定义的格式化器进行处理。

3 运行效果
 1)在 index.html 中完成提交
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>添加用户</h1>
<form action="../add" method="post">Name:<input type="text" name="username" value="user"><br>Age:<input type="text" name="age" value="2000"><br>Tel1:<input type="text" name="tel" value="123123213213"><br>Tel2:<input type="text" name="tel" value="1231231233"><br>brith:<input type="text" name="birth" value="2000-05-03"><br><input type="submit" value="提交">
</form></body>
</html>
2) 在 index.jsp 获取 index.html 提交的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>首页</h1>
用户名:${requestScope.username}<br>
年龄:${requestScope.age}<br>
电话1:${requestScope.tel1}<br>
电话2:${requestScope.tel2}<br>
生日:${requestScope.birth}<br>
</body>
</html>
3)运行

 

 四、获取 list 集合中的数据

1、完成控制器
 @PostMapping("/add3")public ModelAndView add3(User user){// 通过 modelAndView 将参数放入请求作用域ModelAndView index = new ModelAndView("index");// 将参数保存到请求作用域index.addObject("username",user.getUserName());index.addObject("age",user.getAge());index.addObject("tel1",user.getTel().get(0));index.addObject("tel2",user.getTel().get(1));index.addObject("birth",user.getBirth());index.addObject("cardNum",user.getCard().getCardNum());log.info(user.getCard().getCardNum() + "========");index.addObject("addr1",user.getAddresses().get(0).getAddr());index.addObject("addr2",user.getAddresses().get(1).getAddr());return index;}

// 一对多关联
private List<Address> addresses; 实体类封装的是一个集合类型的实体,所这里获取就通过 addresses.get(0).getAddr();取获取第一个参数,以此类推。

  2、在 index.html 中完成提交
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>添加用户</h1>
<form action="../add2" method="post">Name:<input type="text" name="username" value="user"><br>Age:<input type="text" name="age" value="2000"><br>Tel1:<input type="text" name="tel" value="123123213213"><br>Tel2:<input type="text" name="tel" value="1231231233"><br>brith:<input type="text" name="birth" value="2000-05-03"><br>idCard:<input type="text" name="card.cardNum" value="440990191929293939"><br>addr1:<input type="text" name="addresses[0].addr" value="珠海"><br>addr2:<input type="text" name="addresses[1].addr" value="霞山"><br><input type="submit" value="提交">
</form></body>
</html>

 需要使用对象嵌套和集合嵌套的方式来处理。在表单元素中,可以通过 [0][1] 等索引来访问集合中的元素,如果有多个号码,也可以通过 .tel1.tel2 等属性名来访问对象中的属性。

3、在 index.jsp 中获取 index.html 提交的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>首页</h1>
用户名:${requestScope.username}<br>
年龄:${requestScope.age}<br>
电话1:${requestScope.tel1}<br>
电话2:${requestScope.tel2}<br>
生日:${requestScope.birth}<br>
身份证:${requestScope.cardNum}<br>
住址1:${requestScope.addr1}<br>
住址2:${requestScope.addr2}<br>
</body>
</html>
 4、运行效果

五、路径参数绑定

1、完成控制器
/*** 路径参数绑定* 请求格式:/url地址/(变量)* 并且使用 @PathVariable 注解* @param uid* @return*/@GetMapping("/user/{id}")public ModelAndView getUser(@PathVariable("id") String uid){String aa = "";ModelAndView mav = new ModelAndView("index");mav.addObject("uid",uid);return mav;}

创建了一个ModelAndView对象,并将逻辑视图名("index")作为构造函数的参数传入。然后,使用ModelAndView的addObject()方法将路径变量"uid"添加到ModelAndView对象中,以便在返回视图时能够在页面上显示该参数。

@PathVariable注解的value属性用于指定路径变量名,如果方法参数名和路径变量名一致,则可以省略value属性。另外,@PathVariable注解还有其他可选属性,例如required、defaultValue等,用于指定路径变量是否必需,以及默认值等。 

 2、在 index.jsp 中获取路径传递的参数
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1>首页</h1>
路径参数:${requestScope.uid}<br>
</body>
</html>
3、运行效果

六、总结

 参数绑定是指将HTTP请求中的参数值绑定到方法的参数上,以便在方法中使用这些参数进行业务逻辑处理。在Spring MVC框架中,参数绑定可以通过多种方式实现,包括使用@RequestParam注解、使用@PathVariable注解、使用HttpServletRequest对象等。

总结参数绑定的几个关键点如下:

  1. @RequestParam注解:用于将请求参数绑定到方法的参数上。可以指定参数名、是否必需、默认值等属性。适用于GET和POST请求。

  2. @PathVariable注解:用于将路径变量绑定到方法的参数上。可以指定路径变量名,并通过@PathVariable注解的value属性指定参数名。适用于RESTful风格的URL。

  3. HttpServletRequest对象:可以通过HttpServletRequest对象获取请求参数。适用于需要对请求参数进行更加复杂的处理或访问其他请求相关信息的情况。

参数绑定的优势在于简化了开发过程,避免了手动解析请求参数的繁琐操作。同时,参数绑定也提供了一定的灵活性,可以根据具体业务需求选择不同的参数绑定方式。

需要注意的是,在进行参数绑定时,应该考虑安全性和可靠性。对于用户输入的参数,应该进行合法性验证和防御性编程,以避免潜在的安全漏洞和错误。此外,还应该注意参数类型的匹配和转换,确保参数能够正确地绑定到方法的参数上。

总而言之,参数绑定是Spring MVC框架中非常重要的功能之一,可以方便地获取和处理HTTP请求中的参数值,提高开发效率和代码可读性。在使用参数绑定时,需要注意安全性和可靠性,并根据具体业务需求选择合适的参数绑定方式。

七、gitee 案例

地址:ch04 · qiuqiu/SpringMVC - 码云 - 开源中国 (gitee.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/151558.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++模拟实现-----日期计算器(超详细解析,小白一看就会!)

目录 一、前言 二、日期类计算器 三、日期计算器的实现 &#x1f34e;日期计算器各个接口的实现 &#x1f350;日期计算器的需求 &#x1f349;打印当前日期&#xff08;并检查日期是否合理&#xff09; &#x1f4a6;检查日期是否合理 &#x1f4a6;日期类构造函数&#x…

[计算机提升] Windows系统各种开机启动方式介绍

1.14 开机启动 在Windows系统中&#xff0c;开机启动是指开启电脑后&#xff0c;自动运行指定的程序或服务的技术。一些程序或服务需要在开机后自动启动&#xff0c;以便及时响应用户操作&#xff0c;比如防安防软件、即时通信工具、文件同步软件等。 同时&#xff0c;一些系统…

soc的复位reset/rst问题

本节不去讨论同步复位与异步复位以及异步复位的reset_release&#xff0c;这些问题可参考&#xff1a;芯片设计进阶之路——Reset深入理解——cy413026 本机主要回答一下几个问题。 1.片外的reset信号特别是按键reset怎么防止错误抖动的影响&#xff1f; 常见的处理方法包括两…

STM32F4VGT6-DISCOVERY:uart1驱动

对于这款板子&#xff0c;官方并没有提供串口例程&#xff0c;只能自行添加。 一、PA9/PA10复用成串口1功能不可用 驱动测试代码如下&#xff1a; main.c: #include "main.h" #include <stdio.h>void usart1_init(void) {GPIO_InitTypeDef GPIO_InitStruct…

CAN接口的PCB Layout规则要求汇总

随着时代高速发展&#xff0c;控制器局域网&#xff08;CAN&#xff09;接口的应用越来越广泛&#xff0c;尤其是在汽车电子、航空航天等领域中发挥着重要作用&#xff0c;为了确保CAN接口的可靠性和稳定性&#xff0c;工程师必须在其PCB Layout方面下功夫&#xff0c;下面来看…

JVM虚拟机:Java对象的头信息有什么?

本文重点 在前面的课程中,我们学习了对象头,其中对象头包含Mark Word和class pointer,当然数组还会有一个数组长度。本文主要分析Mark Work中包含的信息。 Mark Word 以下两张图是一个意思: 32位 32位 64位 以上就是Mark Word会存储的信息,这个意思是说Java对象在不同…

FPGA时序分析与约束(7)——通过Tcl扩展SDC

一、概述 术语“Synopsys公司设计约束”&#xff08;又名SDC&#xff0c;Synopsys Design Constraints&#xff09;用于描述对时序、功率和面积的设计要求&#xff0c;是EDA工具中用于综合、STA和布局布线最常用的格式。本文介绍时序约束的历史概要和SDC的描述。 二、时序约束…

node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)

文章目录 ⭐前言⭐ 环境准备⭐ 实现过程⭐ mysql 配置⭐路由前的准备⭐账号注册生成token⭐账号登录生成token⭐token登录 ⭐ 自测过程截图⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于node实战——后端koa项目配置jwt实现登录注册&#xff08;n…

VScode 自定义主题各参数解析

参考链接&#xff1a; vscode自定义颜色时各个参数的作用(史上最全)vscode编辑器&#xff0c;自己喜欢的颜色 由于 VScode 搜索高亮是在是太不起眼了&#xff0c;根本看不到此时选中到哪个搜索匹配了&#xff0c;所以对此进行了配置&#xff0c;具体想增加更多可配置项可参考…

windows + ubuntu + vscode开发环境配置安装

一、卸载WSL/WSL2 如果安装了windows子系统的朋友&#xff0c;可以选择继续使用。或者提前卸载WSL&#xff0c;再选择安装虚拟机。虚拟机占用内存较大&#xff0c;WSL可能对于开发的一些需求还有欠缺。根据自己的实际情况进行选择。 WIN10/11安装WSL(请参考官方资料&#xff0c…

nvm的安装和使用

nvm用途 nvm是用来管理node版本的,安装成功之后可以去切换自己的node版本,就不需要通过安装卸载不同版本的node包 下载与安装 下载地址是https://github.com/coreybutler/nvm-windows/releases 下载nvm-setup.zip,然后安装就可以了 默认路径是C:\Users\wangjingtao\AppData\…

NPM【问题 01】npm i node-sass@4.14.1报错not found: python2及Cannot download问题处理

node-sass安装问题处理 1.问题2.处理2.1 方案一【我的环境失败】2.2 方案二【成功】2.3 方案三【成功】 1.问题 gyp verb which failed Error: not found: python2 # 1.添加Python27的安装路径到环境变量 gyp verb check python checking for Python executable "python…