请求参数的绑定
一、一般的参数绑定
1). 绑定的机制
表单中请求参数都是基于key=value的。SpringMVC绑定请求参数的过程是通过把表单提交的请求参数作为控制器中方法参数进行绑定的。
- 例如,有一个超链接,其中请求参数是
accountId=10
<a href="account/findAccount?accountId=10">查询账户</a>
- 对应的控制器(只展示二级访问目录)
@RequestMapping("/findAccount")
public String findAccount(Integer accountId) {
System.out.println("查询了账户。。。。" + accountId);
return "success";
}
2). 支持的数据类型及使用规则
SpringMVC绑定请求参数是框架底层自动实现的。
1. 基本类型参数:【基本类型】 + 【String】
要求参数名称必须和控制器中方法的形参名称保持一致。严格区分大小写
- jsp代码
<a href="account/findAccount?accountId=10&accountName=zhangsan">查询账户</a>
- 控制器代码
@Controller
@RequestMapping("/account")
public class AccountController {
/** 查询账户 */
@RequestMapping("/findAccount")
public String findAccount(Integer accountId, String accountName) {
System.out.println("查询了账户:" + accountId + " 姓名:" + accountName);
return "success";
}
}
2. POJO:【实体类】 + 【关联的实体类】
表单中参数名称和pojo类的属性名称保持一致,并且控制器方法的参数类型是POJO类型。
- 实体类代码
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;
private Address address;
...get/set/toString/构造函数...
/*- - - - - - - - - - - - - - - - - - */
public class Address implements Serializable {
private String provinceName;
private String cityName;
...get/set/toString/构造函数...
- jsp标签
<form action="account/saveAccount" 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>
- 控制器代码
@Controller
@RequestMapping("/account")
public class AccountController {
/** 保存账户 */
@RequestMapping("saveAccount")
public String saveAccount(Account account) {
System.out.println(account);
return "success";
}
}
3. 数组和集合类型:【基本数组】 + 【List】 + 【Map】
有两种方式,如下
1. 方式一:POJO类中包含集合类型参数
要求集合类型的请求参数必须在POJO中。在表单中请求参数名称和POJO中集合属性名称相同。
给List集合中的元素赋值,使用下标。
给Map集合中的元素赋值,使用键值对。
- pojo相关类User
public class User implements Serializable {
private String username;
private String password;
private Integer age;
private List<Account> accounts;
private Map<String, Account> accountMap;
... get/set/toString ...
- jsp代码
<form action="account/updateAccount" method="post">
用户名称:<input type="text" name="username"> <br>
用户密码:<input type="password" name="password"> <br>
用户年龄:<input type="text" name="age"> <br>
<%-- List --%>
账户1名称:<input type="text" name="accounts[0].name"> <br>
账户1金额: <input type="text" name="accounts[0].money"> <br>
账户1省份:<input type="text" name="accounts[0].address.provinceName"> <br>
账户1城市: <input type="text" name="accounts[0].address.cityName"> <br>
<%-- Map --%>
账户2名称:<input type="text" name="accountMap['one'].name"> <br>
账户2金额:<input type="text" name="accountMap['one'].money"> <br>
账户2省份:<input type="text" name="accountMap['one'].address.provinceName"> <br>
账户2城市:<input type="text" name="accountMap['one'].address.cityName"> <br>
<input type="submit" value="保存">
</form>
- 控制器代码
@Controller
@RequestMapping("/account")
public class AccountController {
/** 更新账户 */
@RequestMapping("/updateAccount")
public String updateAccount(User user) {
System.out.println(user);
return "success";
}
}
2. 方式二:JSON
接收的请求参数是json格式数据。需要借助一个注解实现。
4. 数据类型的自动转换
内置转换器全在
org.springframework.core.converter.support
包下。内置的转换规则如下:
原始数据类型 | ->转换后的类型以及对应的转换器 |
---|---|
java.lang.Boolean -> | java.lang.String : ObjectToStringConverter |
java.lang.Character -> | java.lang.Number : CharacterToNumberFactory |
java.lang.Character -> | java.lang.String : ObjectToStringConverter |
java.lang.Enum -> | java.lang.String : EnumToStringConverter |
java.lang.Number -> | java.lang.Character : NumberToCharacterConverter |
java.lang.Number -> | java.lang.Number : NumberToNumberConverterFactory |
java.lang.Number -> | java.lang.String : ObjectToStringConverter |
java.lang.String -> | java.lang.Boolean : StringToBooleanConverter |
java.lang.String -> | java.lang.Character : StringToCharacterConverter |
java.lang.String -> | java.lang.Enum : StringToEnumConverterFactory |
java.lang.String -> | java.lang.Number : StringToNumberConverterFactory |
java.lang.String -> | java.util.Locale : StringToLocaleConverter |
java.lang.String -> | java.util.Properties : StringToPropertiesConverter |
java.lang.String -> | java.util.UUID : StringToUUIDConverter |
java.util.Locale -> | java.lang.String : ObjectToStringConverter |
java.util.Properties -> | java.lang.String : PropertiesToStringConverter |
java.util.UUID -> | java.lang.String : ObjectToStringConverter |
... | ... |
如果遇到特殊类型转换需求,需要自己编写自定义类型转换器。
二、自定义类型转换器绑定参数
以String转为Date为例
1). 定义一个类,实现Converter接口,该接口有两个泛型
- Converter接口的源码!【可千万别自己写,必须的使用Spring提供的Converter接口】
/** 实现Converter接口,该接口有两个泛型,
* S代表接收的类型,T代表目标类型 */
public interface Converter<S, T> {
/** 实现类型转换的方法 */
T convert(S source);
}
- 实现类StringToDateConverter
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class StringToDateConverter implements Converter<String, Date> {
/** 将String类型转换成日期类型 */
@Override
public Date convert(String source) {
DateFormat format = null;
try {
if (StringUtils.isEmpty(source)) {
throw new NullPointerException("请输入要转换的日期");
}
format = new SimpleDateFormat("yyyy-MM-dd");
return format.parse(source);
} catch (Exception e) { throw new RuntimeException(e); }
}
}
2). 在spring配置文件springMVC.xml中配置自定义类型转换器
spring配置类型转换器的机制是将自定义的转换器注册到类型转换服务中去。
<!-- 配置类型转换工厂 -->
<bean id="converterService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 给工厂注入一个新的类型转化器 -->
<property name="converters">
<array>
<!-- 配置自定义类型转换器 -->
<bean class="com.itheima.converter.impl.StringToDateConverter"></bean>
</array>
</property>
</bean>
3). 在<annotation-driven>
标签中应用配合的类型转换服务
<!-- 配置spring开启注解mvc的支持,并引用自定义类型转换器 -->
<mvc:annotation-driven
conversion-service="converterService"></mvc:annotation-driven>
4). 测试代码
- jsp核心代码
<%-- 特殊情况值:类型转换问题! --%>
<a href="account/deleteAccount?date=2019-01-01">根据日期删除账户</a>
- 控制器代码
@Controller
@RequestMapping("/account")
public class AccountController {
/** 删除账户 */
@RequestMapping("/deleteAccount")
public String deleteAccount(Date date) {
System.out.println(date);
return "success";
}
}
三、 使用ServletAPI对象作为方法参数
SpringMVC还支持使用原始ServletAPI对象作为控制器方法的参数。可以将这些对象直接写在控制的方法参数中并使用
支持原始Servlet的对象 |
---|
HttpServletRequest |
HttpServletResponse |
HttpSession |
java.security.Principal |
Locale |
InputStream |
OutputStream |
Reader |
Writer |
). 实例代码
- jsp核心代码
<%-- 原始ServletAPI作为控制器参数 --%>
<a href="account/testServletAPI">测试访问ServletAPI</a>
- 控制器代码
@Controller
@RequestMapping("/account")
public class AccountController {
/** 测试访问testServletAPI */
@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";
}
}