SpringMVC_请求参数绑定

3. 请求参数绑定

SpringMVC通过进行参数解析器可以将请求的参数与方法中的参数进行绑定

3.1. 支持参数类型

  • 基本类型
  • String
  • POJO类型
  • 数组和集合类型

3.2. 使用要求

  • 基本类型或String:请求参数名称和方法形参名称保持一致(区分大小写)

  • POJO类型:请求参数名称和 POJO类的属性名称保持一致,方法参数类型是POJO类型。

  • 数组或集合类型

    • 要求集合类型的请求参数必须在 POJO中。在表单中请求参数名称要和 POJO中集合属性名称相同。

      给 List集合中的元素赋值,使用下标。

      给 Map集合中的元素赋值,使用键值对。

    • 接收的请求参数是 json格式数据。需要借助一个注解实现

3.3. 使用示例

3.3.1. 基本类型和 String 类型作为参数
  • 请求路径
http://localhost:8080/user/select/id/username.do?id=1001&username=tomcat
  • controller
@RequestMapping("/select/id/username")
public String testParam(Integer id,String username){
    System.out.println("id="+id+" username="+username);
    return "success";
}
3.3.2. POJO类型作为参数
  1. 添加POJO类

User.java

public class User {
    private Integer id;
    private String name;
    private Float money;
    private Address address;
    //get set toString...
}

Address.java

public class Address {
    private String provinceName;
    private String cityName;
    //get set toString...
}
  1. 添加表单页面

    user.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/user/pojo.do" method="post">
        用户名称:<input type="text" name="name" ><br/>
        用户余额:<input type="text" name="money" ><br/>
        用户地址-省:<input type="text" name="address.provinceName" ><br/>
        用户地址-市:<input type="text" name="address.cityName" ><br/>
                    <input type="submit" value="保存">
    </form>
</body>
</html>

  1. controller接收参数
@RequestMapping("/pojo")
public String saveAccount(User user){
    System.out.println(user);
    return "success";
}
3.3.3. 请求参数中文乱码处理

web.xml添加请求参数处理过滤器

    <!-- 配置 springMVC编码过滤器 -->
    <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>
        </init-param>
    </filter>
    <!-- 过滤所有请求 -->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
3.3.4. POJO 类中包含集合类型参数

添加pojo类

public class Bank {
    private String account;
    private Double money;
    //get set
}

修改User类

public class User {
    private Integer id;
    private String name;
    private Float money;
    private Address address;

    //集合类型属性
    private List<Integer> ids;
    private List<Bank> bankList;
    private Map<String,Integer> sizeMap;
    private Map<String,Bank> bankMap;

    //get set
}

collection.jsp

<form action="/user/collection.do" method="post">
    用户名称:<input type="text" name="name" ><br/>
    用户余额:<input type="text" name="money" ><br/>
    用户地址-省:<input type="text" name="address.provinceName" ><br/>
    用户地址-市:<input type="text" name="address.cityName" ><br/>

    IdsItegerList:<input type="text" name="ids[0]" ><br/>
    IdsItegerList:<input type="text" name="ids[1]" ><br/>
    IdsItegerList:<input type="text" name="ids[2]" ><br/>

    String[]:<input type="text" name="props" ><br/>
    String[]:<input type="text" name="props" ><br/>
    
    bankList[0].account:<input type="text" name="bankList[0].account" ><br/>
    bankList[0].money:<input type="text" name="bankList[0].money" ><br/>
    bankList[1].account:<input type="text" name="bankList[1].account" ><br/>
    bankList[1].money:<input type="text" name="bankList[1].money" ><br/>

    sizeMap-S:<input type="text" name="sizeMap['S']" ><br/>
    sizeMap-M:<input type="text" name="sizeMap['M']"><br/>
    sizeMap-L:<input type="text" name="sizeMap['L']"><br/>

    bankMap-bank1-account: <input type="text" name="bankMap['bank1'].account"><br/>
    bankMap-bank1-money: <input type="text" name="bankMap['bank1'].money"><br/>
    bankMap-bank2-account: <input type="text" name="bankMap['bank2'].account"><br/>
    bankMap-bank2-money: <input type="text" name="bankMap['bank2'].money"><br/>
    <input type="submit" value="保存">
</form>

controller

@RequestMapping("/collection")
public String collection(User user,String[] props){
    System.out.println(user);
    return "success";
}

测试:
在这里插入图片描述
在这里插入图片描述

3.3. 日期类型参数

新建webapp/date.jsp

<!-- 特殊情况之:类型转换问题 -->
<a href="/user/select/date.do?date=2020/07/03">根据日期查询</a>

UserController添加方法

@RequestMapping("/select/date")
public String selectByDate(Date date){
	System.out.println("date : "+date);
	return "success";
}

当把参数2020/07/03 格式改为 2020-07-03时,抛出异常:String转换为Date类型出错
在这里插入图片描述
spingmvc默认是按照yyyy/mm/dd格式进行日期转换,不支持yyyy-mm-dd格式,需要自定义转换器

3.3.1. 自定义类型转换器
  1. 定义类实现Converter接口
  2. 配置自定义类型转换器
  3. annotation-driven 标签中引用配置的类型转换服务
3.3.2. 定义类实现Converter接口
package com.czxy.mvc.converter;

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

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//public interface Converter<S, T> {//S:表示接受的类型,T:表示目标类型
public class StringToDateConverter implements Converter<String,Date> {
    /**
     * 实现类型转换的方法
     * @param s
     * @return
     */
    @Override
    public Date convert(String s) {
        if(s != null && !s.trim().equals("")){
            SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
            try {
                Date date = format.parse(s);
                return date;
            } catch (ParseException e) {
                System.out.println("日期格式错误!");
                e.printStackTrace();
            }
        }
        return null;
    }
}
3.3.3. 配置自定义类型转换器
<!-- 配置类型转换器工厂 -->
    <bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!-- 给工厂注入一个新的类型转换器 -->
        <!-- 配置自定义类型转换器 -->
        <property name="converters">
            <array>
                <bean class="com.czxy.mvc.converter.StringToDateConverter"></bean>
            </array>
        </property>
    </bean>
3.3.4. 引用配置的类型转换服务
    <!--第三步:在 annotation-driven标签中引用配置的类型转换服务-->
    <!-- 引用自定义类型转换器 -->
    <mvc:annotation-driven conversion-service="converterService"/>
3.3.5. 测试

http://localhost:8080/user/select/date.do?date=2020-07-03

控制台正常输出:Fri Jan 03 00:07:00 CST 2020

3.3.6. pojo中的日期类型
public class User {
	//其他属性...

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    // get set 
    
}

只需要添加@DateTimeFormat指定日期格式即可

注意:需要在springmvc.xml中开启注解驱动:

<mvc:annotation-driven></mvc:annotation-driven>
  • UserController
@RequestMapping("/select/date")
public String selectByDate(Date date,User user){
    System.out.println("user.birthday : "+user.getBirthday());
    System.out.println("date : "+date);
    return "success";
}
  • http://localhost:8080/user/select/date.do?birthday=2020-07-03

3.4. ServletAPI对象作为方法参数

SpringMVC还支持使用原始 ServletAPI对象作为控制器方法的参数。支持原始 ServletAPI对象有:

  • HttpServletRequest (常用)

  • HttpServletResponse (常用)

  • HttpSession (常用)

  • InputStream

  • OutputStream

  • Reader

  • Writer

  • java.security.Principal

  • Locale

    我们可以把上述对象,直接写在控制的方法参数中使用。例如需要使用HttpSession获取session中登录的用户信息,可以将HttpSession对象作为方法参数

3.4.1. 使用示例

在controller方法上将Servlet API对象作为参数,Spring容器会注入这些对象,然后在方法中可以直接使用

@RequestMapping("/test/servletAPI")
public String testServetAPI(HttpServletRequest request, 
                            HttpServletResponse response,
                            HttpSession session){
    System.out.println(request);
    System.out.println(response);
    System.out.println(session);

    return "success";
}
  • 直接在浏览器地址栏访问该方法:

http://localhost:8080/user/test/servletAPI.do

  • 控制台输出对象地址,说明获取到了这些对象:

org.apache.catalina.connector.RequestFacade@20b048eb
org.apache.catalina.connector.ResponseFacade@c5ebc7c
org.apache.catalina.session.StandardSessionFacade@4c9bebef

3.5. forward redirect

3.5.1. forward和redirect区别
  • forward
  1. 转发都是一次请求: A -> B -> C 整个过程还是一次请求,也就是同个request,后面的方法可以获取前面请求中的域属性
  2. 转发地址栏显示地址不变
    在这里插入图片描述
  • redirect
  1. 重定向是2次请求:A -> B ,那么A和B 就是不同request,B无法获取到A 的request中的数据,但是只要没有关闭浏览器,A和B还在一次会话总,A和B可以使用session共享数据
  2. 重定向浏览器地址栏会显示新的请求地址
    在这里插入图片描述
3.5.1. forward示例

使用Servlet API 可以获取内存(servlet域)中的参数,

    @RequestMapping("/forward")
    public String forward(HttpServletRequest request,
                          HttpSession session){
        request.setAttribute("name","张三");
        session.setAttribute("age",20);
        System.out.println("参数设置完毕...转发...");
        return "forward:/user/get/params.do";
    }

    @RequestMapping("/get/params")
    public String getParams(HttpServletRequest request,
                          HttpSession session){
        String name = (String) request.getAttribute("name");
        Integer age = (Integer) session.getAttribute("age");
        System.out.println("name : "+name+" age : "+age);
        return "success";
    }

浏览器地址:http://localhost:8080/user/forward.do

控制台输出:name : 张三 age : 20

3.5.2. redirect示例
   @RequestMapping("/redirect")
    public String redirect(HttpServletRequest request,
                          HttpSession session){
        request.setAttribute("name","张三");
        session.setAttribute("age",20);
        System.out.println("参数设置完毕...转发...");
        return "redirect:/user/get/params.do";
    }

    @RequestMapping("/get/params")
    public String getParams(HttpServletRequest request,
                          HttpSession session){
        String name = (String) request.getAttribute("name");
        Integer age = (Integer) session.getAttribute("age");
        System.out.println("name : "+name+" age : "+age);
        return "success";
    }

访问地址:http://localhost:8080/user/redirect.do

访问后地址:http://localhost:8080/user/get/params.do

控制台输出:name : null age : 20

3.6.3. 使用forward和request转发
  • 使用forward转发
@RequestMapping("/forward")
public String forwar()  {
    //System.out.println("转发到...");
    //转发能访问到webapp目录下所有资源
    //return "forward:/a.html";
    return "forward:/WEB-INF/b.html";
}
  • 使用request转发
@RequestMapping("/req/forward")
public void forwar(HttpServletRequest request) throws Exception{
    System.out.println("转发到...");
    //转发能访问到webapp目录下所有资源
    //return "forward:/a.html";
    //return "forward:/WEB-INF/b.html";
    request.getRequestDispatcher("/WEB-INF/b.html").forward(request,response);
}
3.6.4. 使用redirect和response重定向
  • 使用redirect重定向
@RequestMapping("/redirect")
public String redirect(HttpServletResponse response) throws Exception{
    System.out.println("重定向...");
    //注意重定向是2次请求,不能访问到WEB-INF目录下的资源
    //只能访问webapp目录下(不包含WEB-INF)的资源
    //return "redirect:/user.jsp";
    return "redirect:/a.html";
}
  • 使用response重定向
@RequestMapping("/resp/redirect")
public void redirect(HttpServletResponse response) throws Exception {
    System.out.println("重定向...");
    //注意重定向是2次请求,不能访问到WEB-INF目录下的资源
    //只能访问webapp目录下(不包含WEB-INF)的资源
    //return "redirect:/user.jsp";
    //return "redirect:/a.html";
    response.sendRedirect("/user.jsp");
}

猜你喜欢

转载自blog.csdn.net/qq_44509920/article/details/107699613