目錄
請求參數的綁定
一、綁定的機制
我們都知道道,表單中請求參數都是基於 key=value
的。
SpringMVC 綁定請求參數的過程是通過把表單提交請求參數,作爲控制器中方法參數進行綁定的。
例如:
請求的超鏈接:
<a href="account/findAccount?accountId=10">查詢賬戶</a>
上面的代碼中請求的參數是accountID=10。
後臺代碼:
/**
* 查詢賬戶
* @return
*/
@RequestMapping("/findAccount")
public String findAccount(Integer accountId) {
System.out.println("查詢了賬戶。。。。"+accountId);
return "success";
}
只要我們的方法中的參數和請求參數一致,就會自動綁定。
二、支持的數據類型
基本類型參數: 包括基本類型和 String 類型
POJO 類型參數: 包括實體類,以及關聯的實體類
數組和集合類型參數: 包括 List 結構和 Map 結構的集合(包括數組)
SpringMVC 綁定請求參數是自動實現的,但是要想使用,必須遵循使用要求。
三、使用要求
-
如果是基本類型或者 String類型:
要求我們的參數名稱必須和控制器中方法的形參名稱保持一致。(嚴格區分大小寫) -
如果是 POJO類型,或者它的關聯對象:
要求表單中參數名稱和 POJO 類的屬性名稱保持一致。並且控制器方法的參數類型是 POJO 類型。 -
如果是集合類型,有兩種方式:
第一種:
① 要求集合類型的請求參數必須在 POJO 中。在表單中請求參數名稱要和 POJO 中集合屬性名稱相同。
② 給 List 集合中的元素賦值,使用下標。
③ 給 Map 集合中的元素賦值,使用鍵值對。
第二種:
接收的請求參數是 json 格式數據。需要藉助一個註解實現。
注意:
它可以實現一些數據類型的自動轉換。內置轉換器全都在org.springframework.core.convert.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
......
如遇特殊類型轉換要求,需要我們自己編寫自定義類型轉換器。
四、使用示例
1. 基本類型和String類型作爲基本參數
jsp代碼:
<html>
<head>
<title>請求參數的綁定</title>
</head>
<body>
<a href="param/testParam?username=veeja&userId=10001">請求參數的綁定</a>
</body>
</html>
控制器代碼:
/**
* 請求參數綁定的入門
*
* @return
*/
@RequestMapping("/testParam")
public String testParam(String username, int userId) {
System.out.println("執行了!");
System.out.println("username=" + username);
System.out.println("userId=" + userId);
return "success";
}
控制檯輸出:
2. 實體類類型作爲參數
實體類對象代碼:
package com.veeja.domain;
import java.io.Serializable;
/**
* @Author veeja
* 2020/6/14 14:48
*/
public class Account implements Serializable {
private String username;
private String password;
private double money;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
'}';
}
}
JSP代碼:
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"/><br>
密碼:<input type="password" name="password"/><br>
金額:<input type="text" name="money"/><br>
<input type="submit" value="提交"/><br>
</form>
控制器代碼:
/**
* 請求參數的綁定,把數據封裝到JavaBean的類中
*
* @return
*/
@RequestMapping("/saveAccount")
public String saveAccount(Account account) {
System.out.println("savaAccount()...");
System.out.println(account);
return "success";
}
後臺輸出:
3. 實體類中包含實體類
例如上面的Account如果包含了一個User類:
Account實體類代碼:
package com.veeja.domain;
import java.io.Serializable;
/**
* @Author veeja
* 2020/6/14 14:48
*/
public class Account implements Serializable {
private String username;
private String password;
private double money;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", user=" + user +
'}';
}
}
User實體類代碼:
package com.veeja.domain;
import java.io.Serializable;
/**
* @Author veeja
* 2020/6/14 15:20
*/
public class User implements Serializable {
private String uName;
private Integer age;
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"uName='" + uName + '\'' +
", age=" + age +
'}';
}
}
JSP頁面代碼:
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"/><br>
密碼:<input type="password" name="password"/><br>
金額:<input type="text" name="money"/><br>
uName:<input type="text" name="user.uName"/><br>
money:<input type="text" name="user.age"/><br>
<input type="submit" value="提交"/><br>
</form>
輸出:
上面的代碼有一個問題就是在輸入中文的時候就會出現亂碼,這個問題我們可以通過配置一個過濾器來解決問題:
web.xml中添加過濾器配置信息:
<!--配置過濾器,解決中文亂碼問題-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4. 集合類型封裝
Account實體類代碼:
package com.veeja.domain;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* @Author veeja
* 2020/6/14 14:48
*/
public class Account implements Serializable {
private String username;
private String password;
private double money;
private List<User> list;
private Map<String, User> map;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
public Map<String, User> getMap() {
return map;
}
public void setMap(Map<String, User> map) {
this.map = map;
}
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", list=" + list +
", map=" + map +
'}';
}
}
jsp代碼:
<h1>類中存在集合類型</h1>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"/><br>
密碼:<input type="password" name="password"/><br>
金額:<input type="text" name="money"/><br>
uName:<input type="text" name="list[0].uName"/><br>
money:<input type="text" name="list[0].age"/><br>
uName:<input type="text" name="map['one'].uName"/><br>
money:<input type="text" name="map['one'].age"/><br>
<input type="submit" value="提交"/><br>
</form>
輸出結果:
五、自定義類型轉換器
1. 使用場景
我們來做一個演示:
User實體類代碼:
public class User implements Serializable {
private String uName;
private Date date;
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "User{" +
"uName='" + uName + '\'' +
", date=" + date +
'}';
}
}
jsp頁面代碼:
<form action="param/saveUser" method="post">
姓名:<input type="text" name="uName"/><br>
日期:<input type="text" name="date"/><br>
<input type="submit" value="提交"/><br>
</form>
控制器代碼:
/**
* 請求參數的綁定,把數據封裝到JavaBean的類中
*
* @return
*/
@RequestMapping("/saveUser")
public String saveUser(User user) {
System.out.println("savaUser()...");
System.out.println(user);
return "success";
}
我們在網頁中輸入信息:
後臺顯示:
我們在網頁中輸入信息:
結果網頁報錯了:
也就是數據在類型自動轉換的時候遇到了問題,所以這個時候我們就需要自定義類型轉換器來幫助我們正確的轉換數據類型。
2. 使用步驟
① 定義一個類
首先我們先定義一個類,實現Converter接口,改該接口有兩個泛型。
Converter接口:
public interface Converter<S, T> {
@Nullable
T convert(S var1);
}
其中S表示接受的類型,T表示目標類型。
自定義類型轉換器:
/**
* 字符串轉換成日期
*
* @Author veeja
* 2020/6/14 22:06
*/
public class StringToDateConverter implements Converter<String, Date> {
/**
* @param s 傳進來的字符串
* @return
*/
@Override
public Date convert(String s) {
// 判斷
if (s == null) {
throw new RuntimeException("請您傳入參數數據!");
}
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
// 把字符串轉換成日期
return dateFormat.parse(s);
} catch (ParseException e) {
throw new RuntimeException("數據類型轉換錯誤!");
}
}
}
② 配置自定義轉換器
springmvc.xml:
<!-- 配置自定義類型轉換器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.veeja.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
<!--開啓SpringMVC框架註解的支持-->
<mvc:annotation-driven conversion-service="conversionService"/>
這樣就可以了。
我們再試一下:
結果:
六、使用ServletAPI對象作爲方法參數
SpringMVC 還支持使用原始 ServletAPI 對象作爲控制器方法的參數。支持原始 ServletAPI 對象有:
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
我們可以把上述對象,直接寫在控制的方法參數中使用。
jsp頁面代碼:
<hr>
<h1>原生的ServletAPI</h1>
<a href="param/testServletAPI">獲取Servlet原生API作爲參數</a>
控制器代碼:
/**
* 測試原生的API
*
* @return
*/
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request, HttpServletResponse response) {
System.out.println("testServletAPI()...");
System.out.println(request);
System.out.println(response);
HttpSession session = request.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
return "success";
}
輸出結果: