文章目錄
- @Controller
- @RequestMapping
- 參數綁定常用的注解
- @PathVariable
- @ReuqestHeader和@CookieValue
- @RequestParam
- @ResponseBody和@RequestBody
- @ModelAttribute
- @SessionAttributes和@SessionAttribute
@Controller
Controller也就是我們常說的控制器,負責處理由DispatcherServler分發的使用者請求,将請求資料處理後封裝成ModelAndView傳回。
@Controller這個注解就是用來标記控制器的,被它标記的類就是控制器。Controller通過@RequestMapping來定義URL和其方法之間的映射。
分發處理器将會掃描使用了@Controller注解的類中用@RequestMapping 注解的方法,直到找到具體處理URL請求的方法。
- @Controller隻是定義了一個控制器類,并不是真正的控制器。
-
在使用了@Controller注解的類中,使用@RequesMapping注解的方法才是真正的控制器。
如果想讓你自己定義的Controller被SpringMVC掃描到,你需要在SpringMVC的配置檔案中進行配置,有兩種方法:
- 定義Controller的bean對象(路徑寫全)
- 配置全局注解掃描 (路徑寫到包名即可)
一般我們采用第二種方式,把所有的控制器放在一個或者幾個包下,一并掃描,在這之前,你需要配置SpringMVC的注解驅動(這麼寫不需要再配置處理器映射器和處理器擴充卡):
@RequestMapping
@RequestMapping是一個用來處理請求位址映射的注解(将請求映射到對應的控制器方法中),可以用在類或者方法中。
用類上表示類中的所有響應請求的方法都是以該位址作為父路徑,那麼要想通路該控制器下的方法,都要加上這個路徑。
用在方法上則表示這個方法用來專門處理該位址的請求。
- @RequestMapping的屬性
- value:指定請求的url。
- 普通值。比如
@RequestMapping(value="/test")
- 支援RESTful風格(将請求參數傳遞在url位址中)。比如
,t_id和t_name可以當做變量用@PathVariable注解來提取。(下面介紹)
@RequestMapping(value="/test/{t_id}/{t_name}")
- 支援ant風格。
比對任何單字元,
?
比對0或者任意數量的字元
*
比對0或者更多的目錄。比如
**
@RequestMapping(value="/test/t_*")
- 支援正規表達式。比如
。同樣可以通過@PathVariable提取t_id。
@RequestMapping(value="/test/{t_id:a-z0-9+}")
- 支援多路徑通路。比如
。那麼/test,/test2,test3都會映射到該方法上。
@RequestMapping(value={"/test","/test2","test3"})
- method:指定請求的方式,常見的有GET,POST,PUT,DELETE等。
比如 @RequestMapping(value="/test",method={RequestMethod.GET,RequestMethod.POST})
- params:指定request中必須包含的某些參數值。
比如 @RequestMapping(value="/test",params="user=001")
,http://localhost:8080/test?user=001 那麼才能通路到(名和值都要比對)。
- headers:指定請求位址url中必須包含指定的heard值。
比如
@RequestMapping(value="/test",headers="Referer=http://www.admin.com/")
。
那麼請求的URL必須為"/test"且請求頭必須有包含“Referer”的請求頭和對應值為http://www.admin.com/的請求。
- consumes: 指定處理請求的送出内容類型(Content-Type)。
例如 @RequestMapping(value = "/test", method = RequestMethod.POST, consumes="application/json")
方法僅處理request Content-Type為“application/json”類型的請求。
- produces: 指定傳回的内容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才傳回。
例如 @RequestMapping(value = "/test", method = RequestMethod.POST, produces="application/json")
方法僅處理request請求中Accept頭中包含了"application/json"的請求,同時暗示了傳回的内容類型為application/json;
參數綁定常用的注解
根據處理的Request的不同内容部分分為四類:
- 處理requet uri 部分的注解: @PathVariable;
- 處理request header部分的注解: @RequestHeader, @CookieValue;
- 處理request body部分的注解:@RequestParam, @RequestBody;
- 處理attribute類型是注解: @SessionAttributes, @ModelAttribute;
@PathVariable
@PathVariable注解的位置是方法參數。
@PathVariable這個注解用來将請求URL中的模闆變量映射到處理方法的參數上。
示例:
@RequestMapping(value="/users/{user}/password/{password}")
public void test(
@PathVariable(value="user"))String user,
@PathVariable(value="password")String password){
// TODO
System.out.prinlln("user:"+user);
System.out.println("passord"+password);
}
比如url為/users/admin/password/12345那麼會自動将其與test方法中用@PathVariable注解的同名參數綁定,也就是說,方法中變量user和password的值就是admin和12345。
@ReuqestHeader和@CookieValue
@ReuqestHeader和@CookieValue這兩個注解的位置都是在方法參數上。前者用來将Request請求的header部分的值綁定到方法的參數上。
比如:
這是一個Request 的header部分:
Host:localhost:8080
Accept:text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language:fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding:gzip,deflate
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive:300
@RequestMapping("/testHeader")
public void testHeader(
@RequestHeader("Host")String host,
@RequestHeader("Accept")String accept){
// TODO
}
通過這種方式,可以将header部分的值綁定到方法的參數對象上。
@CookieValue可以把Request Header部分中cookie的值綁定到方法的參數上:
例如有如下的cookie值:status=online
@RequestMapping("/testCookie")
public void testCookie(@CookieValue("status")String status){
// TODO
}
将status的值綁定到參數上。
@RequestParam
@RequestParam注解的位置:方法參數上。
這個注解用于在SpringMVC背景控制層擷取參數(簡單類型),@RequestParam注解會通過request.getParameter(" ")将擷取的Stirng直接與方法參數綁定(String–>簡單類型的轉換有ConversionService配置的轉換器來完成)。因為使用request.getParameter()方式擷取參數,是以可以處理get 方式中queryString的值,也可以處理post方式中 body data的值。也可以用來解決請求參數的名稱和controller方法的參數名稱不一緻時的參數綁定問題。
它有四個個常用的屬性:
- name 表示請求參數的名稱
- value 與name互為别名,無異
- required 值為true|false。表示該參數是否必要。
- defaultValue 給定一個預設值。
@ResponseBody和@RequestBody
- @ResponseBody注解的位置是在方法上。
@ResponseBody表示該方法的傳回結果直接寫入HTTP response body中,一般在異步擷取資料時使用(AJAX),在使用@RequestMapping路徑後,傳回值通常解析為跳轉路徑,加上@ResponseBody後傳回結果不會别解析為跳轉路徑,而是直接寫入HTTP response body中。常用在異步擷取json資料,加上@ResponseBody後,會将傳回結果對象解析為json資料傳回。
@RequestMapping("/responseBody")
@ResponseBody
public User responseBody(){
User user = new User();
user.setId(2);
user.setUsername("lisi");
user.setPassword("123456");
return user;//{"id":2,"username":"lisi","password":"123456"}
}
這個方法會在執行結束後自動以responseBody為邏輯視圖名傳回view。你可以自己建一個真實視圖,頁面上就會顯示{“id”:2,“username”:“lisi”,“password”:“123456”}。
- @RequestBody注解的位置是在方法參數上。
@RequestBody用于将前天發送過來的固定格式的資料(xml,json等)封裝成對應的JavaBean對象,封裝使用的HandlerAdapter 預設配置的HttpMessageConverter,它負責将資料解析然後封裝到形參對象上。該注解通常用來處理Content-Type(不是application/x-www-form-urlencoded編碼的内容,例如application/json,application/xml等)
/**
* @RequestBody User user是用來把請求的json資料格式自動的轉成實體類對象
*/
@RequestMapping("/requestBody")
public String requestBody(@RequestBody User user, Model model) {
model.addAttribute("user", user);
return "forward:index.jsp";
}
@ModelAttribute
- @ModelAttribute注釋的位置:1. 方法參數 2. 方法。
當@ModelAttribute注釋在方法參數上時,會将該參數對象添加到Model中。
當@ModelAttribute注釋在方法上時,該方法就變成了非請求處理方法:該Controller的所有方法在調用前,都會先執行該方法。
被@ModelAttribute注釋的方法表示這個方法的目的是增加一個或多個模型(model)屬性。這個方法和别@RequestMapping注釋的方法一樣同樣支援@RequestParam參數,但是不能直接被請求映射。
一個Controller可以有多個@ModelAttribute方法,這些方法都會在@RequestMapping方法被調用之前先執行。
- @ModelAttribute注釋在方法上
- 傳回值為void的方法
@Controller
public class TestController {
@ModelAttribute
public void populateModel(@RequestParam(value="user") String user, Model model) {
model.addAttribute("user", user);
}
@RequestMapping(value = "/login")
public String login() {
return "login";
}
}
本例中,在擷取了/login的請求後,populateModel()方法會在login()方法執行前執行,并把請求參數(/login/username=“xxx”)加到model屬性(user)中。那麼在login方法執行後會傳回視圖名login和populateModel建立好的model。
2. 傳回具體類的方法
@ModelAttribute
public User getUser(String username){
if(username!=null && !username.equals("admin")){
return userService.getUserInfo(username);
}
return null;
}
這種情況下,model的屬性的名稱沒有指定,它有傳回類型隐含表示,比如這個方法傳回User類型,那麼這個model屬性名稱就是user,值為方法的傳回值。
當然,你也可以自己指定屬性名:
@ModelAttribute(value="user")
public User getUser(String username){
if(username!=null && !username.equals("admin")){
return userService.getUserInfo(username);
}
return null;
}
- @ModelAttribute注釋在方法參數上
ModelAtrribute注釋的方法參數表示應從模型model中取得,如果model中沒有找到,那麼這個參數就會先被執行個體化加入到model中。若在model中找到了它,請求參數名稱和model屬性字段相比對就會自動填充。這個機制對于表單送出資料表單到對象屬性上很有效。
用來通過名稱對應,把相應名稱的值綁定到注解的參數bean上;要綁定的值來源于:
A) @SessionAttributes 啟用的attribute 對象上;
B) @ModelAttribute 用于方法上時指定的model對象;
C) 上述兩種情況都沒有時,new一個需要綁定的bean對象,然後把request中按名稱對應的方式把值綁定到bean中。
@RequestMapping("/test")
public String getUser(@ModelAtrribute("user") User user){
user.setUsername="xxx";
user.setPassword="xxx";
return "login";
}
本例中,首先查詢 @SessionAttributes有無綁定的user對象,不存在則去查詢model中是否綁定了user對象,二者都沒就會先調用User的構造方法建立一個user,當請求路徑的請求參數或者送出的表單與user的屬性名(username|password)比對時,就會自動将其值綁定到user對象中。比如請求路徑為
http://localhost/springmvc_001/login.htm?username="xxx"?password="xxx"
,user對象中的屬性username和password将會被設定為xxx。
- 使用場景
我們一般用@ModelAttribute來注解參數,某種程度上@ModelAttribute和@RequestParam功能相似,不同的是@RequestParam用于綁定單個參數值,而@ModelAttribute注解可以綁定所有名稱比對的,此外它自動将綁定後的資料添加到模型中,無形中也給我們提供了便利。
@SessionAttributes和@SessionAttribute
- @SessionAttributes
實際上,Model中的屬性作用域是request級别的,也就是說,隻是目前請求有效。如果希望在多個請求中共享ModelMap中的屬性,必須将其舒心轉存到session中,這樣Model中的屬性才能跨請求通路。
簡而言之,@SessionAttributes是添加在controller的類名上。@SessionAttributes注解作用,是将model中的資料再向session中存一份以便跨請求通路。
@Controller
@SessionAttributes("username")
public class myController {
//将Model屬性名為username的屬性放到Session屬性清單中,以便這個屬性可以跨請求通路
//在該controller中的方法中往model存入屬性為username的鍵值對時會自動的往session中存一份
//那麼你就可以在下一次通路(session有效期内)中用session.getAtrribute("username")取到
}
當然你也可以指定多個屬性,比如
@SessionAttributes(value={"username","password"})
。此外,@SessionAttributes 還可以通過類型指定屬性,比如
@SessionAttribute(types=User.class)
,類型同樣可以有多個。
- @SessionAttribute
SessionAttribute可以擷取session(HttpSession以及@SessionAttributes)中的資料。
- session的清空
@SessionAttributes需要清除時,使用來清除。注意,它隻清除@SessionAttributes的session,不會清除HttpSession的資料。故如使用者身份驗證對象的session一般不用它來實作,還是用session.setAttribute等傳統的方式實作。如果你想清空未使用注解方式儲存的session資料,使用
SessionStatus.setComplete();
它清空的是HttpSession中的資料。
session.invalidate();
看個@SessionAttribute和session清空的案例:
@RequestMapping("/testGetSessionAttribute")
public String testGetSessionAttribute(
@SessionAttribute(name = "user") User user,
@SessionAttribute(name = "valide_code") String valide_code,
HttpSession session,
SessionStatus sessionStatus) {
// 清空session,隻會清空未使用注解方式儲存的session資料
// session.invalidate();
// 清空session的方法,清空使用@SessionAttributes儲存的資料
sessionStatus.setComplete();
// System.out.println("user_name:"+user.getUsername());
// System.out.println("pass_word:"+user.getPassword());
System.out.println("valide_code:" + valide_code);
return "forward:session_attr.jsp";
}