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.