1. 程式人生 > >springmvc傳多個物件且引數重名

springmvc傳多個物件且引數重名

SpringMVC 多個物件的相同欄位引數傳遞解決方案,在SpringMVC中,有時需要傳遞多個物件(除了Model和web元素)

眾所周知,在SpringMVC中不支援類似struts2的點語法傳參法則,因此多個物件同名引數傳遞勢必會造成一定的問題。

  1. SpringMVC的引數傳遞非常智慧,可自動裝配引數到物件

public class User{
 private String name;
 private String id;
 private String gender,
 private String age;
  //getter 和setter
}
----------------------------------
public class Food{
 private String name;
 private String id;
 private String price,
 private String date;
 //getter 和setter
}
-------
<form method='post' action='url'>
使用者名稱 <input type='text' name='name'>
使用者id <input type='text' name='id'>
食品名 <input type='text' name='name'>
食品id <input type='text' name='id'>
 <input type='text' name='gender'>
 <input type='text' name='age'>
 <input type='text' name='price'>
 <input type='text' name='date'>
</form>

--------
@requestMap(value={'/order/book'})
public string show(User u,Food f){}

在上述情況下User 和food都不能得到正確的name和id,或者說更本得不到,這要是struts2就方便多了,直接使用點語法 u.name,u.id,f.name,f.id....

為了解決上述問題,有2中方案:

1.是建立一個DTO

優點是可以認為的避免參數的傳遞,直接改dto的欄位名 u_name,u_id,f_name,f_id,gender,age,date,price都要列出來,然後作如下操作

然後修改表單欄位和contoller

<form method='post' action='url'>
使用者名稱 <input type='text' name='u_name'>
使用者id <input type='text' name='u_id'>
食品名 <input type='text' name='f_name'>
食品id <input type='text' name='f_id'>
 <input type='text' name='gender'>
 <input type='text' name='age'>
 <input type='text' name='price'>
 <input type='text' name='date'>
</form>

@requestMap(value={'/order/book'})
public string show(UserFoodDto dto){
//然後拆分,將欄位
User u = new User();
Food f = new Food();

u.setName(dto.getUname());
f.setName(dto.getname());

u.setUid(dto.getUid());
f.setFid(dto.getFid());

u.setAge(dto.getAge);
f.setPrice(dto.getPrice);
.....
}

缺點是:如果資料量大,100百個欄位,修改的地方自然越多,而且一個dto,拆分也很費力,因此不建議使用在資料量大的情況下

2.使用橋連線,將不同的部分專門封裝成一個物件推薦

優點:減少了衝突,減少了工作量

缺點:衝突欄位/總欄位趨近於1時顯得沒必要(不過,這種情況幾乎很少出現,除非是繼承關係,但繼承關係完全可以使用子類來傳值,所以這個問題你就當沒遇到過)

表單如下

<form method='post' action='url'>
使用者名稱 <input type='text' name='u_name'>
使用者id <input type='text' name='u_id'>
食品名 <input type='text' name='f_name'>
食品id <input type='text' name='f_id'>
 <input type='text' name='gender'>
 <input type='text' name='age'>
 <input type='text' name='price'>
 <input type='text' name='date'>
</form>

-----將衝突的欄位專門建立一個javaBean
public String UFBridge{
    
    private String uname;
    private String uid;
    private String fname;
    private String fid;
}
--------------------------
@requestMap(value={'/order/book'})
public string show(User u,Food f,UFBridge ufb){

   u.setName(ufb.getUname());
   f.setName(ufb.getUname());
   
   u.setId(ufb.getUid);
   f.setId(ufb.getFid);
}

3.使用相應的註解@InitBinder,可以做出類似struts2的方案(不推薦,程式碼量增加,靈活度不夠)

springController:

  1. @Controller
  2. @RequestMapping("/user")  
  3. public UserController extends BaseController{  
  4.     @RequestMapping("/addUser")    
  5.     publicvoid testBinderOuput(@ModelAttribute User user, HttpServletRequest request, HttpServletResponse response){    
  6.         System.out.println(user);    
  7.     }   
  8. }  

Use物件:
  1. public Class User{  
  2.     private String name;      
  3.     privateint sex;      
  4.     private String address;  
  5.     privateint id;  
  6.     publicint getSex() {  
  7.         return sex;  
  8.     }  
  9.     publicvoid setSex(int sex) {  
  10.         this.sex = sex;  
  11.     }  
  12.     public String getAddress() {  
  13.         return address;  
  14.     }  
  15.     publicvoid setAddress(String address) {  
  16.         this.address = address;  
  17.     }  
  18.     publicint getId() {  
  19.         return id;  
  20.     }  
  21.     publicvoid setId(int id) {  
  22.         this.id = id;  
  23.     }  
  24.     publicvoid setName(String name) {  
  25.         this.name = name;  
  26.     }  
  27. }  

請求路徑:
localhost/user/addUser?user.name="test"
那麼在後臺接受到的引數中,user物件的name屬性是null。如果路徑換為localhost/user/addUser?name="test",則user物件的name屬性是test。
這裡必須用name="test"而不是user.name="test",因為預設情況下springMVC是不支援user.name這種傳參方式的。

如果有個物件manager中也有name這個相同的屬性,那麼可以採用user.name,manager.name來傳輸引數。但是這個需要在controller中新增一個字首繫結:

新增繫結字首後的controller類如下:

  1. @Controller
  2. @RequestMapping("/user")  
  3. public UserController extends BaseController{  
  4.     @InitBinder("manager")    
  5.     publicvoid initBinder1(WebDataBinder binder) {    
  6.             binder.setFieldDefaultPrefix("manager.");    
  7.     }    
  8.     @InitBinder("user")    
  9.     publicvoid initBinder2(WebDataBinder binder) {    
  10.             binder.setFieldDefaultPrefix("user.");    
  11.     }    
  12.     @RequestMapping("/addUser")    
  13.     publicvoid testBinderOuput(@ModelAttribute User user, HttpServletRequest request, HttpServletResponse response){    
  14.         System.out.println(user.getName);    
  15.     }   
  16.     @RequestMapping("/addManager")    
  17.     publicvoid testBinderOuput(@ModelAttribute Manager manager, HttpServletRequest request, HttpServletResponse response){    
  18.         System.out.println(manager.getName);    
  19.     }   
  20. }  
這樣在使用連線localhost/user/addUser?user.name="test",去請求時,後臺拿到的name的引數就不為null了。

有個專門討論這個問題的主題:http://www.iteye.com/topic/1124433?page=2可以參考下