Spring從2.5版本開(kāi)始在編程中引入注解,用戶(hù)可以使用@RequestMapping, @RequestParam, @ModelAttribute等等這樣類(lèi)似的注解。到目前為止,Spring的版本雖然發(fā)生了很大的變化,但注解的特性卻是一直延續(xù)下來(lái),并不斷擴(kuò)展,讓廣大的開(kāi)發(fā)人員的雙手變的更輕松起來(lái),這都離不開(kāi)Annotation的強(qiáng)大作用,今天我們就一起來(lái)看看Spring MVC 4中常用的那些注解吧。
1. @Controller
Controller控制器是通過(guò)服務(wù)接口定義的提供訪(fǎng)問(wèn)應(yīng)用程序的一種行為,它解釋用戶(hù)的輸入,將其轉(zhuǎn)換成一個(gè)模型然后將試圖呈獻(xiàn)給用戶(hù)。Spring MVC 使用 @Controller 定義控制器,它還允許自動(dòng)檢測(cè)定義在類(lèi)路徑下的組件并自動(dòng)注冊(cè)。如想自動(dòng)檢測(cè)生效,需在XML頭文件下引入 spring-context:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<? xml version = "1.0" encoding = "UTF-8" ?>< beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:p = "http://www.springframework.org/schema/p" xmlns:context = "http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> < context:component-scan base-package = "org.springframework.samples.petclinic.web" /> <!-- ... --> </ beans > |
2. @RequestMapping
我們可以 @RequestMapping 注解將類(lèi)似 “/favsoft”這樣的URL映射到整個(gè)類(lèi)或特定的處理方法上。一般來(lái)說(shuō),類(lèi)級(jí)別的注解映射特定的請(qǐng)求路徑到表單控制器上,而方法級(jí)別的注解只是映射為一個(gè)特定的HTTP方法請(qǐng)求(“GET”,“POST”等)或HTTP請(qǐng)求參數(shù)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@Controller @RequestMapping ( "/favsoft" ) public class AnnotationController { @RequestMapping (method=RequestMethod.GET) public String get(){ return "" ; } @RequestMapping (value= "/getName" , method = RequestMethod.GET) public String getName(String userName) { return userName; } @RequestMapping (value= "/{day}" , method=RequestMethod.GET) public String getDay(Date day){ DateFormat df = new SimpleDateFormat( "yyyy-MM-dd" ); return df.format(day); } @RequestMapping (value= "/addUser" , method=RequestMethod.GET) public String addFavUser( @Validated FavUser favUser,BindingResult result){ if (result.hasErrors()){ return "favUser" ; } //favUserService.addFavUser(favUser); return "redirect:/favlist" ; } @RequestMapping ( "/test" ) @ResponseBody public String test(){ return "aa" ; } } |
@RequestMapping 既可以作用在類(lèi)級(jí)別,也可以作用在方法級(jí)別。當(dāng)它定義在類(lèi)級(jí)別時(shí),標(biāo)明該控制器處理所有的請(qǐng)求都被映射到 /favsoft 路徑下。@RequestMapping中可以使用 method 屬性標(biāo)記其所接受的方法類(lèi)型,如果不指定方法類(lèi)型的話(huà),可以使用 HTTP GET/POST 方法請(qǐng)求數(shù)據(jù),但是一旦指定方法類(lèi)型,就只能使用該類(lèi)型獲取數(shù)據(jù)。
@RequestMapping 可以使用 @Validated與BindingResult聯(lián)合驗(yàn)證輸入的參數(shù),在驗(yàn)證通過(guò)和失敗的情況下,分別返回不同的視圖。
@RequestMapping支持使用URI模板訪(fǎng)問(wèn)URL。URI模板像是URL模樣的字符串,由一個(gè)或多個(gè)變量名字組成,當(dāng)這些變量有值的時(shí)候,它就變成了URI。
3. @PathVariable
在Spring MVC中,可以使用 @PathVariable 注解方法參數(shù)并將其綁定到URI模板變量的值上。如下代碼所示:
1
2
3
4
5
|
String findOwner( String , Model model) { FavUser favUser = favUserService.findFavUser(); model.addAttribute( ; } |
URI模板 “favusers/{favUserId}"指定變量的名字 favUserId ,當(dāng)控制器處理這個(gè)請(qǐng)求的時(shí)候, favUserId的值會(huì)被設(shè)定到URI中。比如,當(dāng)有一個(gè)像“favusers/favccxx”這樣的請(qǐng)求時(shí),favUserId的值就是 favccxx。
@PathVariable 可以有多個(gè)注解,像下面這樣:
1
2
3
4
5
|
@RequestMapping (value= "/owners/{ownerId}/pets/{petId}" , method=RequestMethod.GET) public String findPet( @PathVariable String ownerId, @PathVariable String petId, Model model) { Owner owner = ownerService.findOwner(ownerId); Pet pet = owner.getPet(petId); model.addAttribute( "pet" , pet); return "displayPet" ; } |
@PathVariable中的參數(shù)可以是任意的簡(jiǎn)單類(lèi)型,如int, long, Date等等。Spring會(huì)自動(dòng)將其轉(zhuǎn)換成合適的類(lèi)型或者拋出 TypeMismatchException異常。當(dāng)然,我們也可以注冊(cè)支持額外的數(shù)據(jù)類(lèi)型。
如果@PathVariable使用Map<String, String>類(lèi)型的參數(shù)時(shí), Map會(huì)填充到所有的URI模板變量中。
@PathVariable支持使用正則表達(dá)式,這就決定了它的超強(qiáng)大屬性,它能在路徑模板中使用占位符,可以設(shè)定特定的前綴匹配,后綴匹配等自定義格式。
@PathVariable還支持矩陣變量,因?yàn)楝F(xiàn)實(shí)場(chǎng)景中用的不多,這就不詳細(xì)介紹了,有需要的童鞋請(qǐng)查看官網(wǎng)的文檔。
4. @RequestParam
@RequestParam將請(qǐng)求的參數(shù)綁定到方法中的參數(shù)上,如下面的代碼所示。其實(shí),即使不配置該參數(shù),注解也會(huì)默認(rèn)使用該參數(shù)。如果想自定義指定參數(shù)的話(huà),如果將@RequestParam的 required 屬性設(shè)置為false(如@RequestParam(value="id",required=false))。
5. @RequestBody
@RequestBody是指方法參數(shù)應(yīng)該被綁定到HTTP請(qǐng)求Body上。
1
2
3
|
@RequestMapping (value = "/something" , method = RequestMethod.PUT) public void handle( @RequestBody String body, Writer writer) throws IOException { writer.write(body); } |
如果覺(jué)得@RequestBody不如@RequestParam趁手,我們可以使用 HttpMessageConverter將request的body轉(zhuǎn)移到方法參數(shù)上, HttMessageConverser將 HTTP請(qǐng)求消息在Object對(duì)象之間互相轉(zhuǎn)換,但一般情況下不會(huì)這么做。事實(shí)證明,@RequestBody在構(gòu)建REST架構(gòu)時(shí),比@RequestParam有著更大的優(yōu)勢(shì)。
6. @ResponseBody
@ResponseBody與@RequestBody類(lèi)似,它的作用是將返回類(lèi)型直接輸入到HTTP response body中。@ResponseBody在輸出JSON格式的數(shù)據(jù)時(shí),會(huì)經(jīng)常用到,代碼見(jiàn)下圖:
1
2
|
@RequestMapping (value = "/something" , method = RequestMethod.PUT) @ResponseBodypublic String helloWorld() { return "Hello World" ; } |
7. @RestController
我們經(jīng)常見(jiàn)到一些控制器實(shí)現(xiàn)了REST的API,只為服務(wù)于JSON,XML或其它自定義的類(lèi)型內(nèi)容,@RestController用來(lái)創(chuàng)建REST類(lèi)型的控制器,與@Controller類(lèi)型。@RestController就是這樣一種類(lèi)型,它避免了你重復(fù)的寫(xiě)@RequestMapping與@ResponseBody。
1
2
3
4
5
6
7
8
|
@RestController public class FavRestfulController { @RequestMapping (value= "/getUserName" ,method=RequestMethod.POST) public String getUserName( @RequestParam (value= "name" ) String name){ return name; } } |
8. HttpEntity
HttpEntity除了能獲得request請(qǐng)求和response響應(yīng)之外,它還能訪(fǎng)問(wèn)請(qǐng)求和響應(yīng)頭,如下所示:
1
2
3
4
5
6
|
@RequestMapping ( "/something" ) public ResponseEntity<String> handle(HttpEntity< byte []> requestEntity) throws UnsupportedEncodingException { String requestHeader = requestEntity.getHeaders().getFirst( "MyRequestHeader" )); byte [] requestBody = requestEntity.getBody(); // do something with request header and body HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set( "MyResponseHeader" , "MyValue" ); return new ResponseEntity<String>( "Hello World" , responseHeaders, HttpStatus.CREATED); } |
9. @ModelAttribute
@ModelAttribute可以作用在方法或方法參數(shù)上,當(dāng)它作用在方法上時(shí),標(biāo)明該方法的目的是添加一個(gè)或多個(gè)模型屬性(model attributes)。該方法支持與@RequestMapping一樣的參數(shù)類(lèi)型,但并不能直接映射成請(qǐng)求。控制器中的@ModelAttribute方法會(huì)在@RequestMapping方法調(diào)用之前而調(diào)用,示例如下:
1
2
3
4
5
6
7
8
9
10
|
@ModelAttribute public Account addAccount( @RequestParam String number) { return accountManager.findAccount(number); } @ModelAttribute public void populateModel( @RequestParam String number, Model model) { model.addAttribute(accountManager.findAccount(number)); // add more ... } |
@ModelAttribute方法用來(lái)在model中填充屬性,如填充下拉列表、寵物類(lèi)型或檢索一個(gè)命令對(duì)象比如賬戶(hù)(用來(lái)在HTML表單上呈現(xiàn)數(shù)據(jù))。
@ModelAttribute方法有兩種風(fēng)格:一種是添加隱形屬性并返回它。另一種是該方法接受一個(gè)模型并添加任意數(shù)量的模型屬性。用戶(hù)可以根據(jù)自己的需要選擇對(duì)應(yīng)的風(fēng)格。
@ModelAttribute作用在方法參數(shù)上
當(dāng)@ModelAttribute作用在方法參數(shù)上時(shí),表明該參數(shù)可以在方法模型中檢索到。如果該參數(shù)不在當(dāng)前模型中,該參數(shù)先被實(shí)例化然后添加到模型中。一旦模型中有了該參數(shù),該參數(shù)的字段應(yīng)該填充所有請(qǐng)求參數(shù)匹配的名稱(chēng)中。這是Spring MVC中重要的數(shù)據(jù)綁定機(jī)制,它省去了單獨(dú)解析每個(gè)表單字段的時(shí)間。
@ModelAttribute是一種很常見(jiàn)的從數(shù)據(jù)庫(kù)中檢索屬性的方法,它通過(guò)@SessionAttributes使用request請(qǐng)求存儲(chǔ)。在一些情況下,可以很方便的通過(guò)URI模板變量和類(lèi)型轉(zhuǎn)換器檢索屬性。