天天看點

SpringMVC——常用注解總結@Controller@RequestMapping參數綁定常用的注解@PathVariable@ReuqestHeader和@CookieValue@RequestParam@ResponseBody和@RequestBody@ModelAttribute@SessionAttributes和@SessionAttribute

文章目錄

  • @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的配置檔案中進行配置,有兩種方法:

  1. 定義Controller的bean對象(路徑寫全)
  1. 配置全局注解掃描 (路徑寫到包名即可)

一般我們采用第二種方式,把所有的控制器放在一個或者幾個包下,一并掃描,在這之前,你需要配置SpringMVC的注解驅動(這麼寫不需要再配置處理器映射器和處理器擴充卡):

@RequestMapping

@RequestMapping是一個用來處理請求位址映射的注解(将請求映射到對應的控制器方法中),可以用在類或者方法中。

用類上表示類中的所有響應請求的方法都是以該位址作為父路徑,那麼要想通路該控制器下的方法,都要加上這個路徑。

用在方法上則表示這個方法用來專門處理該位址的請求。

  • @RequestMapping的屬性
  1. value:指定請求的url。
  • 普通值。比如

    @RequestMapping(value="/test")

  • 支援RESTful風格(将請求參數傳遞在url位址中)。比如

    @RequestMapping(value="/test/{t_id}/{t_name}")

    ,t_id和t_name可以當做變量用@PathVariable注解來提取。(下面介紹)
  • 支援ant風格。

    ?

    比對任何單字元,

    *

    比對0或者任意數量的字元

    **

    比對0或者更多的目錄。比如

    @RequestMapping(value="/test/t_*")

  • 支援正規表達式。比如

    @RequestMapping(value="/test/{t_id:a-z0-9+}")

    。同樣可以通過@PathVariable提取t_id。
  • 支援多路徑通路。比如

    @RequestMapping(value={"/test","/test2","test3"})

    。那麼/test,/test2,test3都會映射到該方法上。
  1. method:指定請求的方式,常見的有GET,POST,PUT,DELETE等。
比如

@RequestMapping(value="/test",method={RequestMethod.GET,RequestMethod.POST})

  1. params:指定request中必須包含的某些參數值。
比如

@RequestMapping(value="/test",params="user=001")

,http://localhost:8080/test?user=001 那麼才能通路到(名和值都要比對)。
  1. headers:指定請求位址url中必須包含指定的heard值。
比如

@RequestMapping(value="/test",headers="Referer=http://www.admin.com/")

那麼請求的URL必須為"/test"且請求頭必須有包含“Referer”的請求頭和對應值為http://www.admin.com/的請求。

  1. consumes: 指定處理請求的送出内容類型(Content-Type)。
例如

@RequestMapping(value = "/test", method = RequestMethod.POST, consumes="application/json")

方法僅處理request Content-Type為“application/json”類型的請求。
  1. produces: 指定傳回的内容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才傳回。
例如

@RequestMapping(value = "/test", method = RequestMethod.POST, produces="application/json")

方法僅處理request請求中Accept頭中包含了"application/json"的請求,同時暗示了傳回的内容類型為application/json;

參數綁定常用的注解

根據處理的Request的不同内容部分分為四類:

  1. 處理requet uri 部分的注解: @PathVariable;
  2. 處理request header部分的注解: @RequestHeader, @CookieValue;
  3. 處理request body部分的注解:@RequestParam, @RequestBody;
  4. 處理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方法的參數名稱不一緻時的參數綁定問題。

它有四個個常用的屬性:

  1. name 表示請求參數的名稱
  2. value 與name互為别名,無異
  3. required 值為true|false。表示該參數是否必要。
  4. 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注釋在方法上
  1. 傳回值為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

  1. @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)

,類型同樣可以有多個。

  1. @SessionAttribute
SessionAttribute可以擷取session(HttpSession以及@SessionAttributes)中的資料。
  1. session的清空
@SessionAttributes需要清除時,使用

SessionStatus.setComplete();

來清除。注意,它隻清除@SessionAttributes的session,不會清除HttpSession的資料。故如使用者身份驗證對象的session一般不用它來實作,還是用session.setAttribute等傳統的方式實作。如果你想清空未使用注解方式儲存的session資料,使用

session.invalidate();

它清空的是HttpSession中的資料。

看個@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";

}
           

繼續閱讀