Spring RequestMapping

1.Overview

Inthisarticle,wewilldiscussoneofthemainannotationsinSpringMVC–the@RequestMapping–thisisusedtomapwebrequeststoSpringControllermethods.

Throughoutthearticle,wewilltesteachofthemappingsshowedviasimplecurlcommands.

2.RequestMappingBasicExample

Let’sstartwithasimpleexample–mappinganHTTPrequesttoamethodusingsomestraightforwardcriteria.

2.1.@RequestMapping–byPath

?

1

2

3

4

5

@RequestMapping(value="/foos")

@ResponseBody

publicStringgetFoosBySimplePath(){

return"GetsomeFoos";

}

Totestoutthismappingwithasimplecurlcommand,run:

?

1

curl-ihttp://localhost:8080/spring-rest/foos

2.2.@RequestMapping–theHTTPMethod

Bydefault,theHTTPmethodmappedbya@RequestMappingisGET–thiscanofcoursebechanged–forexampletomaptoaPOSTrequest:

?

1

2

3

4

5

@RequestMapping(value="/foos",method=RequestMethod.POST)

@ResponseBody

publicStringpostFoos(){

return"PostsomeFoos";

}

TotestthePOSTviaacurlcomamnd:

?

1

curli-XPOSThttp://localhost:8080/spring-rest/foos

3.RequestMappingandHTTPHeaders

3.1.@RequestMappingwiththeheadersattribute

Themappingcanbenarrowedevenfurtherbyspecifyingaheaderfortherequest:

?

1

2

3

4

5

@RequestMapping(value="/foos",headers="key=val")

@ResponseBody

publicStringgetFoosWithHeader(){

return"GetsomeFooswithHeader";

}

Andevenmultipleheadersviatheheaderattributeof@RequestMapping:

?

1

2

3

4

5

@RequestMapping(value="/foos",headers={"key1=val1","key2=val2"})

@ResponseBody

publicStringgetFoosWithHeaders(){

return"GetsomeFooswithHeader";

}

Totesttheoperation,we’regoingtousethecurlheadersupport:

?

1

curl-i-H"key:val"http://localhost:8080/spring-rest/foos

Notethatforthecurlsyntaxforseparatingtheheaderkeyandtheheadervalueisacolon,sameasintheHTTPspec,whileinSpringtheequalssignisused.

3.2.@RequestMappingConsumesandProduces

Mappingmediatypesproducedbyacontrollermethodisworthspecialattention–wecanmaparequestbasedonitsAcceptheaderviathe@RequestMappingheadersattributeintroducedabove:

?

1

2

3

4

5

@RequestMapping(value="/foos",method=RequestMethod.GET,headers="Accept=application/json")

@ResponseBody

publicStringgetFoosAsJsonFromBrowser(){

return"GetsomeFooswithHeaderOld";

}

ThematchingforthiswayofdefiningtheAcceptheaderisflexible–itusescontainsinsteadofequals,soarequestsuchasthefollowingwouldstillmapcorrectly:

?

1

curl-H"Accept:application/json,text/html"http://localhost:8080/spring-rest/foos

StartingwithSpring3.1,athe@RequestMappingannotationnowhasaproducesandaconsumesattributes,specificallyforthispurpose:

?

1

2

3

4

5

@RequestMapping(value="/foos",method=RequestMethod.GET,produces="application/json")

@ResponseBody

publicStringgetFoosAsJsonFromREST(){

return"GetsomeFooswithHeaderNew";

}

Also,theoldtypeofmappingwiththeheadersattributewillautomaticallybeconvertedtothenewproducesmechanismstartingwithSpring3.1,sotheresultswillbeidentical.

Thisisconsumedviacurlinthesameway:

?

1

curl-H"Accept:application/json"http://localhost:8080/spring-rest/foos

Additionally,producessupportmultiplevaluesaswell:

?

1

@RequestMapping(value="/foos",produces={"application/json","application/xml"})

Keepinmindthatthesearebasicallythesamemapping,soSpringwon’tacceptthemtogether–havingboththesemethodsactivewouldresultin:

?

1

2

3

4

5

6

7

Causedby:java.lang.IllegalStateException:Ambiguousmappingfound.

Cannotmap'fooController'beanmethod

publicjava.lang.Stringorg.baeldung.spring.web.controller.FooController.getFoosAsJsonFromREST()

to{[/foos],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}:

Thereisalready'fooController'beanmethod

publicjava.lang.Stringorg.baeldung.spring.web.controller.FooController.getFoosAsJsonFromBrowser()

mapped.

Afinalnoteonthenewproducesandconsumesmechanism–thesebehavedifferentlyfrommostotherannotations:whenspecifiedattypelevel,themethodlevelannotationsdonotcomplementbutoverridethetypelevelinformation.

4.RequestMappingwithPathVariables

PartsofthemappingURIcanbeboundtovariablesviathe@PathVariableannotation.

4.1.Single@PathVariable

Asimpleexamplewithasinglepathvariable:

?

1

2

3

4

5

@RequestMapping(value="/foos/{id}")

@ResponseBody

publicStringgetFoosBySimplePathWithPathVariable(@PathVariable("id")longid){

return"GetaspecificFoowithid="+id;

}

Thiscanbetestedwithcurl:

?

1

curlhttp://localhost:8080/spring-rest/foos/1

Ifthenameofthemethodargumentmatchesthenameofthepathvariableexactly,thenthiscanbesimplifiedbyusing@PathVariablewithnovalue:

?

1

2

3

4

5

@RequestMapping(value="/foos/{id}")

@ResponseBody

publicStringgetFoosBySimplePathWithPathVariable(@PathVariableStringid){

return"GetaspecificFoowithid="+id;

}

Notethat@PathVariablebenefitsfromautomatictypeconversion,sowecouldhavealsodeclaredtheidas:

?

1

@PathVariablelongid

4.2.Multiple@PathVariable

MorecomplexURImayneedtomapmultiplepartsoftheURItomultiplevalues:

?

1

2

3

4

5

@RequestMapping(value="/foos/{fooid}/bar/{barid}")

@ResponseBody

publicStringgetFoosBySimplePathWithPathVariables(@PathVariablelongfooid,@PathVariablelongbarid){

return"GetaspecificBarwithid="+barid+"fromaFoowithid="+fooid;

}

Thisiseasilytestedwithcurlinthesameway:

?

1

curlhttp://localhost:8080/spring-rest/foos/1/bar/2

4.3.@PathVariablewithRegEx

Regularexpressionscanalsobeusedwhenmappingthe@PathVariable;forexample,wewillrestrictthemappingtoonlyacceptnumericalvaluesfortheid:

?

1

2

3

4

5

@RequestMapping(value="/bars/{numericId:[\\d]+}")

@ResponseBody

publicStringgetBarsBySimplePathWithPathVariable(@PathVariablefinallongnumericId){

return"GetaspecificBarwithid="+numericId;

}

ThiswillmeanthatthefollowingURIswillmatch:

?

1

http://localhost:8080/spring-rest/bars/1

Butthiswillnot:

?

1

http://localhost:8080/spring-rest/bars/abc

5.RequestMappingwithRequestParameters

@RequestMappingallowseasymappingofURLparameterswiththe@RequestParamannotation.

WearenowmappingarequesttoanURIsuchas:

?

1

http://localhost:8080/spring-rest/bars?id=100

?

1

2

3

4

5

@RequestMapping(value="/bars")

@ResponseBody

publicStringgetBarBySimplePathWithRequestParam(@RequestParam("id")longid){

return"GetaspecificBarwithid="+id;

}

Wearethenextractingthevalueoftheidparameterusingthe@RequestParam(“id”)annotationinthecontrollermethodsignature.

Thesendarequestwiththeidparameter,we’llusetheparametersupportincurl:

?

1

curl-i-XPOSTid=100http://localhost:8080/spring-rest/bars

Inthisexample,theparameterwasbounddirectlywithouthavingbeendeclaredfirst.

Formoreadvancedscenarios,@RequestMappingcanexplicitlydefinetheparameterstobemappedasyetanotherwayofnarrowingtherequestmapping:

?

1

2

3

4

5

@RequestMapping(value="/bars",params="id")

@ResponseBody

publicStringgetBarBySimplePathWithExplicitRequestParam(@RequestParam("id")longid){

return"GetaspecificBarwithid="+id;

}

Evenmoreflexiblemappingsareallowed–multipleparamsvaluescanbedefined,andnotallofthemhavetobeused:

?

1

2

3

4

5

@RequestMapping(value="/bars",params={"id","second"})

@ResponseBody

publicStringgetBarBySimplePathWithExplicitRequestParams(@RequestParam("id")longid){

return"NarrowGetaspecificBarwithid="+id;

}

Andofcourse,arequesttoanURIsuchas:

?

1

http://localhost:8080/spring-rest/bars?id=100&second=something

Willalwaysbemappedtothebestmatch–whichisthenarrowermatch,whichdefinesboththeidandthesecondparameter.

6.RequestMappingCornerCases

6.1.@RequestMapping–multiplepathsmappedtothesamecontrollermethod

Althoughasingle@RequestMappingpathvalueisusuallyusedforasinglecontrollermethod,thisisjustgoodpractice,notahardandfastrule–therearesomecaseswheremappingmultiplerequeststothesamemethodmaybenecessary.Forthatcase,thevalueattributeof@RequestMappingdoesacceptmultiplemappings,notjustasingleone:

?

1

2

3

4

5

@RequestMapping(value={"/advanced/bars","/advanced/foos"})

@ResponseBody

publicStringgetFoosOrBarsByPath(){

return"Advanced-GetsomeFoosorBars";

}

Now,bothofthesecurlcommandsshouldhitthesamemethod:

?

1

2

curl-ihttp://localhost:8080/spring-rest/advanced/foos

curl-ihttp://localhost:8080/spring-rest/advanced/bars

6.2.@RequestMapping–multipleHTTPrequestmethodstothesamecontrollermethod

MultiplerequestsusingdifferentHTTPverbscanbemappedtothesamecontrollermethod:

?

1

2

3

4

5

@RequestMapping(value="/foos/multiple",method={RequestMethod.PUT,RequestMethod.POST})

@ResponseBody

publicStringputAndPostFoos(){

return"Advanced-PUTandPOSTwithinsinglemethod";

}

Withcurl,bothofthesewillnowhitthesamemethod:

?

1

2

curl-i-XPOSThttp://localhost:8080/spring-rest/foos/multiple

curl-i-XPUThttp://localhost:8080/spring-rest/foos/multiple

6.3.@RequestMapping–afallbackforallrequests

ToimplementasimplefallbackforallrequestsusingaspecificHTTPmethod:

?

1

2

3

4

5

@RequestMapping(value="*")

@ResponseBody

publicStringgetFallback(){

return"FallbackforGETRequests";

}

Orevenforallrequest:

?

1

2

3

4

5

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

@ResponseBody

publicStringallFallback(){

return"FallbackforAllRequests";

}

7.SpringConfiguration

TheSpringMVCConfigurationissimpleenough–consideringthatourFooControllerisdefinedinthefollowingpackage:

?

1

2

3

4

packageorg.baeldung.spring.web.controller;

@Controller

publicclassFooController{...}

StartingwithSpring3.1,wewillonlyneeda@ConfigurationclasstoenablethefullMVCsupportandconfigureclasspathscanningforthecontroller:

?

1

2

3

4

5

6

@Configuration

@EnableWebMvc

@ComponentScan({"org.baeldung.spring.web.controller"})

publicclassMvcConfig{

//

}

8.Conclusion

Thisarticlefocusonthe@RequestMappingannotationinSpring3-discussingasimpleusecase,themappingofHTTPheaders,bindingpartsoftheURIwith@PathVariableandworkingwithURIparametersandthe@RequestParamannotation.

Theimplementationofthissimpleprojectcanbefoundinthegithubproject–thisisanEclipsebasedproject,soitshouldbeeasytoimportandrunasitis.

相关推荐