問題:使用者的請求,是如何被背景獲得的,即使用者的請求資訊是怎麼配置設定給不同的處理器? 背景又是如何獲得使用者資料的?這些問題會後面的課程中一一解答
一、 使用@RequestMapping映射請求
- SpringMVC使用@RequestMapping注解,為控制器指定可以處理哪些URL請求
- DispathcherSevle截獲請求後,就通過控制器上@RequestMapping提供的映射資訊确定請求所對應的處理方法
- 檢視@RequestMapping源碼,可以知道它可以修飾方法,也可以修飾類

1、@RequestMapping修飾方法
- 測試類
-
@Controller
-
public class SpringMVCTest {
-
@RequestMapping("/testMappingMethod")
-
public String testRequestMapping(){
-
System.out.println("testMappingMethod");
-
return "success";
-
}
-
}
- URL
-
<a href="testMappingMethod"></a>
2 @RequestMapping修飾類
- 測試類
-
@RequestMapping("/mappingClass")
-
@Controller
-
public class MappingClassTest {
-
@RequestMapping("/testMappingMethod")
-
public String testRequestMapping(){
-
System.out.println("testRequestMapping");
-
return "success";
-
}
-
}
- 請求的url
-
<a href="mappingClass/testMappingMethod">testMappingClass</a>
3 總結
- @RequestMapping可以标注在控制器類的定義或方法定義處。
- 類定義:提供初步的請求映射資訊,相對于WEB應用的根目錄
- 方法處:提供進一步細分映射資訊,相對于類定義處的URL;若類定義處未标注@RequestMapping,則方法處标注的URL相對WEB應用的根目錄
二、映射請求參數、請求方式或請求頭
- @RequestMapping除了可以使用請求Url映射請求以外,還可以使用請求方法、請求參數及請求頭映射請求.對應的@RequestMapping源碼如下
-
@Target({ElementType.METHOD, ElementType.TYPE})
-
@Retention(RetentionPolicy.RUNTIME)
-
@Documented
-
@Mapping
-
public @interface RequestMapping {
-
...
-
RequestMethod[] method() default {};
-
...
-
String[] params() default {};
-
String[] headers() default {};
-
...
-
}
- @RequestMapping的vaule、method、params及headers分别表請求URL、請求方法、請求參數及請求頭的映射條件,他們之間是 “與” 的關系,聯合使用多個條件可讓請求映射更加精确化
1、method的屬性
- 控制器
-
@RequestMapping(value="/testMethod",method=RequestMethod.POST)
-
public String testMethod(){
-
System.out.println("testMethod");
-
return "success";
-
}
- 超連結是使用get請求,是以不會成功
-
<a href="mappingOther/testMethod">測試請求方式</a>
- form請求
-
<form action="mappingOther/testMethod" method="post">
-
<input type="submit" value="送出">
-
</form>
2、params的屬性
2.1 params支援簡單的表達式
- param1:表示請求必須包含名為param1的請求參數
- !param1:表示請求不能包含名為param1的請求參數
- param1!=value1:表示請求包含名為param1的參數,但其值不能為value1
- {"param1=value1",param2}:請求必須包含名為param1和param2的兩個請求參數,且param1的參數的值必須是value1
2.2 測試
- 控制器
-
@RequestMapping(value="/testParams",params={"username","age!=10"})
-
public String testParams(){
-
System.out.println("testParams");
-
return "success";
-
}
含義:必須包含參數username和age,且age的值不能為10
- 請求
-
<a href="mappingOther/testParams?username=imentor&age=10">測試參數</a>
不能成功,因為age的值為10
3、header
- 獲得headers的值,可以通過firebug來檢視
- 控制器中的編寫如下
-
@RequestMapping(value="/testHeaders",headers={"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"})
-
public String testHeaders(){
-
System.out.println("testHeader");
-
return "success";
-
}
三、映射請求路徑
- @RequestMapping支援Ant風格的請求路徑,見源碼
1、 Ant風格資源位址支援3種比對符
- ?:比對檔案名中的一個字元
- * :比對檔案名中的任意字元
- ** :比對多層路徑
2 @RequestMapping支援Ant風格的URL
- /usercreateUser :比對/user/createUser
- 比對/user/aaa/bbb/createUser
- /user/createUser?? :比對/user/createUseraa
- 比對/user/createUserbb
3、測試
- 控制器
-
@RequestMapping(value="/user/*/createUser")
-
public String createUser(){
-
System.out.println("createUser");
-
return "success";
-
}
- 請求
-
a href="mappingOther/user/aaa/createUser">ant風格</a>
四、REST
1、知識點
- 浏覽器form表單隻支援GET與POST請求,而DELETE、PUT等method并不支援,spring3.0添加了一個過濾器,可以将這些請求轉換為标準的http方法,使得支援GET、POST、PUT與DELETE請求,該過濾器為HiddenHttpMethodFilter。
- HiddenHttpMethodFilter的父類是OncePerRequestFilter,它繼承了父類的doFilterInternal方法,工作原理是将jsp頁面的form表單的method屬性值在doFilterInternal方法中轉化為标準的Http方法,即GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE,然後到Controller中找到對應的方法。例如,在使用注解時我們可能會在Controller中用于@RequestMapping(value = "list", method = RequestMethod.PUT),是以如果你的表單中使用的是<form method="put">,那麼這個表單會被送出到标了Method="PUT"的方法中。
- REST:Representational State Transfer.即(資源)表現層狀态轉化。
- 資源(Resources):網絡上的一個實體,它可以是一段文本、一張圖檔、一首歌曲、一種服務等。可以用一個URI指向它。第一種資源對應一個特定的URI.也就是說,URI即為每個資源的獨一無二的識别符。
- 表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層。比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式。
- 狀态轉化(State Transfer):每發出一個請求,就代表了用戶端和伺服器一次互動過程。HTTP協定,是一個無狀态協定,即所有的狀态都儲存在服務端。是以,如果客戶想要操作伺服器,必須通過某種手段,讓服務端發生“狀态轉化”。而這種轉化是建立在表現之上的。具體來說,就是HTTP協定裡面,四個表示操作方式的動詞
- GET:擷取資源
- POST:建立資源
- PUT:更新資源
- DELETE:删除資源
- 示例
- /order/1 HTTP GET:得到id=1的order
- /order/1 HTTP DELETE:删除id=1的order
- /order/1 HTTP PUT:更新id=1的order
- /order/1 HTTP POST:新增id=1的order
- HiddenHttpMethodFilter
- 浏覽器form表單隻支援GET與POST請求,而DELETE、PUT等method并不支援
- Spring3.0添加一個過濾器,可以将這些請求轉換為标準的http方法,使其支援GET、POST、PUT與DELETE請求
2、測試
- 在web.xml檔案中HiddenHttpMethodFilter
-
<filter>
-
<filter-name>hiddenHttpMethodFilter</filter-name>
-
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
-
</filter>
-
<filter-mapping>
-
<filter-name>hiddenHttpMethodFilter</filter-name>
-
<url-pattern>/*</url-pattern>
-
</filter-mapping>
- 控制器
-
@RequestMapping("/testREST")
-
@Controller
-
public class TestREST {
-
@RequestMapping(value="/testRest/{id}",method=RequestMethod.GET)
-
public String testRestGet(@PathVariable Integer id){
-
System.out.println("testRest GET:"+id);
-
return "success";
-
}
-
@RequestMapping(value="/testRest/{id}",method=RequestMethod.POST)
-
public String testRestPost(@PathVariable Integer id){
-
System.out.println("testRest POST:"+id);
-
return "success";
-
}
-
@RequestMapping(value="/testRest/{id}",method=RequestMethod.DELETE)
-
public String testRestDelete(@PathVariable Integer id){
-
System.out.println("testRest Delete:"+id);
-
return "success";
-
}
-
@RequestMapping(value="/testRest/{id}",method=RequestMethod.PUT)
-
public String testRestPut(@PathVariable Integer id){
-
System.out.println("testRest Put:"+id);
-
return "success";
-
}
-
}
- 請求
-
<a href="testREST/testRest/1">測試Get</a>
-
<form action="testREST/testRest/1" method="post">
-
<input type="submit" value="測試post">
-
</form>
-
<form action="testREST/testRest/1" method="post">
-
<input type="hidden" name="_method" value="DELETE">
-
<input type="submit" value="測試DELETE">
-
</form>
-
<form action="testREST/testRest/1" method="post">
-
<input type="hidden" name="_method" value="PUT">
-
<input type="submit" value="測試PUT">
-
</form>
3、注意
- 如果用tomcat8作為伺服器,在測試DELETE和Put的時候,會報405錯誤
解決方法有三種
- 一是将Tomcat8改為Tomcat7,在Tomcat7下運作是正常的.或者更新到tomcat 8.0.9以上版本
- 二是将請求轉發(forward)改為redirect
- 三是自己手動寫一個Filter來包裝HttpRequest中的getMethod方法
下面主要介紹一下第三種方法:也就是自己寫一個Filter來包裝從伺服器發回來的HttpRequest請求:
大緻說一下流程, 1. 在第1步中,用戶端發送請求至伺服器,這時如果發送的是POST請求且帶有以_method為名的參數會被Spring的HiddenHttpMethodFilter給攔截。 2. HiddenHttpMethodFilter内有一個靜态内部類通過繼承HttpServletRequestWrapper類并重寫getMethod()方法,将該方法傳回值設為_method隐藏域的值。 3. HiddenHttpMethodFilter在包裝好Request後,将請求發往伺服器的控制器中對應的方法處理器,這時的請求變成了圖中的 3、WrapperRequest by SpringFilter 4. 伺服器處理完請求後,産生了一個forward請求,産生相應的請求處理資訊發往用戶端,注意這時的request的getMethod()方法仍然是HiddenHttpMethodFilter包裝過的 5. 我們需要在伺服器的響應請求到達用戶端前進行攔截,這也是最關鍵的一步,通過自定義過濾器 MyMethodConvertingFilter 進一步包裝請求,将getMethod()方法傳回值改成POST或GET即可
-
public class MyMethodConvertingFilter implements Filter {
-
@Override
-
public void destroy() {
-
// TODO Auto-generated method stub
-
}
-
@Override
-
public void doFilter(ServletRequest request, ServletResponse response,
-
FilterChain chain) throws IOException, ServletException {
-
wrapRequest((HttpServletRequest) request), response);chain.doFilter(
-
}
-
@Override
-
public void init(FilterConfig arg0) throws ServletException {
-
// TODO Auto-generated method stub
-
}
-
private static HttpServletRequestWrapper wrapRequest(HttpServletRequest request) {
-
return new HttpServletRequestWrapper(request) {
-
@Override
-
public String getMethod() {
-
return "GET";
-
}
-
};
-
}
-
}
6. 在web.xml中配置該filter,注意dispatcher結點值必須為FORWARD。
-
<filter-mapping>
-
<filter-name>myFilter</filter-name>
-
<url-pattern>/*</url-pattern>
-
<dispatcher>FORWARD</dispatcher>
-
</filter-mapping>
關注我們
師享空間的宗旨是分享知識,傳播價值。關注我們,及時獲得更多資訊。
捐贈我們
如果您對我們的成果表示認同并且覺得對你有所幫助,歡迎您對我們捐贈^_^。
轉載于:https://www.cnblogs.com/imentors/p/5009186.html