Spring RequestMapping

1. Overzicht

In deze tutorial zullen we ons concentreren op een van de belangrijkste annotaties in Lente MVC: @RequestMapping.

Simpel gezegd, de annotatie wordt gebruikt om webverzoeken toe te wijzen aan Spring Controller-methoden.

2. @RequestMapping Basics

Laten we beginnen met een eenvoudig voorbeeld: een HTTP-verzoek toewijzen aan een methode met behulp van enkele basiscriteria.

2.1. @RequestMapping - door Path

@RequestMapping (value = "/ ex / foos", method = RequestMethod.GET) @ResponseBody public String getFoosBySimplePath () {return "Get some Foos"; }

Om deze mapping te testen met een simple krullen commando, voer uit:

curl -i // localhost: 8080 / spring-rest / ex / foos

2.2. @RequestMapping - de HTTP-methode

Het HTTP methode parameter heeft geen standaard. Dus als we geen waarde specificeren, wordt deze toegewezen aan elk HTTP-verzoek.

Hier is een eenvoudig voorbeeld, vergelijkbaar met het vorige, maar deze keer toegewezen aan een HTTP POST-verzoek:

@RequestMapping (value = "/ ex / foos", method = POST) @ResponseBody public String postFoos () {return "Post some Foos"; }

Om de POST te testen via een krullen opdracht:

curl -i -X ​​POST // localhost: 8080 / spring-rest / ex / foos

3. RequestMapping en HTTP-headers

3.1. @RequestMapping Met de headers Attribuut

De mapping kan nog verder worden beperkt door een header voor het verzoek op te geven:

@RequestMapping (value = "/ ex / foos", headers = "key = val", method = GET) @ResponseBody public String getFoosWithHeader () {return "Get some Foos with Header"; }

Om de werking te testen, gaan we de krullen header ondersteuning:

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

en zelfs meerdere headers via de headers kenmerk van @RequestMapping:

@RequestMapping (value = "/ ex / foos", headers = {"key1 = val1", "key2 = val2"}, method = GET) @ResponseBody public String getFoosWithHeaders () {return "Get some Foos with Header"; }

We kunnen dit testen met het commando:

curl -i -H "key1: val1" -H "key2: val2" // localhost: 8080 / spring-rest / ex / foos

Merk op dat voor de krullen syntaxis, een dubbele punt scheidt de koptekstsleutel en de koptekstwaarde, hetzelfde als in de HTTP-specificatie, terwijl in het voorjaar het gelijkteken wordt gebruikt.

3.2. @RequestMapping Consumeert en produceert

In kaart brengen mediatypen geproduceerd door een controller methode verdient speciale aandacht.

We kunnen een verzoek in kaart brengen op basis van zijn Aanvaarden koptekst via de @RequestMappingheaders attribuut hierboven geïntroduceerd:

@RequestMapping (value = "/ ex / foos", method = GET, headers = "Accept = application / json") @ResponseBody public String getFoosAsJsonFromBrowser () {return "Get some Foos with Header Old"; }

De matching voor deze manier om de Aanvaarden header is flexibel - het gebruikt bevat in plaats van is gelijk aan, dus een verzoek zoals het volgende zou nog steeds correct worden toegewezen:

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

Beginnend met Spring 3.1, de @RequestMapping annotatie heeft nu de produceert en verbruikt attributen, specifiek voor dit doel:

@RequestMapping (value = "/ ex / foos", method = RequestMethod.GET, produceert = "application / json") @ResponseBody public String getFoosAsJsonFromREST () {return "Get some Foos with Header New"; }

Ook is het oude type mapping met de headers attribuut wordt automatisch geconverteerd naar het nieuwe produceert mechanisme te beginnen met Spring 3.1, dus de resultaten zullen identiek zijn.

Dit wordt verbruikt via krullen op dezelfde manier:

curl -H "Accepteer: application / json" // localhost: 8080 / spring-rest / ex / foos

Bovendien, produceert ondersteunt ook meerdere waarden:

@RequestMapping (value = "/ ex / foos", method = GET, produceert = {"application / json", "application / xml"})

Houd er rekening mee dat deze - de oude en nieuwe manieren om het Aanvaarden header - zijn in principe dezelfde mapping, dus Spring staat ze niet samen.

Als beide methoden actief zijn, zou dit resulteren in:

Veroorzaakt door: java.lang.IllegalStateException: dubbelzinnige mapping gevonden. Kan de 'fooController'-bean-methode java.lang.String org.baeldung.spring.web.controller .FooController.getFoosAsJsonFromREST () niet toewijzen aan {[/ ex / foos], methodes = [GET], params = [], headers = [ ], verbruikt = [], produceert = [applicatie / json], aangepast = []}: Er is al 'fooController' bean-methode java.lang.String org.baeldung.spring.web.controller .FooController.getFoosAsJsonFromBrowser () toegewezen .

Een laatste opmerking over het nieuwe produceert en verbruikt mechanismen die zich anders gedragen dan de meeste andere annotaties: indien gespecificeerd op het typeniveau, de annotaties op methode-niveau zijn niet complementair maar overschrijven ze de informatie op typeniveau.

En als je dieper wilt graven in het bouwen van een REST API met Spring, kijk dan natuurlijk eens de nieuwe REST met Spring cursus.

4. RequestMapping Met padvariabelen

Delen van de mapping-URI kunnen via de @PathVariable annotatie.

4.1. Single @PathVariable

Een eenvoudig voorbeeld met een enkele padvariabele:

@RequestMapping (value = "/ ex / foos / {id}", method = GET) @ResponseBody public String getFoosBySimplePathWithPathVariable (@PathVariable ("id") lange id) {return "Haal een specifieke Foo op met / ex / foos / { id} ", method = GET) @ResponseBody public String getFoosBySimplePathWithPathVariable (@PathVariable String id) {return" Get a specific Foo with2-multiple-pathvariable ">4.2. Meerdere @PathVariable

Een complexere URI moet mogelijk meerdere delen van de URI toewijzen aan meerdere waarden:

@RequestMapping (value = "/ ex / foos / {fooid} / bar / {barid}", method = GET) @ResponseBody public String getFoosBySimplePathWithPathVariables (@PathVariable long fooid, @PathVariable long barid) {return "Krijg een specifieke balk met van een Foo with3-pathvariable-with-regex ">4.3. @PathVariable Met Regex

Reguliere expressies kunnen ook worden gebruikt bij het toewijzen van het @PathVariable.

We beperken bijvoorbeeld de toewijzing om alleen numerieke waarden te accepteren voor de ID kaart:

@RequestMapping (value = "/ ex / bars / {numericId: [\ d] +}", method = GET) @ResponseBody public String getBarsBySimplePathWithPathVariable (@PathVariable long numericId) {return "Get a specific Bar withrequest-param">5. RequestMapping Met verzoekparameters

@RequestMapping maakt het eenvoudig toewijzing van URL-parameters met de @RequestParam annotatie.

We koppelen nu een verzoek aan een URI:

// localhost: 8080 / spring-rest / ex / bars? id = 100
@RequestMapping (value = "/ ex / bars", method = GET) @ResponseBody public String getBarBySimplePathWithRequestParam (@RequestParam ("id") lange id) {return "Haal een specifieke balk op met / ex / bars", params = "id ", method = GET) @ResponseBody public String getBarBySimplePathWithExplicitRequestParam (@RequestParam (" id ") lange id) {return" Haal een specifieke balk op met / ex / bars ", params = {" id "," second "}, method = GET) @ResponseBody public String getBarBySimplePathWithExplicitRequestParams (@RequestParam ("id") lange id) {return "Narrow Get a specific Bar withcorner-cases">6. RequestMapping Hoek gevallen

6.1. @RequestMapping - Meerdere paden toegewezen aan dezelfde controllermethode

Hoewel een enkele @RequestMapping padwaarde wordt meestal gebruikt voor een enkele controllermethode (gewoon een goede gewoonte, geen vaste regel), er zijn enkele gevallen waarin het toewijzen van meerdere verzoeken aan dezelfde methode nodig kan zijn.

In dat geval, de waarde kenmerk van @RequestMapping accepteert meerdere toewijzingen, niet slechts één:

@RequestMapping (value = {"/ ex / advanced / bars", "/ ex / advanced / foos"}, method = GET) @ResponseBody public String getFoosOrBarsByPath () {return "Advanced - Get some Foos or Bars"; }

Nu beide krullen commando's zouden dezelfde methode moeten raken:

curl -i // localhost: 8080 / spring-rest / ex / advanced / foos curl -i // localhost: 8080 / spring-rest / ex / advanced / bars

6.2. @RequestMapping - Meerdere HTTP-verzoekmethoden voor dezelfde controllermethode

Meerdere verzoeken met verschillende HTTP-werkwoorden kunnen worden toegewezen aan dezelfde controllermethode:

@RequestMapping (value = "/ ex / foos / multiple", method = {RequestMethod.PUT, RequestMethod.POST}) @ResponseBody public String putAndPostFoos () {return "Advanced - PUT en POST binnen enkele methode"; }

Met krullen, beide zullen nu dezelfde methode raken:

curl -i -X ​​POST // localhost: 8080 / spring-rest / ex / foos / multiple curl -i -X ​​PUT // localhost: 8080 / spring-rest / ex / foos / multiple

6.3. @RequestMapping - een terugval voor alle verzoeken

Om een ​​eenvoudige fallback te implementeren voor alle verzoeken die een bepaalde HTTP-methode gebruiken, bijvoorbeeld voor een GET:

@RequestMapping (value = "*", method = RequestMethod.GET) @ResponseBody public String getFallback () {return "Fallback for GET Requests"; }

of zelfs voor alle verzoeken:

@RequestMapping (value = "*", method = {RequestMethod.GET, RequestMethod.POST ...}) @ResponseBody public String allFallback () {return "Fallback for All Requests"; }

6.4. Dubbelzinnige toewijzingsfout

De dubbelzinnige toewijzingsfout treedt op wanneer Spring evalueert dat twee of meer aanvraagtoewijzingen hetzelfde zijn voor verschillende controllermethoden. Een aanvraagtoewijzing is hetzelfde als deze dezelfde HTTP-methode, URL, parameters, kopteksten en mediatype heeft.

Dit is bijvoorbeeld een dubbelzinnige afbeelding:

@GetMapping (value = "foos / duplicate") public String duplicate () {return "Duplicate"; } @GetMapping (value = "foos / duplicate") public String duplicateEx () {return "Duplicate"; }

De uitzondering die wordt gegenereerd, bevat meestal foutmeldingen in de volgende zin:

Veroorzaakt door: java.lang.IllegalStateException: dubbelzinnige mapping. Kan 'fooMappingExamplesController'-methode openbare java.lang.String org.baeldung.web.controller.FooMappingExamplesController.duplicateEx () niet toewijzen aan {[/ ex / foos / duplicate], methodes = [GET]}: er is al een' fooMappingExamplesController'-bean methode openbaar java.lang.String org.baeldung.web.controller.FooMappingExamplesController.duplicate () toegewezen.

Een zorgvuldige lezing van de foutmelding wijst erop dat Spring de methode niet in kaart kan brengen org.baeldung.web.controller.FooMappingExamplesController.duplicateEx (), omdat het een conflicterende afbeelding heeft met een reeds toegewezen org.baeldung.web.controller.FooMappingExamplesController.duplicate ().

Het onderstaande codefragment zal niet resulteren in een dubbelzinnige toewijzingsfout omdat beide methoden verschillende inhoudstypen retourneren:

@GetMapping (waarde = "foos / duplicate", produceert = MediaType.APPLICATION_XML_VALUE) public String duplicateXml () {return "Duplicate"; } @GetMapping (waarde = "foos / duplicate", produceert = MediaType.APPLICATION_JSON_VALUE) public String duplicateJson () {return "{\" message \ ": \" Duplicate \ "}"; }

Door deze differentiatie kan onze controller de juiste gegevensweergave retourneren op basis van de Accepteert header geleverd in het verzoek.

Een andere manier om dit op te lossen, is door de URL bij te werken die aan een van de twee betrokken methoden is toegewezen.

7. Nieuwe snelkoppelingen voor het toewijzen van aanvragen

Spring Framework 4.3 introduceerde een paar nieuwe HTTP-toewijzingsannotaties, allemaal gebaseerd op @RequestMapping :

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

Deze nieuwe annotaties kunnen de leesbaarheid verbeteren en de breedsprakigheid van de code verminderen.

Laten we deze nieuwe annotaties in actie bekijken door een RESTful API te maken die CRUD-bewerkingen ondersteunt:

@GetMapping ("/ {id}") openbare ResponseEntity getBazz (@PathVariable String id) {retourneer nieuwe ResponseEntity (nieuwe Bazz (id, "Bazz" + id), HttpStatus.OK); } @PostMapping openbare ResponseEntity newBazz (@RequestParam ("naam") String naam) {retourneer nieuwe ResponseEntity (nieuwe Bazz ("5", naam), HttpStatus.OK); } @PutMapping ("/ {id}") openbare ResponseEntity updateBazz (@PathVariable String id, @RequestParam ("name") Stringnaam) {return new ResponseEntity (nieuwe Bazz (id, naam), HttpStatus.OK); } @DeleteMapping ("/ {id}") openbare ResponseEntity deleteBazz (@PathVariable String id) {retourneer nieuwe ResponseEntity (nieuwe Bazz (id), HttpStatus.OK); }

Een diepe duik hierin vind je hier.

8. Veerconfiguratie

De Spring MVC-configuratie is eenvoudig genoeg, aangezien onze FooController wordt gedefinieerd in het volgende pakket:

pakket org.baeldung.spring.web.controller; @Controller openbare klasse FooController {...}

We hebben gewoon een @Configuratie class om de volledige MVC-ondersteuning in te schakelen en classpath scanning voor de controller te configureren:

@Configuration @EnableWebMvc @ComponentScan ({"org.baeldung.spring.web.controller"}) openbare klasse MvcConfig {//}

9. Conclusie

Dit artikel concentreerde zich op het @RequestMapping annotatie in het voorjaar, waarin een eenvoudige use case wordt besproken, het in kaart brengen van HTTP-headers, het binden van delen van de URI met @PathVariable, en werken met URI-parameters en de @RequestParam annotatie.

Als u wilt leren hoe u een andere kernannotatie in Spring MVC gebruikt, kunt u het @ModelAttribute annotatie hier.

De volledige code van het artikel is beschikbaar op GitHub.