SpringMVC | SpringMVC中的 “数据绑定”

news2024/11/14 1:32:14

目录:

    • “数据绑定” 介绍
      • 1.简单数据绑定 :
        • 绑定 “默认数据” 类型
        • 绑定 “简单数据类型” 类型 (绑定Java“基本数据类型”)
        • 绑定 “POJO类型”
        • 绑定 “包装 POJO”
        • “自定义数据” 绑定 :
          • Converter (自定义转换器)
      • 2.复杂数据绑定 :
        • 绑定数组
        • 绑定集合

在这里插入图片描述

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

该文章参考学习教材为:
《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著
文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

(侵权可联系我,进行删除,如果雷同,纯属巧合)


在前面的知识点中,可以知道后台的请求处理方法可以包含多种参数类型。在实际的项目开发中,多数情况下 客户端传递带有不同参数请求,那么后台是如何绑定并获取这些请求参数的呢? 本章将对Spring MVC 框架中的 数据绑定 进行详细讲解。

“数据绑定” 介绍

  • 执行程序时,Spring MVC根据客户端请求参数的不同,将请求消息中的信息一定的方式转换绑定控制器类方法参数中。这种将 请求消息数据后台方法参数建立连接过程就是 Spring MVC 中数据绑定
    ( SpringMVC会对前端的“请求参数”进行转换绑定到控制类的“方法参数”中 )

  • 数据绑定过程中Spring MVC 框架会通过数据绑定组件( DataBinder )将 请求参数串内容进行类型转换,然后将转换后值赋给控制器类方法形参,这样后台方法就可以正确绑定获取客户端请求携带参数了。
    SpringMVC框架通过 数据绑定组件 : DataBinder来对前端的 请求参数 进行 转换赋值控制器类方法参数”中

  • SpringMVC 数据绑定 过程如下图所示
    在这里插入图片描述

    (1) Spring MVCServletRequest对象 传递DataBinder (数据绑定组件)。
    (2)将处理方法入参对象 传递DataBinder
    (3) DataBinder 调用 ConversionService组件进行数据类型转换数据格式化等工作,并将ServletRequest对象中的消息填充参数对象中。
    (4)调用 Validator 组件对已经绑定了请求消息数据参数对象进行数据合法性校验
    (5)校验完成后生成数据绑定结果BindingResult 对象Spring MVC会将 BindingResult对象 中的内容赋给处理方法相应参数

  • 根据客户端请求参数类型个数的不同,我们将 Spring MVC 中的数据绑定主要分为 简单数据绑定复杂数据绑定

1.简单数据绑定 :

绑定 “默认数据” 类型
  • 前端请求的 参数比较简单 时,可以在后台方法形参直接使用Spring MVC提供的 默认参数类型 进行 数据绑定

  • 常用的 默认参数类型 如下 :(以HttpServletRequest类型为例进行演示

    “默认参数”类型描述
    HttpServletRequest通过request对象获取请求信息
    HttpServletResponse通过response 处理响应信息
    HttpSession通过session 对象得到 session 中存储的对象
    Model / ModelMapModel 是一个接口ModelMap 是一个接口实现,作用是将model数据填充request 域
  • 绑定“ 默认数据 类型 例子如下

    第一步创建项目,导入依赖
    Spring MVC所需JAR (百度网盘)

    第二步 :配置 web.xml文件springmvc-config.xml 文件 :

    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>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--  配置Springmvc-config.xml中的存放位置   -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-config.xml</param-value>
            </init-param>
            <!--  配置表示容器启动时立刻加载此Servlet  -->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!--  配置DispatcherServlet的“映射”  -->
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <!--  将所有请求进行“拦截”  -->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

    springmvc-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    	http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--  定义”组件扫描器“,进行根包扫描,让”注解“生效  -->
        <context:component-scan base-package="com.myh.controller"/>
    
        <!-- 配置“视图解析器” : 让return时只填“视图名”即可,不用填“全名” -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 设置“前缀”  -->
            <property name="prefix" value="WEB-INF/jsp/"/>
            <!-- 设置“前缀”  -->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    

    第三步、创建 UserController.javasuccess.jsp (视图) :

    UserController.java

    package com.myh.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    
    
    /**
     * @author 莫月辉
     * @desctiption
     * @since 2024/3/11 9:55
     */
    //使用注解定义了一个“控制器”类
    @Controller //将该类变成“控制器类”,替代“实现Controller接口的情况”。
    public class UserController {
    
        //设置前端请求访问的“路径”
        @RequestMapping("/selectUser")
        public String selectUser(HttpServletRequest request) {
            //获得前端存储在HttpServletRequest中的数据/参数
            String id = request.getParameter("id");
            System.out.println("前端要传递给后端的信息 : id = "+id);//前端的"url中"是会携带一个"名称为id"的参数的
            //通过“视图解析器”来寻找到指定的视图,且返回给前端
            return "success"; //通过String返回值类型,返回一个视图给前端
        }
    
    }
    

    在上面的UserController.java代码中,使用注解方式定义了一个控制器类,同时定义了 方法访问路径。在方法参数中使用了 HttpServletRequest类型,并通过该对象getParameter( )方法获取了指定的参数 ( 简而言之前端存储参数url中后端通过 HttpServletRequest 对象来获得前端要传递的参数 / 数据 )。后端做出的响应是 : 返回一个视图给前端 。SpringMVC会通过视图解析器在“/WEB-INF/jsp/”路径下寻找success.jsp 文件。

    success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>结果页面</title>
    </head>
    <body>
    
    OK
    
    </body>
    </html>
    

    第四步配置Tomcat运行后前端url中输入 http://localhost:8080/selectUser?id=1 来访问后端,后端做出响应
    在这里插入图片描述

    从上图可以看出,后台方法已从请求(url)正确地获取到了id参数信息,这说明使用默认
    HttpServletRequest参数类型已经完成了数据绑定

    即前端存储数据在url中后端通过HttpServletRequest 参数类型来获取“前端传递”的“参数”的过程)。

绑定 “简单数据类型” 类型 (绑定Java“基本数据类型”)
  • 简单数据类型”的绑定,就是指 Java几种基本数据类型绑定intStringDouble等类型。这里仍然 以绑定 “默认数据” 类型的例子基础进行修改部分代码即可

  • 绑定“简单数据类型 类型 例子如下 : (以绑定 “默认数据” 类型的例子基础,进行部分代码修改 :)第一步
    修改控制器类,将控制器类UserController中的selectUser( )方法参数修改为使用简单数据类型 (Java中的“基本数据类型)的形式

        //设置前端请求访问的“路径”
        @RequestMapping("/selectUser")
        public String selectUser(Integer id) {  //处理器方法中设置的参数类型为 : 简单数据类型 (Java中的基本数据类型)
            System.out.println("id = "+id);
            return "success"; //通过String返回值类型,返回一个视图给前端
        }
    

    默认数据类型案例中的selectUser()方法相比,此方法中只是HttpServletRequest 参数类型替换为了 Integer 类型

    启动项目,并在浏览器中访问地址http://localhost:8080/selectUser?id=1 ,此时可以发现浏览器正确跳转success.jsp页面 :
    在这里插入图片描述


  • 从上面的“运行结果可以看出,使用 简单数据类型 同样完成了数据绑定,但是用该类型进行”数据绑定“有限制要求 : 前端传递的”参数名“ 和 后端与之进行数据绑定的”参数名“ 要保持一致(即 前后端进行”数据绑定“的参数名要保持一致。),如果参数名不保持一致,会绑定”数据绑定“失败,那 如果想要参数名不一致呢,怎么解决这个问题?

    为此,SpringMVC 提供了 @RequestParam( ) 注解来进行 间接数据绑定 (也就解决了上述的问题)。

  • @RequestParam注解主要用于请求中参数进行定义,在使用时可以 指定它的4个属性

    属性说明
    valuename 属性别名,这里指 参数名字,即 入参请求参数名字 ( 即 前端传来参数名字),如 :value=user_id” :表示 请求参数名字user_id 的参数的值将传入 (给后端)。如果只使用vaule 属性,则省略value属性名
    name指定 请求头绑定名称
    required用于 指定参数是否必须默认true,表示请求中一定要有相应的参数
    defaultValue默认值,表示如果请求中没有同名参数时默认值
  • @RequestParam注解使用很简单 ,假设浏览器中的请求地址为http://localhost:8080/selectUser?user_id=1,( 此时前后端对应的“参数名没有保持一致 )那么在后台 selectUser( ) 方法中的使用方式如下 :

    @RequestMapping("/selectUser")
    //此时前后端“参数名”没有保持一致,无法进行“数据绑定”。可用@RequestParam()注解解决这个问题
    public String selectUser(@RequestParam(value = "user_id") Integer id) {
        System.out.println("id = "+id);
        return "success"; //通过String返回值类型,返回一个视图给前端
    }

上述代码会将请求user_id 参数值1赋给方法中的id形参属于“前后端参数名不一致的情况,可用 @RequestParam( )注解解决这个问题 )这样通过输出语句就可以输出 id 形参中的值。

绑定 “POJO类型”
  • 在使用“简单数据类型绑定”时,可以很容易地根据具体需求来定义方法中形参类型个数,然而在 实际应用 中,客户端请求可能会传递 多个不同类型参数数据,如果还使用简单数据类型进行绑定,那么就需要手动编写多个不同类型参数,这种操作显然比较烦琐。此时就可以使用 POJO类型 ( 普通Java对象类型 ) / (普通Java对象) 解决这个问题

  • POJO 类型的数据绑定就是将所有关联的请求参数封装在一个POJO中,然后方法 ( 处理方法 )中直接使用该 POJO 作为形参来完成数据绑定

  • 绑定“ POJO类型 类型 例子如下 :(是在之前的例子代码前提下,进行代码部分修改) :

User.java

package com.myh.po;

public class User {
private Integer id;
private String username;
private Integer password;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public Integer getPassword() {
    return password;
}

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

控制器UserController类 中,编写接收用户 注册信息 和 向 注册页面跳转方法代码如下 :

UserController类

/**
       *  向“用户注册”页面跳转
 */
@RequestMapping("/toRegister")
public String toRegister() {
    return "register";
}

/**
       * 接收用户注册信息
 */
@RequestMapping("/registerUser" )
public String registerUser(User user) {//此处的参数为: POJO类型 (SpringMVC的“数据绑定”)
    String username = user.getUsername();
    Integer password = user.getPassword();
    System.out.println("username="+username);
    System.out.println("password"+password);
    //返回一个视图给前端
    return "success";
}

/WEB-INF/jsp目录下,创建一个用户 注册页面register.jsp,在该界面中编写用户注册表单,表单需要以POST 方式提交,并且在提交时会发送一条以“/registerUser结尾的请求消息:

register.jsp :

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册页面</title>
</head>
<body>
<%--
${pageContext.request.contextPath}/registerUser : 获取web应用的上下文路径,并附加/registerUser路径,从而生成完整的URL

--%>
<form action="${pageContext.request.contextPath}/registerUser" method="post">
 用户名:<input type="text" name="username"/> <br/>&nbsp;&nbsp;&nbsp;:&nbsp;<input type="text" name="password"/> <br/>
 <input type="submit" value="注册">
</form>
</body>
</html>

ps :
在使用POJO 类型数据绑定时,前端请求参数名( 本例中指form表单内各元素的name属性值)
必须与要绑定的POJO类中属性名一样
,这样才会自动将请求数据绑定POJO对象中,否则后台接
参数值为 null


运行项目,访问http://localhost:8080/toRegister ,会跳转到“用户注册页面”。
在这里插入图片描述

在这里插入图片描述

从上图可以看出,使用 POJO 类型同样可以获取前端请求传递过来的数据信息,这就是
POJO 类型的数据绑定,但此时存在“参数的中文乱码问题


  • 解决 请求参数中的中文乱码问题 :

    前端请求中,难免会有中文信息传递,例如上述例子中的“用户名” 和 “密码输入框”中输入用户名“小雪”和密码“123”时,虽然浏览器可以正确跳转到结果页面,但是在控制台中输出的中文信息却出现了乱码

    为了防止前端传入中文数据出现乱码问题,我们可以使用 Spring 提供的 编码过滤器统一编码。要使用编码过滤器,只需要在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">
    
        <!--  配置编码过滤器  -->
        <!--  放置请求参数的“中文乱码问题”  -->
        <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>
        </filter>
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <!-- 表示:拦截前端页面中的“所有请求”  -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    </web-app>
    
    

    上述代码中通过 <filter-mapping>元素配置拦截前端页面中的所有请求并交由名称CharacterEncodingFilter编码过滤器类进行处理。在 <filter>元素 中,首先配置了编码过滤
    器类 org.springframework.web.filter.CharacterEncodingFilter,然后通过 初始化参数设置统一的编
    码为 UTF-8
    。这样所有的请求信息内容都会以UTF-8 的编码格式进行解析。配置完成后就解决了前端请求中携带的参数的“中文乱码”问题

绑定 “包装 POJO”
  • 使用 简单POJO类型已经可以完成多数数据绑定 ,但有时客户端请求中传递参数会比较复杂。例如,在用户查询订单时,页面传递的参数可能包括订单编号用户名称等信息,这就包含了订单用户两个对象的信息。如果将订单用户所有查询条件都封装在一个简单 POJO中,显然会比较混乱,这时就可以考虑使用 包装POJO 类型数据绑定

  • 所谓的 包装POJO,就是在 一个POJO包含另一个简单POJO ( 一个POJO中有另一个POJO类型属性)。

  • 例子如,在订单对象中包含用户对象 (一个POJO对象中包含另一个POJO对象类型属性),这样在使用时,就可以通过 订单查询到用户信息
    (该例子是在 :绑定 “默认数据” 类型的例子基础上进行修改部分代码的 :)

    Orders.java

    package com.myh.po;
    
    /**
     *  该类中除了常规的属性外,还封装了User类型的属性参数
     */
    public class Orders {//订单类Orders,该类用于封装“订单”和“用户信息”
        private Integer OrdersId; //订单编号
        private User user; //用户POJO,所属用户 (属于一个POJO对象中有另一个POJO对象类型的属性)
    
        public Integer getOrdersId() {
            return OrdersId;
        }
    
        public void setOrdersId(Integer ordersId) {
            OrdersId = ordersId;
        }
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    }
    
    

    在上述包装 POJO 类中,定义了订单号和 ( 用户POJO对象类型 )的属性及其对应的getter/setter方法。这样订单类中就不仅可以封装订单基本属性参数,还可以封装User类型属性参数

    OrdersController.java

    package com.myh.controller;
    
    import com.myh.po.Orders;
    import com.myh.po.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class OrdersController { //订单控制器类 : 该类的属性中有一个POJO类型的属性
        /**
         * 向“订单查询页面”跳转
         */
        @RequestMapping("/tofindOrderWithUser")
        public String toFindOrdersWithUser() {
                return "orders"; //返回一个“视图” - 有关“订单信息”的“视图”
        }
    
        /**
         * 查询"订单"和"用户信息"
         */
        @RequestMapping("/findOrderWithUser")
        public String findOrderWithUser(Orders orders) {
            //获取订单id
            Integer ordersId = orders.getOrdersId();
            //获取该订单对应的“客户信息”
            User user = orders.getUser();
            String username = user.getUsername();
            //输出“订单号”
            System.out.println(ordersId);
            //输出"用户姓名"
            System.out.println(username);
            return "success"; //返回一个视图
        }
    }
    
    

    在上面的 订单控制器类 : OrdersController,在该中编写一个跳转到订单查询页面的方法和一个查询订单及用户信息的方法。

    order.jsp :

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>订单查询</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/findOrderWithUser" method="post">
        订单查询: <input type="text" name="ordersIs"><br/>
        <%--  传递的参数是: 所属用户的“用户名”,传递的参数名是 : user.username --%>
        所属用户: <input type="text" name="user.username">
        <input type="submit" value="查询">
    </form>
    </body>
    </html>
    
    
    

    注意点
    在使用 包装POJO类型数据绑定 时,前端请求的参数名编写必须符合以下两种情况
    如果 查询条件参数包装类直接基本属性,则参数名直接用对应属性名上面代码中ordersId
    如果 查询条件参数包装类POJO对象类型的属性,则 参数名 必须为【 对象名.属性 ],其中[对象名]
    要和包装 POJO 中对象属性名称一致,【属性]要和包装POJO 中对象子属性名一致,如上述代码中
    user.username


    启动项tomcat后访问地址为 : http://localhost:8080/tofindOrderWithUser ,会跳转到 “订单查询页面” ,收集信息后,点击“查询”后访问后端进行查询"订单"和"用户信息",最后后端响应一个“视图”。可以看出包装POJO类同样完成了数据绑定

“自定义数据” 绑定 :
  • 一般情况下,使用 基本数据类型POJO类型的参数数据 已经能够满足需求,然而有些 特殊类型参数无法在后台进行直接转换 的。
  • 例如 “日期数据”就需要开发者自定义转换器 (Converter ) / ② 格式化( Formatter ) 来进行数据绑定
Converter (自定义转换器)
  • Spring 框架提供了一个 Converter (转换器) 用于将 一种类型的对象” 转换为“另一种类型的对象。例如,
    用户输入日期形式 可能是 “2017-04-08” 或 “2017/04/08” 的 字符串 ,而要 Spring输入的日期 后台Date 进行绑定,则需要将字符串转换为日期 (前端传来的参数String类型的,后端参数类型Date,此时就要自定义一个“转换器”,来进行数据的“转换”),此时就可以自定义一个Converter类来进行日期转换

  • 自定义Converter类 (自定义转换器”)需要 实现org.springframework.core.convert.converter.Converter接口。该接口代码如下 :

    public interface Converter<S, T> {
        T convert(S var1);
    }
    
    

    在上述接口代码中,泛型中的 S表示源类型 (如 :前端传递的“参数的类型”),T表示目标类型 (如 : 后端用于“接收数据参数类型” ),而 convert(S source) 表示 接口中的方法

  • 自定义转换器 (Converter ) 例子如下

    绑定“默认数据”类型代码基础上,进行添加修改代码来完成该例子

    DateConverter.java

    package com.myh.convert;
    
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
      自定义“日期转换器”
     (要在springmvc-config.xml中 ① 自定义“类型转换器”的配置 : 配置ConversionServiceFactoryBean ②显示装配了的“自定义类型转换器”
     )
     */
    public class DateConverter implements Converter<String, Date> {  //自定义转换器,为前端的“String类型”转换为后端需要的“Date类型”数据服务
    
        //定义“日期格式”
        private String datePattern = "yyyy-MM-dd HH:mm:ss";
    
    
        @Override
        public Date convert(String source) {  //参数为: String类型,返回值为Date类型
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
           try {
               Date date = sdf.parse(source); //返回一个Date类型的数据
               return date;
           } catch (ParseException e) {
               throw new IllegalArgumentException("无效的的日期格式,请使用这种格式: "+datePattern);
           }
        }
    
    }
    
    

    上述代码中,DateConverter类实现了Converter接口,该接口中 第一个类型String 表示需要被转换的数据类型第二个类型 Date 表示需要转换成的目标类型。为了让 Spring MVC 知道并使用这个转换器类,还需要在springmvc-config.xml配置文件中编写一个idconversionServiceBean.

    springmvc-config.xml :

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
    	http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans.xsd
    	http://www.springframework.org/schema/mvc
    	http://www.springframework.org/schema/mvc/spring-mvc.xsd
    	http://www.springframework.org/schema/context
    	http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--  定义”组件扫描器“,进行根包扫描,让”注解“生效  -->
        <context:component-scan base-package="com.myh.controller"/>
    
        <!-- 配置“视图解析器” : 让return时只填“视图名”即可,不用填“全名” -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 设置“前缀”  -->
            <property name="prefix" value="WEB-INF/jsp/"/>
            <!-- 设置“前缀”  -->
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!--  自定义"类型转换器"配置  -->
        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="com.myh.convert.DateConverter"/>
                </set>
            </property>
        </bean>
    
        <!--  显示的装配的 “自定义类型转换器”  -->
        <mvc:annotation-driven conversion-service="conversionService"/>
    </beans>
    
    
    

    DateController.java

    package com.myh.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.Date;
    
    /**
     * 日期控制器类
     */
    @Controller //将该类标记为“控制器类”
    public class DateController {
    
        /**
         * 使用自定义类型数据绑定日期数据
         */
        @RequestMapping("/customDate")
        public String CustomDate(Date date) {
            System.out.println("date="+date);
            return "success"; //返回一个视图
        }
    
    }
    
    

    此时启动项目,在浏览器地址中访问 :localhost:8080/customDate?date=2024-03-11 23:30:30 :
    在这里插入图片描述

    在这里插入图片描述

2.复杂数据绑定 :

  • 通过前面内容讲解 :“简单数据绑定”后,我们已经能够完成实际开发中多数数据绑定问题,但仍可能遇到一些 比较复杂数据绑定问题,比如 数组的绑定集合的绑定,这在实际开发中也是十分常见的。
绑定数组
  • 实际开发时,可能会遇到 前端请求需要传递到后台一个多个相同名称参数情况( 如批量删除 ),此种情况采用前面讲解的简单数据绑定的方式显然是不合适的。此时,就可以使用 绑定数组 的方式,来完成实际需求

  • 绑定数组 例子如 :(一个批量删除用户例子

    user.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>用户列表</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/deleteUsers" method="post">
       <table width="20%" border="1">
            <tr>
                <td>选择</td>
                <td>用户名</td>
            </tr>
           <tr>
               <td><input name="ids" value="1" type="checkbox"></td>
               <td>tom</td>
           </tr>
           <tr>
               <td><input name="ids" value="2" type="checkbox"></td>
               <td>jack</td>
           </tr>
           <tr>
               <td><input name="ids" value="3" type="checkbox"></td>
               <td>lucy</td>
           </tr>
       </table>
        <input type="submit" value="删除">
    </form>
    </body>
    </html>
    

    上述页面代码中,定义了 3个 name属性相同而value属性值不同复选框控件,并在每一个复选框对应的行中编写了一个对应用户。在单击“删除”按钮执行删除操作时,表单会提交到以“/deleteUsers”结尾的请求中

    UserController.java

    package com.myh.controller;
    
    import com.myh.po.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import javax.servlet.http.HttpServletRequest;
    
    //使用注解定义了一个“控制器”类
    @Controller 
    public class UserController {
    
        /**
         * 向用户列表页面跳转
         */
        @RequestMapping("/toUser" )
        public String toUser() {
            return "user";
        }
    
    
        /**
         * 接收批量删除用户的方法
         */
        @RequestMapping("/deleteUsers" )
        public String deleteUsers(Integer[] ids) {
            if (ids != null) {
                for (Integer id : ids) {
                    //使用输出语句模拟已经删除的用户
                    System.out.println("删除了id为: " + id + "的用户!");
                }
            } else {
                System.out.println("ids=null");
            }
            return "success";
        }
    
    }
    

    访问 http://localhost:8080/toUser 跳转到 “用户列表”页面。

绑定集合
  • 批量删除用户操作中,前端请求传递的都是同名参数用户id,只要在后台使用同一种数组类型的参数绑定接收,就可以在方法中通过循环数组参数的方式来完成删除操作

  • 如果是批量修改用户操作前端请求传递过来的数据可能就会批量包含各种类型的数据,如 IntegerString 等。这种情况使用数组绑定无法实现的。针对这种情况,我们可以使用 集合数据绑定。即在 包装类 中定义一个 包含用户信息类的 “集合,然后在接收方法中将参数类型定义为该包装类集合

  • 绑定集合”的例子如 :

    UserVO.java :(包装类 : 其中有一个 “集合”类型的“属性”)

    package com.myh.vo;
    
    import com.myh.po.User;
    
    import java.util.List;
    
    /**
     * 用户包装类
     */
    public class UserVO { //该包装类中,包含了一个“集合类型(泛型为User对象)”的属性,存储User对象类型的数据
    
        private List<User> users; //集合类型,其中类型为User对象类型
    
        public List<User> getUsers() {
            return users;
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    }
    

    上述代码中,声明了一个 List<User>类型集合属性users,并编写了该属性对应的getter/setter方法。该集合属性就是用于 绑定批量修改用户数据信息

    UserController.java

    package com.myh.controller;
    
    import com.myh.po.User;
    import com.myh.vo.UserVO;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.List;
    
    
    //使用注解定义了一个“控制器”类
    @Controller 
    public class UserController {
    
        /**
         * 向用户批量修改页面跳转
         */
        @RequestMapping("/toUserEdit" )
        public String toUserEdit() {
            return "user_edit";
        }
    
        /**
         * 接收批量修改用户的方式
         */
        @RequestMapping("/editUsers" )
        public String editUsers(UserVO userList) { //UserVO : 用户包装类 (其中有一个“集合”类型的属性)
            //将所有用户封装到集合中
            List<User> users = userList.getUsers(); //获得用户包装类中的“集合”属性,其中为一个一个的User对象信息
            //循环输出所有用户信息
            for (User user : users) {
                //如果接受的用户的对象不为null,则对用户数据进行修改
                if (user.getId() != null) {
                    System.out.println("修改了id为" + user.getId() + "的用户名为: " + user.getUsername());
                }
            }
            return "success";
        }
    
    }
    

    上述代码两个方法中,通过toUserEdit( )方法将跳转到user_edit.jsp 页面,通过editUsers( )方法将执行用户批量更新操作,其中 editUsers( )方法的 UserVO 类型参数用于绑定并获取页面传递过来的用户数据

    注意 :
    在使用 集合数据绑定 时, 后台方法不支持直接使用集合形参进行数据绑定,所以需要使用包装
    POJO 作为形参,然后在包装POJO包装一个集合属性


    user_edit.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>修改用户</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/editUsers" method="post" id="formid">
        <table width="30%" border="1">
            <tr>
                <td>选择</td>
                <td>用户名</td>
            </tr>
            <tr>
                <%--  users[0]为集合中的元素(User对象)名 id为该对象中的id --%>
                <%--   users[0].id 为传递给前端的参数名,这样类似形式但不同类型的有4个,可用集合类型(其中元素为User对象)来接收  --%>
                <td><input name="users[0].id" value="1" type="checkbox"></td>
                <td><input name="users[0].username" value="tom" type="text"></td>
            </tr>
            <tr>
                <td><input name="users[1].id" value="2" type="checkbox"></td>
                <td><input name="users[1].username" value="jack" type="text"></td>
            </tr>
        </table>
        <input type="submit" value="修改">
    </form>
    </body>
    </html>
    

    上述页面代码中,模拟展示了id 为 1用户名为 tome 和 id 为 2用户名为jack 的两个用户 (将这两个User对象传给后端,让其进行“批量修改”)。当单击“修改”按钮后,会将表单提交到一个以“/editUsers”结尾的请求中。

    启动项目后访问 http://localhost:8080/toUserEdit

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《互联网的世界》第七讲-能源

本想聊聊 tcp 和 quic&#xff0c;但这些都属于术的范畴&#xff0c;变化多端&#xff0c;等孩子们长大了又不知变成什么样子了&#xff0c;趁这段时间在家&#xff0c;还是得讲一些相对不变的东西&#xff0c;或法或势。 从 安阳卖血糕的精巧篦子 想到如何做圆米粉和圆面条&a…

python-绘制五角星

绘制五角星 """ 功能&#xff1a;五角星的绘制 """ import turtledef main():"""主函数"""count 1lenth50while count < 50:lenth lenth 50turtle.forward(lenth) #向前走50turtle.right(144) #向右转…

探索数据结构:双向链表的灵活优势

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 前言 前面我们学习了单链表&#xff0c;它解决了顺序表中插入删除需…

IM项目题

消息的可靠性 前言 IM系统的可靠性指的是端到端的可靠性&#xff0c;并不是tcp的可靠性&#xff0c;它是指客户端A&#xff0c;客户端B以及服务端三端通信之间的可靠性&#xff0c;并不是客户端A到服务端这么一个上行消息的可靠&#xff0c;这个tcp就可以保证了&#xff0c;当…

openssl3.2 - note - Getting Started with OpenSSL

文章目录 openssl3.2 - note - Getting Started with OpenSSL概述笔记openssl 历史版本Configure 选项开关支持的OSopenssl 文档简介安装新闻每个平台的安装文档支持的命令列表配置文件格式环境变量 END openssl3.2 - note - Getting Started with OpenSSL 概述 看到官方文档…

基于单片机的智能环境监测系统

摘 要 本设计主要由温湿度检测、烟雾检测电路、报警电路、显示电路和人体检测等模块组成。温湿度检测部分使用的是DHT11这种型号的温湿度传感器。DHT11是一种单总线型数字式温湿度传感器&#xff0c;它具有误差小、分辨率高、抗干扰能力强等特点。在烟雾检测电路模块当中&…

ant-design的DatePicker、a-range-picker限制选择今天之前的时间和今天之后的日期时间

a-range-picker限制选择今天之前的时间和今天之后的时间 antd的时间选择器做限制主要用到的参数是disabledDate &#xff0c;下面我们看下案例&#xff1a; HTML&#xff1a; <a-date-picker :disabledDate"disabledDate"></a-date-picker> //最简单…

Linux学习之网络

目录 认识协议 网络协议初始 协议分层 OSI七层模型 TCP/IP的四层模型 数据包封装和分用 以太网通信 ip地址与MAC地址 网络编程套接字 端口号&#xff08;port&#xff09; 认识协议 网络字节序 socket接口 网络的产生是计算机历史的必然性&#xff0c;是计算机发展…

【AI+CAD】(二)LLM和VLM生成结构化数据结构(PPT/CAD/DXF)

当前LLM和VLM在PPT生成任务上已经小有成效,如ChatPPT。 @TOC 1. PPT-LLM LLM根据用户的instruction生成规范的绘制ppt的API语句:即使是最强的GPT-4 + CoT也只能达到20-30%的内容准确度。 LLM输入:User_instruction(当前+过去)、PPT_content、PPT_reader_API。其中 PPT_rea…

文心一言 VS 讯飞星火 VS chatgpt (215)-- 算法导论16.2 2题

二、设计动态规划算法求解 0-1 背包问题&#xff0c;要求运行时间为 O(nW)&#xff0c;n为商品数量&#xff0c;W是小偷能放进背包的最大商品总重量。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 0-1 背包问题是一个典型的动态规划问题&#xff0c;其目标是在…

Supervisor,一个超酷的 Python 库!

大家好&#xff0c;今天为大家分享一个超酷的 Python 库 - supervisor。 Github地址&#xff1a;https://github.com/Supervisor/supervisor 在大型项目中&#xff0c;经常需要管理多个进程&#xff0c;确保它们能够稳定运行并协同工作。Python提供了许多工具和库来帮助实现进…

使用Minio搭建文件服务器

Minio是一个开源的对象存储服务器&#xff0c;可以用来存储和管理大规模的数据。我们可以用它来存储图片或者视频资源。 minio和阿里云&#xff08;腾讯云、百度云等&#xff09;oss对比 托管方式&#xff1a;MinIO 是一个开源的对象存储系统&#xff0c;可以在自己的服务器或…

记录Mysql主从复制-读写分离原理

在实际生产环境中&#xff0c;一台MySQL服务器同时对数据库读写&#xff0c;往往满足不了高并发的需求&#xff0c;因此我们可以使用主从复制的方式来实现数据同步&#xff0c;再通过读写分离的手段提高MySQL并发负载能力。 MySQL主从复制原理 如图&#xff1a; &#xff08;1…

C语言例3-18:使用关系表达式的例子

关系表达式的一般形式&#xff1a; 表达式 关系运算符 表达式 最初代码如下&#xff1a; #include<stdio.h> int main(void) {int i3,j4,k5;float f11.0, f22.1;char c1a, c2d; //a(97) d(100)printf("i>j 的结果为&#xff1a…

B/S基于云计算的云HIS智慧医院管理系统源码带电子病历编辑器

目录 一、系统概述 二、开发环境 三、系统功能 1、门诊部分 2、住院部分 3、电子病历 4、药物管理 5、统计报表 6、综合维护 7、运营运维 云HIS系统&#xff1a;病案首页 云his系统源码 SaaS应用 功能易扩 统一对外接口管理 现如今&#xff0c;大数据、云计算、移动…

中霖教育:考注册会计师报班能提高通过率吗?

CPA考试涵盖了会计、审计、税法及相关的知识,这些知识点不仅繁多而且专业性强&#xff0c;对于自学能力较弱或时间不足的考生来说&#xff0c;有一定的挑战性。在这种情况下&#xff0c;报班提供了系统化和结构化的学习方案&#xff0c;有助于考生更快地掌握考点和难点。 经验…

分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测

分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测 目录 分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GSWOA-KELM分类&#xff0…

位运算#蓝桥杯

位运算#蓝桥杯 文章目录 位运算#蓝桥杯1、小蓝学位运算2、异或森林3、位移4、笨笨的机器人5、博弈论 1、小蓝学位运算 #include<bits/stdc.h> using namespace std; using LL long long; const LL N 1e97; template<int kcz> struct ModInt { #define T (*this)…

1997-2022年各省市场化指数及分项指数(初始数据+计算代码+结果)

1997-2022年各省市场化指数及分项指数&#xff08;初始数据计算代码结果&#xff09; 1、时间&#xff1a;1997-2022年 2、来源&#xff1a;2019年之前的数据来源于市场化指数报告&#xff0c;其中2020年之后的数据根据历年数据拓展所得 3、指标&#xff1a;province、year、…

【办公类-40-01】20240311 用Python将MP4转MP3提取音频 (家长会系列一)

作品展示&#xff1a; 背景需求&#xff1a; 马上就要家长会&#xff0c;我负责做会议前的照片滚动PPT&#xff0c;除了大量照片视频&#xff0c;还需要一个时间很长的背景音乐MP3 一、下载“歌曲串烧” 装一个IDM 下载三个“串烧音乐MP4”。 代码展示 家长会背景音乐: 歌曲串…