默认支持的参数类型
处理器形参中添加如下类型的参数处理注解适配器会默认识别并进行赋值。
1
HttpServletRequest
通过
request
对象获取请求信息
2
HttpServletResponse
通过
response
处理响应信息
3
HttpSession
通过
session
对象得到
session
中存放的对象
4
Model
通过
model
向页面传递数据,如下:
//
调用
service
查询商品信息
Items item =
itemService
.findItemById(id);
model
.addAttribute("item", item);
页面通过
${
item
.XXXX}
获取
item
对象的属性值。
model也可以通过modelMap或map将数据传到页面(这是因为底层就是这个类型,具体可以看看底层代码)。
参数绑定介绍
注解适配器对RequestMapping
标记的方法进行适配,对方法中的形参会进行参数绑定,
早期
springmvc
采用
PropertyEditor
(属性编辑器)进行参数绑定将
request
请求的参数绑定到方法形参上,
3.X之后springmvc就开始使用Converter进行参数绑定。
1
@RequestParam:
用于绑定单个请求参数。
value
:
参数名字,即入参的请求参数名字,如value=“
item_id
”
表示请求的参数区中的名字为
item_id
的参数的值将传入;
注意:如果请求参数中没有
item_id
将跑出异常:
HTTP Status 500 - Required Integer parameter 'item_id' is not present
required
:
是否必须,默认是
true
,表示请求中一定要有相应的参数,否则将报;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue
:
默认值,表示如果请求中没有同名参数时的默认值(
即使
required=true
也可以不传
item_id
参数值
)
定义如下:
public String editItem(@RequestParam(value="item_id",required=true) String id) {
}
如果request
请求的参数名和controller
方法的形参数名称一致,适配器自动进行参数绑定(不需要手动进行绑定了)。
如果不一致可以通过@RequestParam
指定request
请求的参数名绑定到哪个方法形参上。
简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
整型
public String editItem(Model model,Integer id) throws Exception
{
}
字符串
例子略
单精度
/
双精度
例子略
布尔型
处理器方法:
public String editItem(Model model,Integer id,Boolean status) throws Exception
请求url:
http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2&status=false
说明:对于布尔类型的参数,请求的参数值为
true
或
false
。
需要注意的是,如果Controller方法参数中定义的是基本数据类型,但是从页面提交过来的数据为null或者”"的话,会出现数据转换的异常。也就是必须保证表单传递过来的数据不能为null或”",所以,在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型,具体参见下面的例子。
@RequestMapping("saysth.do"
)
public
void
test(Integer count) { }
}
表单代码:
<
form
action
="saysth.do"
method
="post"
>
<
input
name
="count"
value
="10"
type
="text"
/>
......
</
form
>
和基本数据类型基本一样,不同之处在于,表单传递过来的数据可以为null或”",以上面代码为例,如果表单中
count
为”"或者表单中无
count
这个input,那么,Controller方法参数中的
count
值则为null。
简单
pojo
简单pojo
类型只包括简单类型的属性。
将pojo对象中的属性名与传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中。
页面定义如下;
<input type="text" name="
name
"/>
<input type="text" name="
price
"/>
Contrller
方法定义如下:
@RequestMapping
(
"/editItemSubmit"
)
public
String editItemSubmit(Items items)
throws
Exception{
System.out.println(items);
请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
包装
pojo
问题:
如果
controller
方法形参中有多个
pojo
且
pojo
中有重复的属性,使用简单
pojo
绑定无法有针对性的绑定,
比如:方法形参有
items
和
User
,
pojo
同时存在
name
属性,从
http
请求过程的
name
无法有针对性的绑定到
items
或
user
。
这个时候需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。
包装对象定义(
包装的
pojo
里边包括了
pojo
)
如下:
Public class
QueryVo {
private
Items
items
;
}
页面定义:
<input type="text" name="
items.
name" />
<input type="text" name="
items.
price" />
Controller
方法定义如下:
public String useraddsubmit(Model model,
QueryVo
queryVo)throws Exception{
System.out.println(queryVo.getItems());
数组
页面定义如下:
页面选中多个checkbox向controller方法传递
<input type="checkbox" name="item_id" value="001"/>
<input type="checkbox" name="item_id" value="002"/>
<input type="checkbox" name="item_id" value="002"/>
传递到controller方法中的格式是:001,002,003
Controller
方法中可以用String[]接收,定义如下:
public String deleteitem(String[] item_id)throws Exception{
System.out.println(item_id);
}
List绑定:
List需要绑定在对象上,而不能直接写在Controller方法的参数中。
Model代码:
public
class
User {
private
String firstName;
private
String lastName;
}
public
class
UserListForm {
private
List<User>
users;
}
Controller代码:
@RequestMapping("saysth.do"
)
public
void
test(UserListForm userForm) {
for
(User user : userForm.getUsers()) { System.out.println(user.getFirstName()
System.out.println(user.getFirstName()
+ " - " +
user.getLastName()); } }
}
}
表单代码:
<
input
name
="users[0].firstName"
value
="aaa"
/>
<
input
name
="users[0].lastName"
value
="bbb"
/>
<
input
name
="users[1].firstName"
value
="ccc"
/>
<
input
name
="users[1].lastName"
value
="ddd"
/>
在表单中需要指定List的下标。值得一提的是,Spring会创建一个以最大下标值为size的List对象,所以,如果表单中有动态添加行、删除行的情况,就需要特别注意,譬如一个表格,用户在使用过程中经过多次删除行、增加行的操作之后,下标值就会与实际大小不一致,这时候,List中的对象,只有在表单中对应有下标的那些才会有值,否则会为null,看个例子:
表单代码:
<
input
name
="users[0].firstName"
value
="aaa"
/>
<
input
name
="users[0].lastName"
value
="bbb"
/>
<
input
name
="users[1].firstName"
value
="ccc"
/>
<
input
name
="users[1].lastName"
value
="ddd"
/>
<
input
name
="users[20].firstName"
value
="eee"
/>
<
input
name
="users[20].lastName"
value
="fff"
/>
这个时候,Controller中的userForm.getUsers()获取到List的size为21,而且这21个User对象都不会为null,但是,第2到第19的User对象中的firstName和lastName都为null。打印结果:
aaa - bbb
ccc - ddd
null - null
null - null
......
null - null
null - null
eee - fff
6. Set绑定:
Set和List类似,也需要绑定在对象上,而不能直接写在Controller方法的参数中。但是,绑定Set数据时,必须先在Set对象中add相应的数量的模型对象。
Model代码:
public
class
User {
private
String firstName;
private
String lastName;
}
public
class
UserSetForm {
private
Set<User> users =
new
HashSet<User>
();
}
Controller代码:
@RequestMapping("saysth.do"
)
public
void
test(UserSetForm userForm) {
for
(User user : userForm.getUsers()) { System.out.println(user.getFirstName()
System.out.println(user.getFirstName()
+ " - " +
user.getLastName()); } }
}
}
表单代码:
<
input
name
="users[0].firstName"
value
="aaa"
/>
<
input
name
="users[0].lastName"
value
="bbb"
/>
<
input
name
="users[1].firstName"
value
="ccc"
/>
<
input
name
="users[1].lastName"
value
="ddd"
/>
<
input
name
="users[2].firstName"
value
="eee"
/>
<
input
name
="users[2].lastName"
value
="fff"
/>
基本和List绑定类似。
需要特别提醒的是,如果最大下标值大于Set的size,则会抛出org.springframework.beans.InvalidPropertyException异常。所以,在使用时有些不便。
7. Map绑定:
Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数中。
Model代码:
public
class
User {
private
String firstName;
private
String lastName;
}
public
class
UserMapForm {
private
Map<String, User>
users;
}
Controller代码:
@RequestMapping("saysth.do"
)
public
void
test(UserMapForm userForm) {
for
(Map.Entry<String, User>
entry : userForm.getUsers().entrySet()) { System.out.println(entry.getKey()
System.out.println(entry.getKey()
+ ": " + entry.getValue().getFirstName() + " - " +
entry.getValue().getLastName());
}
}
表单代码:
<
input
name
="users['x'].firstName"
value
="aaa"
/>
<
input
name
="users['x'].lastName"
value
="bbb"
/>
<
input
name
="users['y'].firstName"
value
="ccc"
/>
<
input
name
="users['y'].lastName"
value
="ddd"
/>
<
input
name
="users['z'].firstName"
value
="eee"
/>
<
input
name
="users['z'].lastName"
value
="fff"
/>
打印结果:
x: aaa - bbb
y: ccc - ddd
z: eee - fff
1.1.1
自定义参数绑定
1.1.1.1
需求
根据业务需求自定义日期格式进行参数绑定。
springmvc
没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定。
1.1.1.2
propertyEditor
(了解)
1.1.1.2.1
使用
WebDataBinder
在
controller
方法中通过
@InitBinder
标识方法为参数绑定方法
,通过
WebDataBinder
注册属性编辑器,问题是此方法只能在单个
controller
类中注册。
/**
注册属性编辑器
(
字符串转换为日期
)*/
@InitBinder
public void
initBinder(
WebDataBinder
binder)
throws
Exception {
binder.registerCustomEditor(Date.
class
,
new
CustomDateEditor(
new
SimpleDateFormat(
"yyyy-MM-dd"
),
true
));
}
1.1.1.2.2
使用
WebBindingInitializer
如果想多个
controller
需要共同注册相同的属性编辑器,可以实现
PropertyEditorRegistrar
接
口,并注入
webBindingInitializer
中。
如下:
编写
CustomPropertyEditor
:
public
class
CustomPropertyEditor
implements
PropertyEditorRegistrar {
public
void
registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.
class
,
new
CustomDateEditor(
new
SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss"
),
true
));
}
}
配置如下:
<!--
注册属性编辑器
-->
<
bean
id="customPropertyEditor"class="cn.itcast.ssm.propertyeditor.CustomPropertyEditor"></bean>
<!--
自定义
webBinder -->
<
bean
id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<
property
name="propertyEditorRegistrars">
<
list
>
<
ref
bean="customPropertyEditor"/>
</
list
>
</
property
>
</
bean
>
<!--
注解适配器
-->
<
bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<
property
name="webBindingInitializer"ref="customBinder"></property>
</
bean
>
Converter转换器(架构师掌握)
自定义
Converter
public
class
CustomDateConverter
implements
Converter<String, Date> {
public
Date convert(String source) {
try
{
SimpleDateFormat simpleDateFormat =
new
SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss"
);
return
simpleDateFormat.parse(source);
}
catch
(Exception e) {
e.printStackTrace();
}
return
null
;
}
}
配置
方式
1
<!--
注解适配器
-->
<!-- conversionService -->
<
bean
id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!--
转换器
-->
<
property
name="converters">
<
list
>
<
bean
class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
</
list
>
</
property
>
</
bean
>
配置
方式
2
<
mvc:annotation-driven
conversion-service="conversionService">
</
mvc:annotation-driven
>
<!-- conversionService -->
<
bean
id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!--
转换器
-->
<
property
name="converters">
<
list
>
<
bean
class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
</
list
>
</
property
>
</
bean
>
来自为知笔记(Wiz)