天天看点

SpringMVC请求参数的绑定

文章目录

  • ​​请求参数绑定机制​​
  • ​​支持的数据类型​​
  • ​​封装一个实体类型:​​
  • ​​实体类中有引用类型的封装​​
  • ​​配置解决中文乱码的过滤器:​​
  • ​​解决办法一:​​
  • ​​解决办法二:(推荐使用)​​
  • ​​请求参数绑定集合类型​​
  • ​​特殊情况​​
  • ​​自定义类型转换器​​
  • ​​演示异常:​​
  • ​​解决办法​​
  • ​​使用ServletAPI 对象作为方法参数​​

请求参数绑定机制

我们都知道,表单中请求参数都是基于 key=value 的。

SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。

例如:

<a href="account/findAccount?accountId=10">查询账户</a>      

中请求参数是:

accountId=10

/**
  • 查询账户
  • @return

    */ @RequestMapping("/findAccount") public String findAccount(Integer accountId) { System.out.println(“查询了账户。。。。”+accountId); return

    “success”; }

支持的数据类型

封装一个实体类型:

1. 封装一个javaBean的类:

Account.java

package cn.itcast.domain;

import java.io.Serializable;

/**
 * Create By LiFang on 2020/8/24.
 */
public class Account implements Serializable {
     private String username;
     private String password;
     private Double money;

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

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                '}';
    }
}      

2. 写一个表单页面

param.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/8/23
  Time: 15:34
  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>
<%--请求参数绑定--%>

<%--把username传到后台--%>
<%--
<a href="param/testParam?username=haha&password=123456789">请求参数的绑定</a>  --%>
<%-- 提交表单,往一个类中封装,那么表单的name要和JavaBean类中的属性一样; 提交表单数据应该走后台的方法--%>
<form method="post" action="param/saveAction"></form>
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
<input type="submit" value="提交" /><br/>
</body>
</html>      

3. 控制器类:

ParamController.java

package cn.itcast.controller;

import cn.itcast.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


//把类交容器管
@Controller
@RequestMapping("/param")
public class ParamController {
//    /**
//     * 请求参数绑定入门
//     * Create By LiFang on 2020/8/23.
//     * @return
//     */
//    @RequestMapping("/testParam")
//    public String testParam(String username,String password){
//        System.out.println("执行了,,,");
//        System.out.println("用户名" + username);
//        System.out.println("密码" + password);
//        return "success";
//    }
    /**
     * 请求参数绑定把数据封装到JavaBean的类中( 提交表单数据默认会被封装到account对象中)
     * Create By LiFang on 2020/8/23.
     * @return
     */
    @RequestMapping("/saveAccount") //请求路径
    public String saveAccount(Account account){
        System.out.println("执行了、、、、、");
        System.out.println(account);

        return "success";
    }
}      

此时,数据封装完成。然后,重启Tomcat.

进入param.jsp页面

填写表单后提交数据。

控制台输出:

SpringMVC请求参数的绑定

可以看到,数据全部都封装上了。这就是給对象类型(实体类型)去做封装。

实体类中有引用类型的封装

需求:

此时,如果Account中还有一个引用类型User,那么我们如何给引用类型传值呢?

  1. User.java实体类:
package cn.itcast.domain;

import java.io.Serializable;

/**
 * Create By LiFang on 2020/8/24.
 */
public class User implements Serializable {
    private String uname;
    private Integer age;

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "uname='" + uname + '\'' +
                ", age=" + age +
                '}';
    }
}      
  1. Account.java
package cn.itcast.domain;

import java.io.Serializable;

/**
 * Create By LiFang on 2020/8/24.
 */
public class Account implements Serializable {
     private String username;
     private String password;
     private Double money;
     private User user;


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

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public User getUser() {
        return user;
    }

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

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}      
  1. param.jsp
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/8/23
  Time: 15:34
  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>
<%--请求参数绑定--%>

<%--把username传到后台--%>
<%--
<a href="param/testParam?username=haha&password=123456789">请求参数的绑定</a>  --%>
<%-- 提交表单,往一个类中封装,那么表单的name要和JavaBean类中的属性一样; 提交表单数据应该走后台的方法--%>
<form method="post" action="param/saveAccount">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
    用户姓名:<input type="text" name="user.uname" ><br/>
    用户年龄:<input type="text" name="user.age" ><br/>
    <input type="submit" value="提交" /><br/>
</form>
</body>
</html>      
  1. 控制器类:

    ParamController.java

package cn.itcast.controller;

import cn.itcast.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


//把类交容器管
@Controller
@RequestMapping("/param")
public class ParamController {
//    /**
//     * 请求参数绑定入门
//     * Create By LiFang on 2020/8/23.
//     * @return
//     */
//    @RequestMapping("/testParam")
//    public String testParam(String username,String password){
//        System.out.println("执行了,,,");
//        System.out.println("用户名" + username);
//        System.out.println("密码" + password);
//        return "success";
//    }
    /**
     * 请求参数绑定把数据封装到JavaBean的类中( 提交表单数据默认会被封装到account对象中)
     * Create By LiFang on 2020/8/23.
     * @return
     */
    @RequestMapping("/saveAccount") //请求路径
    public String saveAccount(Account account){
        System.out.println("执行了、、、、、");
        System.out.println(account);

        return "success";
    }
}      

此时,数据封装完成。

之后,重启Tomcat服务器

SpringMVC请求参数的绑定

控制台结果:

SpringMVC请求参数的绑定
注意:控制器类中的方法不用改,重点是页面的表达式写法。

配置解决中文乱码的过滤器:

需求:在post请求下,提交的数据会乱码。
解决办法一:

单一解决:(较麻烦)

每次都需要在controller类中去设置request.setCharEncording()方法

解决办法二:(推荐使用)

批量解决:

在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>      

结果:

SpringMVC请求参数的绑定

中文乱码解决!

请求参数绑定集合类型

param.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/8/23
  Time: 15:34
  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>
<%--请求参数绑定--%>

<%--把username传到后台--%>
<%--
<a href="param/testParam?username=haha&password=123456789">请求参数的绑定</a>  --%>
<%-- 提交表单,往一个类中封装,那么表单的name要和JavaBean类中的属性一样; 提交表单数据应该走后台的方法--%>
<%--<form method="post" action="param/saveAccount">--%>
<%--姓名:<input type="text" name="username" /><br/>--%>
<%--密码:<input type="text" name="password" /><br/>--%>
<%--金额:<input type="text" name="money" /><br/>--%>
<%--    用户姓名:<input type="text" name="user.uname" ><br/>--%>
<%--    用户年龄:<input type="text" name="user.age" ><br/>--%>
<%--    <input type="submit" value="提交" /><br/>--%>
<%--</form>--%>
<form method="post" action="param/saveAccount">
    姓名:<input type="text" name="username" /><br/>
    密码:<input type="text" name="password" /><br/>
   金额:<input type="text" name="money" /><br/>
<%--    把数据封装到user对象,再把user对象存到List中去--%>
    用户姓名:<input type="text" name="list[0].uname" ><br/>
     用户年龄:<input type="text" name="list[0].age" ><br/>
    <%--    把数据封装到user对象,再把user对象存到Map集合中去,map的key上,此次key=one--%>
    用户姓名:<input type="text" name="map['one'].uname" ><br/>
    用户年龄:<input type="text" name="map['one'].age" ><br/>
     <input type="submit" value="提交" /><br/>
</form>
</body>
</html>      

Account.java

package cn.itcast.domain;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * Create By LiFang on 2020/8/24.
 */
public class Account implements Serializable {
     private String username;
     private String password;
     private Double money;
//     private User user;
    private List<User> list;
    private Map<String,User> map;

    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }

    public Map<String, User> getMap() {
        return map;
    }

    public void setMap(Map<String, User> map) {
        this.map = map;
    }

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

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

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


    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                ", list=" + list +
                ", map=" + map +
                '}';
    }
}      

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!-- SpringMVC的前端控制器 -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
<!--    启动服务器就可以创建这个对象,servlet一旦创建,就可以加载springmvc配置文件,注册扫描就生效,
控制器类就可以扫到;然后,jsp一发请求,控制器类中的方法就可以去执行了-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
<!--  配置解决中文乱码的问题-->
  <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>      

ParamController.java

package cn.itcast.controller;

import cn.itcast.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


//把类交容器管
@Controller
@RequestMapping("/param")
public class ParamController {
    /**
     * 请求参数绑定入门
     * Create By LiFang on 2020/8/23.
     * @return
     */
    @RequestMapping("/testParam")
    public String testParam(String username,String password){
        System.out.println("执行了,,,");
        System.out.println("用户名" + username);
        System.out.println("密码" + password);
        return "success";
    }
    /**
     * 请求参数绑定把数据封装到JavaBean的类中( 提交表单数据默认会被封装到account对象中)
     * Create By LiFang on 2020/8/23.
     * @return
     */
    @RequestMapping("/saveAccount") //请求路径
    public String saveAccount(Account account){
        System.out.println("执行了、、、、、");
        System.out.println(account);

        return "success";
    }
}      

结果:

SpringMVC请求参数的绑定

点击提交

SpringMVC请求参数的绑定

控制台结果:

SpringMVC请求参数的绑定

表明数据封装完成。

特殊情况

自定义类型转换器

演示异常:

我们知道当你写一个具有表单的jsp页面的时候,运行时,会把数据传到后端,这个jsp页面中表单提交的任何数据类型都是String类型,但是后台却是Integer或Date类型,出现这个问题,不要着急,我们的Spring框架内部会默认进行数据类型转换。但是,这里有一个问题,当你从jsp页面传一个Date日期类型的数据,比如:2020/8/25

此格式的日期可以被Spring MVC识别,会转换为Date类型,能够让对象成功接收;

但是如果日期的格式是这样的:2020-8-25 ,此时,spring MVC 不会识别成功。那么我们如何解决呢?

解决办法

  1. 定义一个类,实现Converter接口,该接口有两个泛型。
package cn.itcast.utils;

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

import java.text.*;
import java.util.Date;

/**把字符串转换日期
 *
 * Create By LiFang on 2020/8/26.
 */
public class StringToDateConverter implements Converter<String,Date> {
    /**
     * String source         传入的字符串的值
     * @param source
     * @return
     */
    public Date convert(String source) {
        if (source == null){
            throw new RuntimeException("请您传入数据!");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        //把字符串转换日期
        try {
            //把字符串转换日期
           return df.parse(source);
        } catch (Exception e) {
            throw new RuntimeException("数据类型转换出现错误");
        }

    }
}      
  1. 在Spring配置文件中配置类型转换器

    spring 配置类型转换器的机制是,将自定义的转换器注册到类型转换服务中去。

  2. 在 annotation-driven 标签中引用配置的类型转换服务
<mvc:annotation-driven/>
    <!-- 配置类型转换器工厂 -->
    <bean id="converterService"
          class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!-- 给工厂注入一个新的类型转换器 -->
        <property name="converters">
            <set>
                <!-- 配置自定义类型转换器 -->
                <bean class="cn.itcast.utils.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>
    <!--    开启SpringMVC框架注解的支持:让类型转换配置生效-->
    <mvc:annotation-driven
            conversion-service="converterService"></mvc:annotation-driven>      

结果:

SpringMVC请求参数的绑定
SpringMVC请求参数的绑定
SpringMVC请求参数的绑定

日期格式转换成功!

使用ServletAPI 对象作为方法参数

获取Servert原生的API

param.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2020/8/23
  Time: 15:34
  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>

    <a href="param/testServlet">Servlet原生的API</a>
</form>
</body>
</html>      

ParamController.java

SpringMVC请求参数的绑定

结果:

SpringMVC请求参数的绑定

点击超链接,

SpringMVC请求参数的绑定