springmvc 註解總結


1、@RequestMapping
@RequestMapping
RequestMapping是一個用來處理請求地址映射的註解(將請求映射到對應的控制器方法中),可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作爲父路徑。
RequestMapping請求路徑映射,如果標註在某個controller的類級別上,則表明訪問此類路徑下的方法都要加上其配置的路徑;最常用是標註在方法上,表明哪個具體的方法來接受處理某次請求。

複製代碼複製代碼

@Controller @RequestMapping(value="/book") public class BookController {     @RequestMapping(value="/title")     public String getTitle(){         return "title";     }                     @RequestMapping(value="/content")     public String getContent(){         return "content";     }  }

複製代碼複製代碼

由於BookController類加了value="/book"的@RequestMapping的註解,所以相關路徑都要加上"/book",即請求的url分別爲:
(1)http://localhost:8080/book/title 
(2)http://localhost:8080/book/content
"@RequestMapping"的value值前後是否有“/”對請求的路徑沒有影響,即value="book" 、"/book"、"/book/"其效果是一樣的。

RequestMapping的屬性
value:指定請求的實際url
(1)普通的具體值。如前面的value="/book"。
(2)含某變量的一類值。

@RequestMapping(value="/get/{bookId}") public String getBookById(@PathVariable String bookId,Model model){     model.addAttribute("bookId", bookId);     return "book"; }

路徑中的bookId可以當變量,@PathVariable註解即提取路徑中的變量值。
(3)ant風格
@RequestMapping(value="/get/id?"):可匹配“/get/id1”或“/get/ida”,但不匹配“/get/id”或“/get/idaa”;
@RequestMapping(value="/get/id*"):可匹配“/get/idabc”或“/get/id”,但不匹配“/get/idabc/abc”;
@RequestMapping(value="/get/id/*"):可匹配“/get/id/abc”,但不匹配“/get/idabc”;
@RequestMapping(value="/get/id/**/{id}"):可匹配“/get/id/abc/abc/123”或“/get/id/123”,也就是Ant風格和URI模板變量風格可混用。
(4)含正則表達式的一類值
@RequestMapping(value="/get/{idPre:\\d+}-{idNum:\\d+}"):可以匹配“/get/123-1”,但不能匹配“/get/abc-1”,這樣可以設計更加嚴格的規則。
可以通過@PathVariable 註解提取路徑中的變量(idPre,idNum)
(5)或關係
@RequestMapping(value={"/get","/fetch"} )即 /get或/fetch都會映射到該方法上。

method:指定請求的method類型, GET、POST、PUT、DELETE等;
@RequestMapping(value="/get/{bookid}",method={RequestMethod.GET,RequestMethod.POST})

params:指定request中必須包含某些參數值是,才讓該方法處理。
@RequestMapping(params="action=del"),請求參數包含“action=del”,如:http://localhost:8080/book?action=del

複製代碼複製代碼

@Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController {   @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")   public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {         // implementation omitted   } }

複製代碼複製代碼

 僅處理請求中包含了名爲“myParam”,值爲“myValue”的請求。

headers:指定request中必須包含某些指定的header值,才能讓該方法處理請求。
@RequestMapping(value="/header/id", headers = "Accept=application/json"):表示請求的URL必須爲“/header/id 且請求頭中必須有“Accept =application/json”參數即可匹配。

複製代碼複製代碼

@Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { @RequestMapping(value = "/pets", method = RequestMethod.GET, headers="Referer=http://www.ifeng.com/")   public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {         // implementation omitted   } }

複製代碼複製代碼

 僅處理request的header中包含了指定“Refer”請求頭和對應值爲“http://www.ifeng.com/”的請求。

consumes:指定處理請求的提交內容類型(Content-Type),例如application/json, text/html。

@Controller @RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") public void addPet(@RequestBody Pet pet, Model model) {         // implementation omitted }

 方法僅處理request Content-Type爲“application/json”類型的請求。
produces: 指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回。 

@Controller @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json") @ResponseBody public Pet getPet(@PathVariable String petId, Model model) {         // implementation omitted }

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

2、@RequestParam綁定單個請求參數值
@RequestParam用於將請求參數區數據映射到功能處理方法的參數上。

public String requestparam1(@RequestParam String username)

 請求中包含username參數(如/requestparam1?username=zhang),則自動傳入。

@RequestParam有以下三個參數:
value:參數名字,即入參的請求參數名字,如username表示請求的參數區中的名字爲username的參數的值將傳入;
required:是否必須,默認是true,表示請求中一定要有相應的參數,否則將拋出異常;
defaultValue:默認值,表示如果請求中沒有同名參數時的默認值,設置該參數時,自動將required設爲false。

public String requestparam4(@RequestParam(value="username",required=false) String username)

表示請求中可以沒有名字爲username的參數,如果沒有默認爲null,此處需要注意如下幾點:
原子類型:必須有值,否則拋出異常,如果允許空值請使用包裝類代替。
Boolean包裝類型:默認Boolean.FALSE,其他引用類型默認爲null。

如果請求中有多個同名的應該如何接收呢?如給用戶授權時,可能授予多個權限,首先看下如下代碼:

public String requestparam7(@RequestParam(value="role") String roleList)

如果請求參數類似於url?role=admin&rule=user,則實際roleList參數入參的數據爲“admin,user”,即多個數據之間使用“,”分割;我們應該使用如下方式來接收多個請求參數:

public String requestparam7(@RequestParam(value="role") String[] roleList)

或者

public String requestparam8(@RequestParam(value="list") List<String> list)

3、@PathVariable綁定URI模板變量值
@PathVariable用於將請求URL中的模板變量映射到功能處理方法的參數上。

@RequestMapping(value="/users/{userId}/topics/{topicId}") public String test(        @PathVariable(value="userId") int userId,         @PathVariable(value="topicId") int topicId)

 如請求的URL爲“控制器URL/users/123/topics/456”,則自動將URL中模板變量{userId}和{topicId}綁定到通過@PathVariable註解的同名參數上,即入參後userId=123、topicId=456。

4、@ModelAttribute

ModelAttribute可以應用在方法參數上或方法上,他的作用主要是當註解在方法參數上時會將註解的參數對象添加到Model中;當註解在請求處理方法Action上時會將該方法變成一個非請求處理的方法,但其它Action被調用時會首先調用該方法。

4.1 @ModelAttribute註釋一個方法

被@ModelAttribute註釋的方法表示這個方法的目的是增加一個或多個模型(model)屬性。這個方法和被@RequestMapping註釋的方法一樣也支持@RequestParam參數,但是它不能直接被請求映射。實際上,控制器中的@ModelAttribute方法是在同一控制器中的@RequestMapping方法被調用之前調用的。

被@ModelAttribute註釋的方法用於填充model屬性,例如,爲下拉菜單填充內容,或檢索一個command對象(如,Account),用它來表示一個HTML表單中的數據。
一個控制器可以有任意數量的@ModelAttribute方法。所有這些方法都在@RequestMapping方法被調用之前調用。
有兩種類型的@ModelAttribute方法。一種是:只加入一個屬性,用方法的返回類型隱含表示。另一種是:方法接受一個Model類型的參數,這個model可以加入任意多個model屬性。

(1)@ModelAttribute註釋void返回值的方法

複製代碼複製代碼

@Controller @RequestMapping(value="/test") public class TestController {          /**      * 1.@ModelAttribute註釋void返回值的方法       * @param abc      * @param model      */     @ModelAttribute     public void populateModel(@RequestParam String abc, Model model) {         model.addAttribute("attributeName", abc);     }          @RequestMapping(value = "/helloWorld")     public String helloWorld() {        return "test/helloWorld";     } }

複製代碼複製代碼

這個例子,在獲得請求/helloWorld 後,populateModel方法在helloWorld方法之前先被調用,它把請求參數(/helloWorld?abc=text)加入到一個名爲attributeName的model屬性中,在它執行後helloWorld被調用,返回視圖名helloWorld和model已由@ModelAttribute方法生產好了。
這個例子中model屬性名稱和model屬性對象由model.addAttribute()實現,不過前提是要在方法中加入一個Model類型的參數。

(2)@ModelAttribute註釋返回具體類的方法

複製代碼複製代碼

/**  * 2.@ModelAttribute註釋返回具體類的方法  * @param id  * @return  */ @ModelAttribute public User getUserInfo(String id){     if(id!=null && !id.equals("")){         return userService.getUserInfo(id);     }     return null; }

複製代碼複製代碼

這種情況,model屬性的名稱沒有指定,它由返回類型隱含表示,如這個方法返回User類型,那麼這個model屬性的名稱是user。
這個例子中model屬性名稱有返回對象類型隱含表示,model屬性對象就是方法的返回值。它無須要特定的參數。

(3)@ModelAttribute(value="")註釋返回具體類的方法

複製代碼複製代碼

@Controller @RequestMapping(value="/test") public class TestController {          /**      * 3.@ModelAttribute(value="")註釋返回具體類的方法       * @param abc      * @return      */     @ModelAttribute("str")     public String getParam(@RequestParam String param) {         return param;     }          @RequestMapping(value = "/helloWorld")     public String helloWorld() {        return "test/helloWorld";     } }

複製代碼複製代碼

這個例子中使用@ModelAttribute註釋的value屬性,來指定model屬性的名稱。model屬性對象就是方法的返回值。它無須要特定的參數。

完整的代碼:

複製代碼複製代碼

package demo.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import demo.model.User; import demo.service.IUserService; @Controller @RequestMapping(value="/test") public class TestController {          @Autowired     private IUserService userService;          /**      * 1.@ModelAttribute註釋void返回值的方法       * @param abc      * @param model      */     @ModelAttribute     public void populateModel(@RequestParam String abc, Model model) {         model.addAttribute("attributeName", abc);     }          /**      * 2.@ModelAttribute註釋返回具體類的方法       * @param id      * @return      */     @ModelAttribute     public User getUserInfo(String id){         if(id!=null && !id.equals("")){             return userService.getUserInfo(id);         }         return null;     }          /**      * 3.@ModelAttribute(value="")註釋返回具體類的方法       * @param abc      * @return      */     @ModelAttribute("str")     public String getParam(@RequestParam String param) {         return param;     }          @RequestMapping(value = "/helloWorld")     public String helloWorld() {        return "test/helloWorld";     } }

複製代碼複製代碼

Jsp前臺取值:

複製代碼複製代碼

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>   <head>      <title>helloWorld</title>   </head>      <body>        1.The attributeValue is:  ${attributeName}        <br/><br/>                2.用戶信息:<br/>        姓名:${user.user_name}<br/>        年齡:${user.user_age}<br/>        郵箱:${user.user_email}<br/><br/>              3.The param is:  ${str}   </body> </html>

複製代碼複製代碼

頁面效果圖:

URL格式:http://localhost/SSMDemo/test/helloWorld?abc=text&id=1&param=aaa 注:當url或者post中不包含參數abc和參數param時,會報錯。

(4)@ModelAttribute和@RequestMapping同時註釋一個方法

複製代碼複製代碼

@Controller @RequestMapping(value="/test") public class TestController {     @RequestMapping(value = "/helloWorld")     @ModelAttribute("attributeName")     public String helloWorld() {        return "hi";     } }

複製代碼複製代碼

這時這個方法的返回值並不是表示一個視圖名稱,而是model屬性的值,視圖名稱由RequestToViewNameTranslator根據請求"/helloWorld"轉換爲helloWorld。Model屬性名稱由@ModelAttribute(value=””)指定,相當於在request中封裝了key=attributeName,value=hi。

Jsp頁面:

複製代碼複製代碼

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>   <head>      <title>helloWorld</title>   </head>      <body>       The attributeValue is:  ${attributeName}   </body> </html>

複製代碼複製代碼

 4.2 @ModelAttribute註釋一個方法的參數

@ModelAttribute註釋方法的一個參數表示應從模型model中取得。若在model中未找到,那麼這個參數將先被實例化後加入到model中。若在model中找到,則請求參數名稱和model屬性字段若相匹配就會自動填充。這個機制對於表單提交數據綁定到對象屬性上很有效。

當@ModelAttribute註解用於方法參數時,它有了雙重功能,即“存/取”。首先,它從模型中取出數據並賦予對應的參數,如果模型中尚不存在,則實例化一個,並存放於模型中;其次,一旦模型中已存在此數據對象,接下來一個很重要的步驟便是將請求參數綁定到此對象上(請求參數名映射對象屬性名),這是Spring MVC提供的一個非常便利的機制--數據綁定。

@RequestMapping(value = "/login.htm", method = RequestMethod.GET) public String doLogin(@ModelAttribute("baseMember") BaseMember member) {     member.setLoginName("loginName");     return "home"; }

上述代碼中,如果模型中尚不存在鍵名爲“baseMember”的數據,則首先會調用BaseMember類的默認構造器創建一個對象,如果不存在默認構造器會拋出異常。因此,給實體類提供一個默認構造器是一個好的編程習慣。當請求路徑的請求參數或提交的表單與BaseMember的屬性名匹配時,將自動將其值綁定到baseMember對象中,非常的便利!這可能是我們使用@ModelAttribute最主要的原因之一。比如:請求路徑爲http://localhost:8080/spring-web/login.htm?loginName=myLoginName,baseMember對象中的loginName屬性的值將被設置爲myLoginName。

4.3 @ModelAttribute註解的使用場景 
當@ModelAttribute註解用於方法時,與其處於同一個處理類的所有請求方法執行前都會執行一次此方法,這可能並不是我們想要的,因此,我們使用更多的是將其應用在請求方法的參數上,而它的一部分功能與@RequestParam註解是一致的,只不過@RequestParam用於綁定單個參數值,而@ModelAttribute註解可以綁定所有名稱匹配的,此外它自動將綁定後的數據添加到模型中,無形中也給我們提供了便利,這也可能是它命名爲ModelAttribute的原因。

5、SessionAttributes

在默認情況下,ModelMap中的屬性作用域是request級別,也就是說,當本次請求結束後,ModelMap 中的屬性將銷燬。如果希望在多個請求中共享ModelMap中的屬性,必須將其屬性轉存到session 中,這樣 ModelMap 的屬性纔可以被跨請求訪問。
Spring 允許我們有選擇地指定 ModelMap 中的哪些屬性需要轉存到 session 中,以便下一個請求屬對應的 ModelMap 的屬性列表中還能訪問到這些屬性。這一功能是通過類定義處標註 @SessionAttributes 註解來實現的。

複製代碼複製代碼

package demo.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; import demo.model.User; @Controller @RequestMapping(value="/demo1") //(1)將ModelMap中屬性名爲currUser的屬性放到Session屬性列表中,以便這個屬性可以跨請求訪問 @SessionAttributes("currUser") public class Demo1Controller {          @RequestMapping(value="/getUser")     public String getUser(ModelMap model){         User user=new User();         user.setUser_name("zhangsan");         user.setUser_age(25);         user.setUser_email("[email protected]");         //(2)向ModelMap中添加一個屬性          model.addAttribute("currUser",user);         return "/demo/user";     }          @RequestMapping(value="/getUser1")     public String getUser1(ModelMap model){         User user=(User)model.get("currUser");         System.out.println(user.getUser_name());         System.out.println(user.getUser_age());         System.out.println(user.getUser_email());         return "demo/user1";     } }

複製代碼複製代碼

我們在(2)處添加了一個 ModelMap 屬性,其屬性名爲 currUser,而(1)處通過 @SessionAttributes 註解將 ModelMap 中名爲 currUser 的屬性放置到 Session 中,所以我們不但可以在 getUser() 請求所對應的 JSP 視圖頁面中通過 request.getAttribute(“currUser”) 和 session.getAttribute(“currUser”) 獲取 user 對象,還可以在下一個請求(getUser1())所對應的 JSP 視圖頁面中通過 session.getAttribute(“currUser”) 或 session.getAttribute(“currUser”)訪問到這個屬性。

 這裏我們僅將一個 ModelMap 的屬性放入 Session 中,其實 @SessionAttributes 允許指定多個屬性。你可以通過字符串數組的方式指定多個屬性,如 @SessionAttributes({“attr1”,"attr2”})。此外,@SessionAttributes 還可以通過屬性類型指定要 session 化的 ModelMap 屬性,如 @SessionAttributes(types = User.class),當然也可以指定多個類,如 @SessionAttributes(types = {User.class,Dept.class}),還可以聯合使用屬性名和屬性類型指定:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,"attr2”})。

user.jsp頁面:

複製代碼複製代碼

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page import="demo.model.User" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>   <head>     <base href="<%=basePath%>">     <title>My JSP 'index.jsp' starting page</title>   </head>   <body><br>       <%User user=(User)session.getAttribute("currUser");%>       用戶名:<%=user.getUser_name() %><br/>       年齡:<%=user.getUser_age() %><br/>       郵箱:<%=user.getUser_email() %><br/><br/>       <a href="<%=path %>/demo1/getUser1">跳轉</a>   </body> </html>

複製代碼複製代碼

 通過@ModelAttribute綁定

@SessionAttributes 是用來在 controller 內部共享 model 屬性的。我們可以在需要訪問 Session 屬性的 controller 上加上 @SessionAttributes,然後在 action 需要的 User 參數上加上 @ModelAttribute,並保證兩者的屬性名稱一致。SpringMVC 就會自動將 @SessionAttributes 定義的屬性注入到 ModelMap 對象,在 setup action 的參數列表時,去 ModelMap 中取到這樣的對象,再添加到參數列表。只要我們不去調用 SessionStatus 的 setComplete() 方法,這個對象就會一直保留在 Session 中,從而實現 Session 信息的共享。

複製代碼複製代碼

@Controller   @SessionAttributes("currentUser")   public class GreetingController{        @RequestMapping       public void hello(@ModelAttribute("currentUser") User user){        //user.sayHello()        }    }

複製代碼複製代碼

@SessionAttributes清除
@SessionAttributes需要清除時,使用SessionStatus.setComplete();來清除。注意,它只清除@SessionAttributes的session,不會清除HttpSession的數據。故如用戶身份驗證對象的session一般不用它來實現,還是用session.setAttribute等傳統的方式實現。

6、@Responsebody與@RequestBody

@Responsebody表示該方法的返回結果直接寫入HTTP response body中。一般在異步獲取數據時使用,在使用@RequestMapping後,返回值通常解析爲跳轉路徑,加上@Responsebody後返回結果不會被解析爲跳轉路徑,而是直接寫入HTTP response body中。比如異步獲取json數據,加上@Responsebody後,會直接返回json數據。
@RequestBody將HTTP請求正文插入方法中,使用適合的HttpMessageConverter將請求體寫入某個對象。

複製代碼複製代碼

$("#btn2").click(function(){     var url='<%=request.getContextPath()%>/User/addUserInfo';     var data={"user_name":$("#userName").val(),"user_sex":$("#userSex").val(),"user_age":$("#userAge").val(),     "user_email":$("#userEmail").val(),"user_telephone":$("#userTelephone").val(),"user_education":$("#userEducation").val(),     "user_title":$("#userTitle").val()};         $.ajax({        type:'POST',        contentType : 'application/json',          url:url,       dataType:"json",       data:JSON.stringify(data),       async:false,       success:function(data){           alert("新增成功!");             },       error: function(XMLHttpRequest, textStatus, errorThrown){            alert(XMLHttpRequest.status);            alert(XMLHttpRequest.readyState);            alert(textStatus);       }     }) })

複製代碼複製代碼複製代碼複製代碼

@RequestMapping(value="/addUserInfo",method=RequestMethod.POST) @ResponseBody  //將請求中的data寫入UserModel對象中 public String addUserInfo(@RequestBody UserModel user){     System.out.println("user_name--------"+user.getUser_name());     System.out.println("user_sex--------"+user.getUser_sex());     System.out.println("user_age--------"+user.getUser_age());     System.out.println("user_email--------"+user.getUser_email());     System.out.println("user_title--------"+user.getUser_title());     System.out.println("user_education--------"+user.getUser_education());     System.out.println("user_telephone--------"+user.getUser_telephone());     //不會被解析爲跳轉路徑,而是直接寫入HTTP response body中     return "{}"; }

複製代碼複製代碼

@RequestBody 將HTTP請求正文轉換爲適合的HttpMessageConverter對象。
@ResponseBody 將內容或對象作爲 HTTP 響應正文返回,並調用適合HttpMessageConverter的Adapter轉換對象,寫入輸出流。

@RequestBody
作用: 
 i) 該註解用於讀取Request請求的body部分數據,使用系統默認配置的HttpMessageConverter進行解析,然後把相應的數據綁定到要返回的對象上;
 ii) 再把HttpMessageConverter返回的對象數據綁定到 controller中方法的參數上。
使用時機:
A) GET、POST方式提時, 根據request header Content-Type的值來判斷:
application/x-www-form-urlencoded, 可選(即非必須,因爲這種情況的數據@RequestParam, @ModelAttribute也可以處理,當然@RequestBody也能處理);
multipart/form-data, 不能處理(即使用@RequestBody不能處理這種格式的數據);
其他格式, 必須(其他格式包括application/json, application/xml等。這些格式的數據,必須使用@RequestBody來處理);
 
B) PUT方式提交時, 根據request header Content-Type的值來判斷:
application/x-www-form-urlencoded, 必須;
multipart/form-data, 不能處理;
其他格式, 必須;
說明:request的body部分的數據編碼格式由header部分的Content-Type指定;

@ResponseBody
作用: 
 該註解用於將Controller的方法返回的對象,通過適當的HttpMessageConverter轉換爲指定格式後,寫入到Response對象的body數據區。
使用時機:
 返回的數據不是html標籤的頁面,而是其他某種格式的數據時(如json、xml等)使用;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章