文章目錄
(一)請求參數綁定入門
(二)請求參數綁定實體類型
(三)配置解決中文亂碼的過濾器
(四)請求參數綁定集合類型
(五)自定義類型轉換器演示異常
(六)自定義類型轉換器代碼編寫
(七)獲取Servlet原生的API
(一)請求參數綁定入門
比如說我們希望前端傳username和password,即前端請求username=hehe&password=123
,那麼使用MVC框架只需要在方法的參數指明即可,即sayHello(String username,String password)
底層原理:通過反射獲取方法的參數信息,從而進行綁定
支持的數據類型:
- 基本數據類型和字符串類型
- 實體類型(JavaBean)
- 集合數據類型(List、map集合等)
下面代碼演示一下
param.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 請求參數綁定--%>
<a href="param/testParam?username=hehe">請求參數綁定</a>
</body>
</html>
ParamController.java:
/**
* 請求參數綁定
*/
@Controller
@RequestMapping("/param")//一級目錄
public class ParamController {
/**
* 請求參數綁定的入門
*
* @return
*/
@RequestMapping("/testParam")
public String testParam(String username) {
System.out.println("username:" + username);
return "success";
}
}
運行結果如下:
如果傳輸多個參數就用&
符號隔開,如下:
可以看到如果傳輸的參數數量太多,這種綁定方法就很麻煩了
如果傳輸的參數數量比較多,我們通常會封裝成一個JavaBean對象,下面會介紹
(二)請求參數綁定實體類型
我們先創建一個實體類,如下:
然後寫一個頁面,注意name要跟實體類的屬性一一對應,如下:
最後在控制器類編寫方法,注意方法的參數是實體類,如下:
/**
* 請求參數綁定,把數據封裝到JavaBean的類中
*
* @return
*/
@RequestMapping("/saveAccount")
public String saveAccount(Account account) {
System.out.println(account);
return "success";
}
運行服務器測試,如下:
注意:現在不能輸入中文,會出現亂碼問題,下面再介紹解決辦法
可以看到參數都被封裝到實體類中了
下面再看一個問題,如果實體類中的屬性類型是引用類型又該如何封裝呢?
我們先創建一個User實體類,如下:
控制器類的方法不用改,主要改頁面的,表達式:user.uname
(其中user爲Account實體類的User引用類型的參數名;uname則爲User引用類型的屬性名)
運行服務器測試程序,如下:
(三)配置解決中文亂碼的過濾器
先演示一下中文亂碼問題,如下:
注意:GET方法是不會亂碼的,亂碼的是POST方法,但是經過下面的配置,什麼方法都不會亂碼了
我們在黑馬旅遊網項目中曾經手寫過一個過濾器專門處理中文亂碼問題,現在springmvc給我們提供了一個過濾器,我們不用自己手寫,直接調用即可,如下:
我們在web.xml中配置,如下:
同時,還要給它配初始化參數,告知springmvc我們需要的編碼集,完整代碼如下:
<!-- 配置解決中文亂碼的過濾器-->
<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>
此時再次測試,如下:
(四)請求參數綁定集合類型
我們準備一個List集合和一個Map集合,如下:
接着寫頁面,依然是有特定的表達式,如下:
(其中的list[0]
是指List集合的第一個元素,map['one']
是指Map集合的key爲one的元素)
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username"></br>
密碼:<input type="text" name="password"></br>
金額:<input type="text" name="money"></br>
<%-- 把下面的數據封裝成一個User對象,然後把該User對象存入List集合--%>
用戶姓名:<input type="text" name="list[0].uname"></br>
用戶年齡:<input type="text" name="list[0].age"></br>
<%-- 把下面的數據封裝成一個User對象,然後把該User對象存入Map集合--%>
用戶姓名:<input type="text" name="map['one'].uname"></br>
用戶年齡:<input type="text" name="map['one'].age"></br>
<input type="submit" value="提交"></br>
</form>
控制器類的方法不用改,因爲依然是封裝成Account實體類,只是該實體類中包含集合類型數據
運行結果如下:
(五)自定義類型轉換器演示異常
其實只要是瀏覽器請求的數據,服務器接收了之後都是String(字符串)類型的
那爲什麼我們的age屬性會被轉換成Integer呢?其實是SpringMVC幫我們轉換的
理論上SpringMVC能轉大多數的類型,但是有一些還是無法轉換的,比如非標準的日期類型
像2000/11//11
是可以轉的,但是2000-11-11
就不可以了,我們可以自己寫一個轉換器實現轉換
我們模擬上面的情景,給User實體類加多一個Date類型的屬性,如下:
接着修改頁面,如下:
(爲了簡單起見,直接保存User,所以要在控制器類寫一個新方法)
<%-- 請求參數綁定--%>
<form action="param/saveUser" method="post">
用戶姓名:<input type="text" name="uname"></br>
用戶年齡:<input type="text" name="age"></br>
用戶生日:<input type="text" name="date">
<input type="submit" value="提交"></br>
</form>
在控制器累中寫一個新方法,如下:
@RequestMapping("/saveUser")
public String saveUser(User user) {
System.out.println(user);
return "success";
}
運行結果如下:
下面演示非標準格式,如下:
可以看到出問題了數據無法正常封裝
(此時只能從瀏覽器看到報錯信息,服務器是沒有報錯信息的)
(六)自定義類型轉換器代碼編寫
其實SpringMVC是寫了很多Converter接口的實現類實現類型轉換的,我們先看看該接口的源碼
自定義轉換器的核心思想也是自己寫一個實現類實現上述接口
也就是<S>
寫字符串類型,<T>
寫日期類型,分析完畢,接下來開始編碼
實現Converter接口並且實現接口的方法,如下:
/**
* @param source 傳入進來的字符串
* @return
*/
@Override
public Date convert(String source) {
//判斷
if (source == null) {
throw new RuntimeException("請您傳入數據");
}
//轉換
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
return df.parse(source);
} catch (Exception e) {
throw new RuntimeException("數據類型轉換出現錯誤");
}
}
我們需要在springmvc配置自定義類型轉換器,如下:
然後還需要配置依賴來綁定我們自己寫的StringToDateConverter,完整代碼如下:
(注意:converters是一個Set集合)
<!-- 配置自定義類型轉換器-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.zzq.utils.StringToDateConverter"></bean>
</set>
</property>
</bean>
最後還要配置一個地方,如下:
之前介紹過annotation-driven
標籤會把適配器之類的幫我們全部配好,但是我們自定義的類型轉換器就需要我們自己手動加上去了
運行結果如下:
(七)獲取Servlet原生的API
如果我們想要拿到原生的request對象或者response對象應該怎麼獲取?
先寫一個頁面,如下:
<a href="param/testServlet">Servlet原生API</a>
再寫一個控制器類的方法,如下:
/**
* 原生的API
*
* @return
*/
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response) {
System.out.println("request:" + request);
HttpSession session = request.getSession();
System.out.println("session:" + session);
ServletContext servletContext = session.getServletContext();
System.out.println("servletContext:" + servletContext);
return "success";
}
運行結果如下: