springMVC參數綁定,springmvc綁定
默認支持的參數類型
處理器形參中添加如下類型的參數處理注解適配器會默認識別並進行賦值。
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(
newSimpleDateFormat("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,
newCustomDateEditor(
new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),
true));
}
}
配置如下:
<!-- 注冊屬性編輯器 -->
<beanid=
"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 =
newSimpleDateFormat("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>
<beanclass=
"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>
<beanclass=
"cn.itcast.ssm.controller.converter.CustomDateConverter"/>
</list>
</property>
</bean>