数据绑定

What?

这种将请求消息数据与后台方法参数建立连接的过程就是Spring MVC中的数据绑定。
Spring MVC会根据客户端的请求参数的不同,将请求消息中的信息以一定的方法转换并绑定到控制器类的方法参数中,

过程

Spring Mvc框架通过数据绑定组件(DataBinder)将请求参数串的内容进行类型的转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确的绑定并获取客户端请求携带的参数了,
在这里插入图片描述

数据绑定的分类

根据客户端请求参数类型和个数的不同,将数据绑定分为简单数据绑定和复杂数据绑定,

绑定默认数据类型

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

  • 常用的默认参数类型:
  • HttpServletRequest:通过request对象获取请求信息;
  • HttpServletResponse:通过response处理响应信息;
  • HttpSession:通过session对象得到session中存放的对象。
  • Model/ModelMap:Model是一个接口,ModelMap是一个接口实现,作用将model数据填充到request域中。

代码

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_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--initparam元素存在并且通过其子元素配置了
        Spring MVC配置文件的路径,则应用程序在启动时会加载配置路径下的配置文件-->
        <!--如果这里面没有通过<init-param>元素配置,则应用程序会默认去WEB-INF目录下寻找
        以servletName-servlet.xml方式命名的配置文件,这里的servletName指的下面的springmvc-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

FirstController

package com.yzb.chapter13;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller

public class FirstController {
    @RequestMapping("/first")
    public String first(HttpServletRequest request){
        String id = request.getParameter("id");
        System.out.println(id);
        return "first";
    }
}

springmvc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <!--上面引入context的信息-->
    <!--指定需要扫描的包-->
    <context:component-scan base-package="com.yzb.chapter13"/>
    <!--使用注解的时候,程序的运行需要依赖Spring的AOP包,因此需要注入aop的jar包-->
    <!--配置视图解析器的前缀和后缀,-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--设置前缀-->
        <property name="prefix" value="/WEB-INF/jsp"></property>
        <!--设置后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

first.jxp


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

简单的数据类型的绑定

指的时Java中集中基本数据类型的绑定,例如String,Double等类型,

@RequestMapping("/second")
    public String first(Integer id){
        System.out.println(id);
        return "first";
    }
    //将HttpServletRequest请求改为基本请求类型Integer的绑定方式

@RequestParam

如果前端请求中的参数和后台方法中传入的形参名不一样,这就会导致无法接受前台的请求参数,这是就可以使用@RequestParam注解进行间接注解绑定

  • @RequestParam注解的属性说明
  • value:name属性的别名,这里指参数的名字,即入参的请求参数的名字,如value="item_id"表示请求的参数中名字为item_id的参数的值传入,如果只用value属性,则可以省略value属性名
  • name:指定请求绑定的名称
  • required:用于指定参数是否必须,默认为true,表示请求中一定要有相应的参数
  • defaultValue:默认值,表示如果请求中没有同名参数的默认值。
@RequestMapping("/second")
    public String first(@RequestParam(value = "item_id" ,required = true ) Integer id){
        System.out.println(id);
        return "first";
    }

POJO类型的数据绑定

FirstController

package com.yzb.chapter12;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller

public class FirstController {
 
    @RequestMapping("/abc")
    public String register(){
        return "register";
    }
    @RequestMapping("/toRegister")
    public String first(User user){
        String username = user.getUsername();
        String password = user.getPassword();
        System.out.println(username +"<br/>"+ password);
        return "first";
    }
}

User

package com.yzb.chapter12;

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + 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 String getPassword() {
        return password;
    }

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

register.jsp


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 <form action="${pageContext.request.contextPath}/toRegister" method="post">
     <%--当绑定POJO类型数据时,表单的name的属性名要和pojo类中的属性名保持一直--%>
    用户名;<input type="text" name="username"><br/>
     密码:<input type="text" name="password"><br/>
     <input type="submit" value="注册">
 </form>
</body>
</html>

注意在使用POJO类型数据绑定的时,前端请求的参数名必须与pojo类中的属性名一样,这样才能自动将请求数据绑定到POJO对象中,否则后台接受的值为空

解决前台传入参数为乱码

  • 加入编码乱码过滤器,在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>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

包装POJO类型的数据绑定

为了解决一个页面传递的参数包含多个对象的信息,这是就需要对POJO类型进行包装。就是在一个POJO中包含另一个简单POJO,例如在订单对象中包含用户对象,这样就可以在查询订单的时候,查询用户,

Orders

package com.yzb.chapter12;

public class Orders {
    private Integer orderId;
    private  User user;

    public Integer getOrderId() {
        return orderId;
    }

    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

OrderController

package com.yzb.chapter12;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class OrderController {
    @RequestMapping("toFindOrdersWithUser")
    public String toFindOrdersWithUser(){
        return "orders";
    }
    @RequestMapping("findOrdersWithUser")
    public String findOrdersWithUser(Orders orders){
        Integer orderId = orders.getOrderId();
        System.out.println(orderId);
        User user = orders.getUser();
        String username = user.getUsername();
        System.out.println(username);
        return "first";
    }
}

orders.jsp

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


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 <form action="${pageContext.request.contextPath}/findOrdersWithUser" method="post">
     <%--当绑定POJO类型数据时,表单的name的属性名要和pojo类中的属性名保持一直--%>
    订单id;<input type="text" name="orderId"><br/>
     用户名:<input type="text" name="user.username"><br/>
     <input type="submit" value="注册">
 </form>
</body>
</html>

自定义数据绑定

对于特殊类型的参数是无法在后台进行直接转换的,但也有特殊数据类型无法直接进行数据绑定,必须经过数据类型的转换,例如日期数据。

自定义转换器Converter

spring提供的Converter用于将一种类型的对象转换为另一种类型的对象。
自定义了Converter类需要实现org.framework.core.convert.vonverter.Converter接口

public interface Converter<S,T>{
T convert(S source);
}
//S 是源类型,T是目标类型

格式化Formatter

作用与Converter的一样,指示Formatter的源类型必须是String类型,而Converter可以是任意类型。
使用Formatter自定义转换器类需要实现org.springframework.format.Formatter接口。

public interface Formatter<T> extends Printer<T>, Parser<T>{}

Converter的代码

DateConverter

定义格式转换类

package com.yzb.chapter12;

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 自定义日期转换器
* */
public class DataConverter implements Converter<String, Date> {
    //定义日期格式化
    private  String datePattern = "yyyy-MM-dd HH:mm:ss";
    @Override
    public Date convert(String s) {
        //格式化日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
        try {
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            throw new IllegalArgumentException("无效的日期格式,请使用这种格式:"+ datePattern);
        }
    }
}

springmvc.xml

告诉spring配置了自定义转换器

<!--显示装配的自定义类型转换器-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <!--自定义类型转换器配置-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.yzb.chapter12.DataConverter"/>
            </set>
        </property>
    </bean>

DateController

package com.yzb.chapter12;

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 "first";
    }
}

在这里插入图片描述

formatter的代码

DateFormatter

package com.yzb.chapter12;

import org.springframework.format.Formatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateFormatter implements Formatter<Date> {
    //定义格式
    private  String datePattern = "yyyy-MM-dd HH:mm:ss";
    //声明SimpleDateFormat对象
    private SimpleDateFormat simpleDateFormat;
    /*
    * 解析字符串文本,生成Date对象
    * */
    @Override
    public Date parse(String s, Locale locale) throws ParseException {
         simpleDateFormat = new SimpleDateFormat(datePattern);
        return simpleDateFormat.parse(s);
    }
    /*
    * 将日期装换成对应的日期/时间字符串
    * */
    @Override
    public String print(Date date, Locale locale) {
        return new SimpleDateFormat().format(date);
    }
}

springmvc.xml

    <!--显示装配的自定义类型转换器-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <!--自定义类型格式化转换器配置-->
    <!--class和name的属性必须是这两个-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="com.yzb.chapter12.DateFormatter"></bean>
            </set>
        </property>
    </bean>

绑定数组

结果图在这里插入图片描述

User.jsp

<%--
  Created by IntelliJ IDEA.
  User: 岳振彪
  Date: 2020/6/30
  Time: 14:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/deleteUser" method="post">
    <table border="1">
        <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>rose</td>
        </tr>
    </table>
    <input type="submit" value="删除">
</form>

</body>
</html>

UserController

package com.yzb.chapter12;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    @RequestMapping("delete")
    public String toFindOrdersWithUser(){
        return "user";
    }
    @RequestMapping("deleteUser")
    public String findOrdersWithUser(Integer[] ids){
        if(ids !=null){
            for (Integer id : ids) {
                System.out.println("删除了id为"+id+"的用户!");
            }
        }else {
            System.out.println("ids = null");
        }
       return "first";
    }
}

集合类的包装

UserVO

package com.yzb.chapter12;

import java.util.List;

public class UserVO {
    private List<User>  users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

EditController

package com.yzb.chapter12;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class EditController {
    @RequestMapping("edit")
    public String toFindOrdersWithUser(){
        return "edit";
    }
    @RequestMapping("editUser")
    public String findOrdersWithUser(UserVO list){
        List<User> users = list.getUsers();
        for (User user : users) {
            System.out.println("修改id为"+ user.getId()+"的用户名"+user.getUsername());
        }
        return "first";
    }
}

edit.jsp

<%--
  Created by IntelliJ IDEA.
  User: 岳振彪
  Date: 2020/6/30
  Time: 14:59
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/editUser" method="post">
    <table border="1">
        <tr>
            <td>选择</td>
            <td>用户名</td>
        </tr>
        <tr>
            <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>
        <tr>
            <td> <input name="users[2].id" value="3" type="checkbox"></td>
            <td><input name="users[2].username" value="rose" type="text"></td>
        </tr>
    </table>
    <input type="submit" value="删除">
</form>

</body>
</html>

该代码文件用于本科生计算机科学与技术专业数据库课程设计,图书借阅管理子系统,数据库用户名sa,密码gsw,数据库名名称BookManageSystem,这些都可以在DButil.java文件中修改。功能有学生账号注册登录借书还书,罚款计算,同时设有管理员,账号固定在login.Java代码中为administrator,密码password,可自行在代码中修改,管理员可查询图书情况,学生账户情况,修改图书信息等等功能,内容十分简单,十分适合大二大三本科生参考 设计本系统模拟学生在图书馆借阅图书的管理内容,包括查询图书、借书、借阅后的查询、统计、超期罚款等的处理情况,简化的系统需要管理的情况如下: 1、可随时查询出可借阅图书的详细情况,如图书编号(BNO)、图书名称(BNA)、出版日期(BDA)、图书出版社(BPU)、图书存放位置(BPL)、图书总数量(BNU)等,这样便于学生选借。 2、学生查询图书情况后即可借阅所需图书,可借阅多种图书,每种图书一般只借一本,若已有图书超期请交清罚金后,才能开始本次借阅; 3、为了唯一标识每一学生,图书室办借书证需如下信息:学生姓名(SNA)、学生系别(SDE)、学生所学专业(SSP)、借书上限数(SUP)及唯一的借书证号(SNO)。 4、每学生一次可借多本书,但不能超出该生允许借阅上限数,每个学生可多次借阅,允许重复借阅同一本书。规定借书期限为二个月,超期每天罚二分。 5、学生可以进行借阅、续借、归还和查询书籍。借阅时要登记相应的借书日期;归还时要记录还书日期;续借相当于归还书后重新借阅。 根据以上信息完成如下要求: 1、请认真作系统需求分析,设计出反映本系统的E-R图(需求分析、概念设计)。 2、写出已设计E-R图相应的关系模式,根据设计需要还可增加辅助关系模式,并找出各关系模式的关键字(逻辑设计)。 3、在已设计的关系模式基础上开发设计功能子系统,要求子系统能完成如下功能要求(物理设计、设施与试运行): 1)在某数据库管理系统中建立各关系模式对应的库表,并设计所需的视图、索引等。 2)能对各库表进行输入、修改、删除、添加、查询、打印等基本操作。 3)能根据学生要求借阅图书库中有的书,并完成一次借阅任务后汇总已借书本总数,报告还可借书量,已超期的需付清罚款金额后才可借书。 4)能明细查询某学生的借书情况及图书的借出情况。 5)能统计出某图书的总借出数量与库存量及某学生借书总数,当天为止总罚金。 6)其他你认为子系统应有的查询、统计功能。
2.2 主要功能说明: 一.欢迎界面:改界面主要是作为本系统的封面,程序运行后该界面会出 现在屏幕中间,操作者可以点击该界面即可计入下一个窗体。 二.入口:本系统中权限的设置主要是靠入口,选择不同的登录身份进入 系统后将会得到不一样的执行权限。若选择退出系统,则将会退出整个软件。 三. 读者登陆界面:该窗体主要是给一般读者登陆系统执行图书的查询和借阅功能的,当读者输入的编号和密码正确后即可进入系统,当用户输入用户名和密码出现错误后,系统会提示用户重新输入。当用户三次输入均出现错误时,系统会自动关闭。 四.管理员登陆界面:该窗体主要是提供给系统管理员进入系统进行操作的,其中用法和读者登陆界面一样,不同的是进入系统后具有的操作权限不同。管理员具有全部权限。 五.图书管理:(1)图书信息录入界面:此界面主要用于首次录入图书信 息,因此该界面应该具有输入图书所有信息的元素, 如图书编号,书名,书号,作者…. (2)图书信息修改界面:此界面主要是用于已经存在馆里的图书的信息的修改,因此该界面应该有查找和修改的功能,所以除了具有图书信息录入界面的元素外,还应该有上一条,下一条,查询等元素。 六.读者管理:(1)读者注册界面:此界面主要是用于录入新读者的信息, 因此此界面应该具有读者的所有信息,另外应该还具 有赋予读者一个进入系统的密码的元素。 (2)读者信息修改:此界面主要用于对已经注册过本系统 的读者的信息的修改,包括密码等等元素。 七.图书服务:(1)图书查询界面:此界面主要是用于查询,借阅,预 约图书,查询时可按图书的书名,作者,出版社来 查询,查询到的图书用表格显示,并且可以显示图书 的借阅情况。 (2)借书还书界面:该界面主要是用于读者的借书和还 书的情况,并且读者可以归还图书。 八.数据安全:(1)数据备份界面:该界面主要用于对本系统的重要数 据进行备份,以便不小心失去数据后可以恢复数据 提高系统的安全性。 (2)数据恢复界面:该界面是和数据备份界面配合使用的,当需要恢复已经备份的数据时,即可使用该窗体。 九.系统管理:(1)帮助和相关界面:该界面主要是向使用本系统的读者或者管理员提供相应的提示和帮助,同时显示一些关于本系统的相关信息。 (2)密码设置界面:该界面主要是用于管理员的注册和密码修改,注册界面可以注册新的管理员,密码修改界面可以对已经存在的管理员的信息的修改。 (3)退出本系统界面:该界面主要是用来安全退出整个软件,包括退出了vfp软件 (4)恢复vfp系统界面:该界面主要是用来退出当前运行的图书管理系统,恢复到vfp系统继续进行操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值