SpringMVC中的参数绑定
本篇博客源代码GitHub地址:github源码地址
绑定的机制
我们都知道,表单中请求参数都是基于 key=value 的。
SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的
支持的数据类型:
- 基本类型参数:包括基本类型和 String 类型
- POJO 类型参数:包括实体类,以及关联的实体类
- 数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)
- SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求
使用要求
- 如果是基本类型或者 String 类型:要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
- 如果是 POJO 类型,或者它的关联对象:要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型
- 如果是集合类型,有两种方式:
- 第一种:要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
- 给 List 集合中的元素赋值,使用下标。
- 给 Map 集合中的元素赋值,使用键值对。
- 第二种:接收的请求参数是 json 格式数据。需要借助一个注解实现(@ResponseBody)
- 第一种:要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
小案例:
普通类型参数
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/params")
public String params(String username,String password){
System.out.println("hello springMVC");
System.out.println("用户名:" + username);
System.out.println();
System.out.println("密码:"+password);
return "success";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello world!
<a href="test/hello?username=hehe">简单案例</a>
<a href="hello">简单案例</a>
<hr/>
<form action="test/params">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input name="username" type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
<a href="test/params">参数绑定</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span id="address"></span>
<script type="text/javascript">
var url = document.location;
document.getElementById("address").innerHTML=url;
</script>
</body>
</html>
由上面案例我们可以发现SpringMVC可以自动对我们传过去的参数进行封装,但我们的地址栏中的参数名称和方法中的参数名称必须一样。
对象类型参数
HelloController.java
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/beans")
public String beans(User user){
System.out.println("用户名:" + user);
return "success";
}
}
User.java
public class User {
private String username;
private String password;
//seter and geter
//tostring
}
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span id="address"></span>
<script type="text/javascript">
var url = document.location;
document.getElementById("address").innerHTML=url;
</script>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello world!
<a href="test/hello?username=hehe">简单案例</a>
<a href="hello">简单案例</a>
<hr/>
<form action="test/beans">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input name="username" type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
<a href="test/params">参数绑定</a>
</body>
</html>
对象中含有引用类型
public class User {
private String username;
private String password;
private Account account;
//seter and geter
//tostring
}
public class Account implements Serializable {
private String username;
private Double money;
private String email;
//seter and geter
//tostring
}
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/beans")
public String beans(User user){
System.out.println("用户名:" + user);
return "success";
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello world!
<a href="test/hello?username=hehe">简单案例</a>
<a href="hello">简单案例</a>
<hr/>
<form action="test/beans">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input name="username" type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password"></td>
</tr>
<tr>
<td>姓名:</td>
<td><input name="account.username" type="text"></td>
</tr>
<tr>
<td>薪水:</td>
<td><input name="account.money" type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="account.email" type="text"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span id="address"></span>
<script type="text/javascript">
var url = document.location;
document.getElementById("address").innerHTML=url;
</script>
</body>
</html>
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>
<!--创建核心控制器,所有的请求都会经过改类然后通过该servlet,通过该servlet对请求进行分发-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--将配置文件springmvc.xml加载到项目中-->
<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>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>
对象中含有集合类型
public class User {
private String username;
private String password;
private List<Account> accounts;
private Map<String, Account> accountMap;
//seter and geter
//tostring
}
public class Account implements Serializable {
private String username;
private Double money;
private String email;
//seter and geter
//tostring
}
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/beans")
public String beans(User user){
System.out.println("用户名:" + user);
return "success";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
hello world!
<a href="test/hello?username=hehe">简单案例</a>
<a href="hello">简单案例</a>
<hr/>
<form action="test/beans">
<table border="1px">
<tr>
<td>用户名:</td>
<td><input name="username" type="text"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password" type="password"></td>
</tr>
<tr>
<td>list姓名:</td>
<td><input name="accounts[0].username" type="text"></td>
</tr>
<tr>
<td>list薪水:</td>
<td><input name="accounts[0].money" type="text"></td>
</tr>
<tr>
<td>list邮箱:</td>
<td><input name="accounts[0].email" type="text"></td>
</tr>
<tr>
<td>map姓名:</td>
<td><input name="accountMap['one'].username" type="text"></td>
</tr>
<tr>
<td>map薪水:</td>
<td><input name="accountMap['one'].money" type="text"></td>
</tr>
<tr>
<td>map邮箱:</td>
<td><input name="accountMap['one'].email" type="text"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span id="address"></span>
<script type="text/javascript">
var url = document.location;
document.getElementById("address").innerHTML=url;
</script>
</body>
</html>
获取原生Servlet的API
SpringMVC 还支持使用原始 ServletAPI 对象作为控制器方法的参数。支持原始 ServletAPI 对象有:
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale
- InputStream
- OutputStream
- Reader
- Writer
我们可以把上述对象,直接写在控制的方法参数中使用
示例源代码如下:
HelloController .java
@Controller
@RequestMapping("/test")
public class HelloController {
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request,
HttpServletResponse response,
HttpSession session) {
System.out.println(request);
System.out.println(response);
System.out.println(session);
return "success";
}
}
springmvc.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">
<!-- 开启注解扫描,因为需要将该xml加载到项目中,所以,将该文件配置到web.xml中,让核心控制器加载的时候将该文件也加载到项目中 -->
<context:component-scan base-package="com.toulan"></context:component-scan>
<!--
例如:某个请求的全路径为:http://localhost:8080/springmvc_introduction_demo01_war/WEB-INF/pages/success.jsp
因为我们的项目启动地址为 http://localhost:8080/springmvc_introduction_demo01_war 所以当
prefix:/WEB-INF/pages/
suffix:.jsp
我们在controller层return页面时就只需要传jsp页面的名称: success ,如果我们此处不配置suffix 我们就需要传success.jsp return "success.jsp";
如果此处不写 prefix suffix 那么我们在控制层就需要返回 /WEB-INF/pages/success.jsp return "/WEB-INF/pages/success.jsp";
-->
<!--配置视图解析器对象-->
<!--通过Spring的IOC容器,创建InternalResourceViewResolver对象,并使用-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 在构建URL时用于查看名称的前缀,通俗点讲,就是浏览器请求路径的前缀 -->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!-- 在构建URL时附加到视图名称的后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!--开启SpringMVC框架注解的支持,例如RequestMapping等
同时使用 <mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping (处理映射器) 和
RequestMappingHandlerAdapter ( 处 理 适 配 器 ) , 可 用 在 SpringMVC.xml 配 置 文 件 中 使 用
<mvc:annotation-driven>替代注解处理器和适配器的配置。
-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
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>
<!--创建核心控制器,所有的请求都会经过改类然后通过该servlet,通过该servlet对请求进行分发-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--将配置文件springmvc.xml加载到项目中-->
<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>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>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<>
<a href="test/testServletAPI">测试ServletAPI</a>
</body>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span id="address"></span>
<script type="text/javascript">
var url = document.location;
document.getElementById("address").innerHTML=url;
</script>
</body>
</html>