springMVC中關於引數傳遞的問題
有這麼一個jsp頁面
有這一個pojo類<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%> <form action="addProduct"> 產品名稱 :<input type="text" name="name" value=""><br /> 產品價格: <input type="text" name="price" value=""><br /> <input type="submit" value="增加商品"> </form>
對應的控制器為package pojo; public class Product { private int id; private String name; private float price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
最後是展示用的jsppackage controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import pojo.Product; @Controller public class ProductController { @RequestMapping("/addProduct") public ModelAndView add(Product product) throws Exception { ModelAndView mav = new ModelAndView("showProduct"); return mav; } }
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
產品名稱: ${product.name}<br>
產品價格: ${product.price}
問題1
為什麼第一個jsp頁面中傳遞引數只是pojo類Product的的屬性即可,而不用寫成product.name這種形式?分析:
這應該是springMVC的一個特點,name和price屬性會賦值給add方法的product引數物件,稍後也會討論當有多個物件具有相同的屬性時該怎麼處理。
問題2
第二個jsp頁面${product} 這個 product 到底是哪兒來的?
分析:
引數product會預設被當做值加入到ModelAndView 中,相當於:
mav.addObject("product",product);
絕大部分疑問都是圍繞 ${product} 這個 product 到底是哪兒來的,看了站長的回答,其實是有些問題的。
我自己一開始也是一臉懵逼的,經過多次實驗以及google,給大家講一下吧:
大家應該都知道,EL 表示式中的引數應該是來自於 addObject("abc",xxx) 中的第一個引數 abc
站長說的半對半錯,他告訴你們引數 product 會預設被當做值加入到 ModelAndView 中
但是沒有說,這只是 addObject() 第二個引數的來歷,有疑問的其實更關心第一個引數,也就是我們 EL 表示式中要用到的這個 "product" 從何而來:)
一句話,大家就能明白:
add()方法的【引數型別】會自動轉小駝峰並加入到 ModelAndView 中作為 addObject() 的【第一個引數】,相當於 addObject("theFirstParam", product);
綜上:addObject 裡第一個引數是根據 add() 的引數型別自動轉成小駝峰命名,第二個引數是 add() 的引數名。
區分命名,舉個極端的栗子就明白了,這裡程式碼看的不爽點上面【程式碼】到那裡看
bean:
public class MyFuckingProduct {...};
controller:
public ModelAndView add(MyFuckingProduct 隨便寫我寫中文應該沒人發現吧) {...}
jsp:
${myFuckingProduct.xxx}
跑一下,bingo!
大家注意 add() 方法的引數,引數名是什麼根本不用管,瞎寫一通 fhdhdfai2u3y,沒有關係,因為預設的 addObject()方法第一個引數只跟你的引數型別有關係,第二個引數就是你瞎寫的引數名。
相當於:addObject("myFuckingProduct", 隨便寫我寫中文應該沒人發現吧);
然後 EL 表示式寫什麼就很明瞭了。
4種方法讓SpringMVC接收多個物件(以下內容來自百度)
問題背景:
我要在一個表單裡同時一次性提交多名乘客的個人資訊到SpringMVC,前端HTML和SpringMVC Controller裡該如何處理?
- 第1種方法:表單提交,以欄位陣列接收;
- 第2種方法:表單提交,以BeanListModel接收;
- 第3種方法:將Json物件序列化成Json字串提交,以List接收;
- 第4種方法:將表單物件序列化成Json字串提交,以List接收;
第4種方法其實是第3種方法的升級,就是將表單轉成Json物件,再轉成Json字串提交;
然而,第4種方法還不支援含有多選控制元件表單的提交,故應該還有第5種加強版的方法。
以上4種方法都共用同一個User實體類,程式碼如下:
public class User {
private Integer id;
private String name;
private String pwd;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
// .......後面還有getter、setter方法,省略了
}
第1種方法:表單提交,以欄位陣列接收
HTML程式碼如下:
<form action="/user/submitUserList_1" method="post">
ID:<input type="text" name="id"><br/>
Username:<input type="text" name="name"><br/>
Password:<input type="text" name="pwd"><br/><br/>
ID:<input type="text" name="id"><br/>
Username:<input type="text" name="name"><br/>
Password:<input type="text" name="pwd"><br/><br/>
<input type="submit" value="submit">
</form>
Java程式碼如下:
@RequestMapping(value = "/submitUserList_1", method ={RequestMethod.POST})
@ResponseBody
public String submitUserList_1(HttpServletResponse response,Integer[] id, String[] name, String[] pwd)
throws Exception{
String result = "";
if(id == null || id.length <= 0){ return "No any ID.中文"; }
List<User> userList = new ArrayList<User>();
for (int i = 0; i < id.length; i++ ) {
User user = new User();
user.setId(id[i]);
user.setName(name[i]);
user.setPwd(pwd[i]);
userList.add(user);
}
result = this.showUserList(userList);
return result;
}
第2種方法:表單提交,以BeanListModel接收
HTML程式碼如下:
<form action="/user/submitUserList_2" method="post">
ID:<input type="text" name="users[0].id"><br/>
Username:<input type="text" name="users[0].name"><br/>
Password:<input type="text" name="users[0].pwd"><br/><br/>
ID:<input type="text" name="users[2].id"><br/>
Username:<input type="text" name="users[2].name"><br/>
Password:<input type="text" name="users[2].pwd"><br/><br/>
<input type="submit" value="Submit">
</form>
Java程式碼:
除了剛才公用的User類,還要封裝一個User的容器類UserModel:
public class UserModel {
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public UserModel(List<User> users) {
super();
this.users = users;
}
public UserModel() {
super();
}
}
SpringMVC Controller方法:
@RequestMapping(value = "/submitUserList_2", method ={RequestMethod.POST})
@ResponseBody
public String submitUserList_2(UserModel users)
throws Exception{
String result = "";
List<User> userList = users.getUsers();
if(userList == null || userList.size() <= 0){ return "No any ID.中文"; }
result = this.showUserList(userList);
return result;
}
第3種方法:將Json物件序列化成Json字串提交,以List接收
HTML程式碼:
<head>
<title>submitUserList_3</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script language="JavaScript" src="/js/jquery.min.js" ></script>
<script language="JavaScript" src="/js/jquery.json.min.js" ></script>
<script type="text/javascript" language="JavaScript">
function submitUserList_3() {alert("ok");
var customerArray = new Array();
customerArray.push({id: "1", name: "李四", pwd: "123"});
customerArray.push({id: "2", name: "張三", pwd: "332"});
$.ajax({
url: "/user/submitUserList_3",
type: "POST",
contentType : 'application/json;charset=utf-8', //設定請求頭資訊
dataType:"json",
//data: JSON.stringify(customerArray), //將Json物件序列化成Json字串,JSON.stringify()原生態方法
data: $.toJSON(customerArray), //將Json物件序列化成Json字串,toJSON()需要引用jquery.json.min.js
success: function(data){
alert(data);
},
error: function(res){
alert(res.responseText);
}
});
}
</script>
</head>
<body>
<h1>submitUserList_3</h1>
<input id="submit" type="button" value="Submit" onclick="submitUserList_3();">
</body>
Java程式碼:
@RequestMapping(value = "/submitUserList_3", method ={RequestMethod.POST})
@ResponseBody
public String submitUserList_3(@RequestBody List<User> users)
throws Exception{
String result = "";
if(users == null || users.size() <= 0){ return "No any ID.中文"; }
result = this.showUserList(users);
return result;
}
第4種方法:將表單物件序列化成Json字串提交,以List接收
HTML程式碼:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>submitUserList_4</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script language="JavaScript" src="/js/jquery.min.js" ></script>
<script type="text/javascript" language="JavaScript">
//將表單序列化成json格式的資料(但不適用於含有控制元件的表單,例如複選框、多選的select)
(function($){
$.fn.serializeJson = function(){
var jsonData1 = {};
var serializeArray = this.serializeArray();
// 先轉換成{"id": ["12","14"], "name": ["aaa","bbb"], "pwd":["pwd1","pwd2"]}這種形式
$(serializeArray).each(function () {
if (jsonData1[this.name]) {
if ($.isArray(jsonData1[this.name])) {
jsonData1[this.name].push(this.value);
} else {
jsonData1[this.name] = [jsonData1[this.name], this.value];
}
} else {
jsonData1[this.name] = this.value;
}
});
// 再轉成[{"id": "12", "name": "aaa", "pwd":"pwd1"},{"id": "14", "name": "bb", "pwd":"pwd2"}]的形式
var vCount = 0;
// 計算json內部的陣列最大長度
for(var item in jsonData1){
var tmp = $.isArray(jsonData1[item]) ? jsonData1[item].length : 1;
vCount = (tmp > vCount) ? tmp : vCount;
}
if(vCount > 1) {
var jsonData2 = new Array();
for(var i = 0; i < vCount; i++){
var jsonObj = {};
for(var item in jsonData1) {
jsonObj[item] = jsonData1[item][i];
}
jsonData2.push(jsonObj);
}
return JSON.stringify(jsonData2);
}else{
return "[" + JSON.stringify(jsonData1) + "]";
}
};
})(jQuery);
function submitUserList_4() {alert("ok");
var jsonStr = $("#form1").serializeJson();
//console.log("jsonStr:\r\n" + jsonStr);
//alert(jsonStr);
$.ajax({
url: "/user/submitUserList_4",
type: "POST",
contentType : 'application/json;charset=utf-8', //設定請求頭資訊
dataType:"json",
data: jsonStr,
success: function(data){
alert(data);
},
error: function(res){
alert(res.responseText);
}
});
}
</script>
</head>
<body>
<h1>submitUserList_4</h1>
<form id="form1">
ID:<input type="text" name="id"><br/>
Username:<input type="text" name="name"><br/>
Password:<input type="text" name="pwd"><br/><br/>
ID:<input type="text" name="id"><br/>
Username:<input type="text" name="name"><br/>
Password:<input type="text" name="pwd"><br/><br/>
<input type="button" value="submit" onclick="submitUserList_4();">
</form>
</body>
</html>
Java程式碼:
@RequestMapping(value = "/submitUserList_4", method ={RequestMethod.POST})
@ResponseBody
public String submitUserList_4(@RequestBody List<User> users)
throws Exception{
String result = "";
if(users == null || users.size() <= 0){ return "No any ID.中文"; }
result = this.showUserList(users);
return result;
}
總結:
第1、2種方法其實都有一個共同的BUG:假如提交三條記錄時,前面兩條記錄的某些欄位不填值的話,在SpringMVC裡接收不準確了。而且,每2種方法在HMTL中需要給name屬性新增[下標],如果下標有跨度的話(比如第一組控制元件下標是0,第二組下標是2),那麼SpringMVC裡其實的是0到2三個物件的,預設下標是1的那個物件全為null值。
第3、4種方法最實用。