文章目录
五、SpringMVC的数据绑定
SpringMVC里面,所谓的数据绑定就是将请求带过来的表单数据绑定到执行方法的参数变量中,SpringMVC除了能够绑定前端提交过来的数据还可以绑定Servlet的一套API,例如我们刚刚一直在使用的HttpServletRequest和HttpServletResponse
5.1 自动绑定的数据类型
- 普通类型:基本数据类型+String+包装类
- 包装数据类型(POJO):包装实体类
- 数组和集合类型:List、Map、Set、数组等数据类型
5.1.1 基本数据类型
- Controller:
package com.dfbz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Controller
@RequestMapping("/demo")
public class DemoController {
/**
* 映射普通数据类型
*
* @param id : 城市id
* @param cityName : 城市名称
* @param GDP : 城市GDP(单位亿元)
* @param capital : 是否省会城市
* @param response
* @throws IOException
*/
@RequestMapping(value = "/demo01")
public void demo01(Integer id,
String cityName,
Double GDP,
Boolean capital,
HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
response.getWriter().write("id= " + id + "<hr>");
response.getWriter().write("cityName= " + cityName + "<hr>");
response.getWriter().write("GDP= " + GDP + "<hr>");
response.getWriter().write("capital= " + capital + "<hr>");
}
}
表单:
Demo01.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>测试参数类型绑定</h3>
<form action="/demo/demo01.form" method="post">
<input type="text" name="id" placeholder="城市id">
<input type="text" name="cityName" placeholder="城市名称">
<input type="text" name="GDP" placeholder="城市GDP">
<input type="text" name="capital" placeholder="是否省会城市(true/false)">
<input type="submit" value="测试参数类型绑定">
</form>
</body>
</html>
5.1.2 普通实体类
- lombok依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
- 定义实体类型:
package com.dfbz.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {
private Integer id; // 城市id
private String cityName; // 城市名称
private Double GDP; // 城市GDP,单位亿元
private Boolean capital; // 是否省会城市
}
- Controller:
/**
* 封装包装数据类型
* @param city
* @param response
* @throws IOException
*/
@RequestMapping("/demo02")
public void demo02(City city, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
response.getWriter().write("id= " + city.getId() + "<hr>");
response.getWriter().write("cityName= " + city.getCityName() + "<hr>");
response.getWriter().write("GDP= " + city.getGDP() + "<hr>");
response.getWriter().write("capital= " + city.getCapital() + "<hr>");
}
表单:
Demo02.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>测试对象参数绑定</h3>
<form action="/demo/demo02.form" method="post">
<input type="text" name="id" placeholder="城市id">
<input type="text" name="cityName" placeholder="城市名称">
<input type="text" name="GDP" placeholder="城市GDP">
<input type="text" name="capital" placeholder="是否省会城市(true/false)">
<input type="submit" value="测试参数类型绑定">
</form>
<br>
<hr>
</body>
</html>
5.2.3 数组和集合类型
1)数组
- Controller:
/**
* 测试数组类型绑定
* @param ids
* @param response
* @throws IOException
*/
@RequestMapping("/demo03")
public void demo03(Integer[] ids, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
response.getWriter().write(Arrays.toString(ids));
}
- 表单:
- Demo03.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>测试数组类型绑定</h3>
<form action="/demo/demo03.form" method="post">
<input type="checkbox" value="1" name="ids">
<input type="checkbox" value="2" name="ids">
<input type="checkbox" value="3" name="ids">
<input type="submit" value="数组类型绑定">
</form>
<br>
<hr>
</body>
</html>
既然能使用数组,那能不能使用List或者Set集合接收呢?
答案是不能的 ,SpringMVC默认不支持集合类型来接收前端参数;(我们可以使用@RequestParam注解解决这个问题)
如果直接使用List或者Set,那么出现如下错误:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface java.util.List
2)List集合
List和Set集合一样,都需要使用@RequestParam
注解来进行参数的绑定;
- Controller:
/**
* 测试集合类型
* @param ids
* @param response
* @throws IOException
*/
@RequestMapping("/demo04")
// public void demo04(@RequestParam List<Integer> ids, HttpServletResponse response) throws IOException {
public void demo04(@RequestParam Set<Integer> ids, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
response.getWriter().write(ids.toString());
}
3)Map集合
绑定Map集合和List、Set集合一样,需要借助@RequestParam注解来进行绑定;
- Controller:
/**
* 测试数组类型绑定
* @param cityMap
* @param response
* @throws IOException
*/
@RequestMapping("/demo05")
public void demo05(@RequestParam Map<String,Object> cityMap, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
response.getWriter().write(cityMap.toString());
}
- 表单:
- Demo05.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>测试Map数据绑定</h3>
<hr>
<form action="/demo/demo05.form" method="post">
<input type="text" name="id" placeholder="城市id">
<input type="text" name="cityName" placeholder="城市名称">
<input type="text" name="GDP" placeholder="城市GDP">
<input type="text" name="capital" placeholder="是否省会城市(true/false)">
<input type="submit" value="测试Map数据绑定">
</form>
</body>
</html>
4)Pojo包装类型
定义一个PoJo包装类:
package com.dfbz.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pojo {
// List<T> 类型
private List<City> cityList;
// List<Map> 类型
private List<Map<String,Object>> cityMapList;
// 对象类型
private City city;
// List<普通> 类型
private List<Integer> ids;
// 数组类型
private String[] cityNames;
}
- Controller:
/**
* 测试pojo类型
* @param pojo
* @param response
* @throws IOException
*/
@RequestMapping("/demo06")
public void demo06(Pojo pojo, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf8");
System.out.println(pojo);
response.getWriter().write(pojo.toString());
}
- 表单:
- Demo06.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>测试参数类型绑定</h3>
<form action="/demo/demo06.form" method="get">
<h3>数组类型: cityNames</h3>
<input type="checkbox" name="cityNames" value="广州">
<input type="checkbox" name="cityNames" value="佛山">
<input type="checkbox" name="cityNames" value="东莞">
<hr>
<h3>集合类型List cityList </h3>
<input type="text" name="cityList[0].id" placeholder="请输入城市id" value="1">
<input type="text" name="cityList[0].cityName" placeholder="请输入城市名称" value="南宁">
<input type="text" name="cityList[0].GDP" placeholder="请输入城市GDP" value="30000.0D">
<input type="text" name="cityList[0].capital" placeholder="是否省会城市" value="true">
<hr>
<input type="text" name="cityList[1].id" placeholder="请输入城市id" value="2">
<input type="text" name="cityList[1].cityName" placeholder="请输入城市名称" value="柳州">
<input type="text" name="cityList[1].GDP" placeholder="请输入城市GDP" value="20000.0D">
<input type="text" name="cityList[1].capital" placeholder="是否省会城市" value="true">
<hr>
<h3>List(Map) 类型 cityMapList</h3>
<input type="text" name="cityMapList[0]['id']" placeholder="请输入城市id" id="1">
<input type="text" name="cityMapList[0]['cityName']" placeholder="请输入城市名称" value="昆明">
<input type="text" name="cityMapList[0]['GDP']" placeholder="请输入城市GDP" value="30000.0D">
<input type="text" name="cityMapList[0]['capital']" placeholder="是否省会城市" value="true">
<hr>
<input type="text" name="cityMapList[1]['id']" placeholder="请输入城市id" value="2">
<input type="text" name="cityMapList[1]['cityName']" placeholder="请输入城市名称" value="香格里拉">
<input type="text" name="cityMapList[1]['GDP']" placeholder="请输入城市GDP" value="30000.0D">
<input type="text" name="cityMapList[1]['capital']" placeholder="是否省会城市" value="false">
<hr>
<h3>对象类型:City</h3>
<input type="text" name="city.id" placeholder="请输入城市id" value="1">
<input type="text" name="city.cityName" placeholder="请输入城市名称" value="福州">
<input type="text" name="city.GDP" placeholder="请输入城市GDP" value="10000.0D">
<input type="text" name="city.capital" placeholder="是否省会城市" value="true">
<h3>List普通类型:ids</h3>
<input type="text" name="ids" placeholder="请输入城市id" value="1">
<input type="text" name="ids" placeholder="请输入城市id" value="2">
<input type="text" name="ids" placeholder="请输入城市id" value="3">
<input type="submit" value="测试参数类型绑定">
</form>
</body>
</html>
5.2 内置参数自动绑定
5.2.1 ServletAPI:
-
HttpServletRequest
-
HttpServletResponse
-
HttpSession
SpringMVC在处理一个handler时,会默认准备好request、response、session这些原生的ServletAPI,我们可以直接传递进Handler方法
- Controller:
/**
* 测试servlet原生API
* @param request
* @param response
* @param session
* @throws IOException
*/
@RequestMapping("/demo07")
public void demo07(
HttpServletRequest request,
HttpServletResponse response,
HttpSession session) throws IOException {
session.setAttribute("sessionVal","hello session!");
response.sendRedirect("/hello.jsp");
}
编写一个jsp页面,取出session域的值;
5.2.2 SpringMVC内置对象
- Model:是一个接口,存储的数据存放在request域
- ModelMap:是一个类,存储的数据存放在request域
- ModelAndView:包含数据和视图;
Model和ModelMap默认都是存储了Request请求作用域的数据的对象,这个两个对象的作用是一样,就将数据返回到页面
- Controller:
/**
* 测试SpringMVC内置对象
*
* @param model
* @param modelMap
* @throws IOException
*/
@RequestMapping("/demo08")
public String demo08(
Map<String, Object> map,
Model model,
ModelMap modelMap) throws IOException {
map.put("mapMsg", "hello map!");
model.addAttribute("modelMsg", "hello model!");
modelMap.addAttribute("modelMapMsg", "hello modelMap!");
System.out.println(map.getClass()); // BindingAwareModelMap
System.out.println(model.getClass()); // BindingAwareModelMap
System.out.println(modelMap.getClass()); // BindingAwareModelMap
return "forward:/Demo08.jsp";
}
- 页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>map-${requestScope.mapMsg}</h1>
<h1>model-${requestScope.modelMsg}</h1>
<h1>modelMap-${requestScope.modelMapMsg}</h1>
</body>
</html>
5.3 乱码的处理
我们知道Tomcat在处理Post请求时,中文会出现乱码,我们一般是通过request.setCharacterEncoding(true)
来解决Post乱码问题;在SpringMVC中,提供有专门的Filter过滤器来帮我们处理Post请求乱码问题
在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>
<!--解决response乱码问题-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--解决request乱码 问题-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<!--拦截所有的请求,统一处理乱码问题-->
<url-pattern>/*</url-pattern>
</filter-mapping>