Simply put, the annotation is used to map web requests to Spring Controller methods.
2. @RequestMapping Basics
Let’s start with a simple example – mapping an HTTP request to a method using some basic criteria.2.1. @RequestMapping – by Path
@RequestMapping(value = "/ex/foos", method = RequestMethod.GET)@ResponseBodypublic String getFoosBySimplePath() { return "Get some Foos";} To test out this mapping with a simple curl command, run: curl -i http://localhost:8080/spring-rest/ex/foos 2.2. @RequestMapping – the HTTP Method
The HTTP method parameter has no default – so if we don’t specify a value, it’s going to map to any HTTP request.Here’s a simple example, similar to the previous one – but this time mapped to an HTTP POST request:
@RequestMapping(value = "/ex/foos", method = POST)@ResponseBodypublic String postFoos() { return "Post some Foos";} To test the POST via a curl command:curl -i -X POST http://localhost:8080/spring-rest/ex/foos 3. RequestMapping and HTTP Headers
3.1. @RequestMapping with the headers Attribute
The mapping can be narrowed even further by specifying a header for the request:@RequestMapping(value = "/ex/foos", headers = "key=val", method = GET)@ResponseBodypublic String getFoosWithHeader() { return "Get some Foos with Header";}
And even multiple headers via the header attribute of @RequestMapping:
@RequestMapping( value = "/ex/foos", headers = { "key1=val1", "key2=val2" }, method = GET)@ResponseBodypublic String getFoosWithHeaders() { return "Get some Foos with Header";} To test the operation, we’re going to use the curl header support:
curl -i -H "key:val" http://localhost:8080/spring-rest/ex/foos Note that for the curl syntax for separating the header key and
the header value is a colon, same as in the HTTP spec, while in Spring
the equals sign is used. 3.2. @RequestMapping Consumes and Produces
Mapping media types produced by a controller method is worth special attention – we can map a request based on its Accept header via the @RequestMapping headers attribute introduced above:@RequestMapping( value = "/ex/foos", method = GET, headers = "Accept=application/json")@ResponseBodypublic String getFoosAsJsonFromBrowser() { return "Get some Foos with Header Old";} he matching for this way of defining the Accept header is flexible – it uses contains instead of equals, so a request such as the following would still map correctly:curl -H "Accept:application/json,text/html" http://localhost:8080/spring-rest/ex/foos Starting with Spring 3.1, the @RequestMapping annotation now has the produces and the consumes attributes, specifically for this purpose:@RequestMapping( value = "/ex/foos", method = RequestMethod.GET, produces = "application/json")@ResponseBodypublic String getFoosAsJsonFromREST() { return "Get some Foos with Header New";} Also, the old type of mapping with the headers attribute will automatically be converted to the new produces mechanism starting with Spring 3.1, so the results will be identical.This is consumed via curl in the same way:
curl -H "Accept:application/json" http://localhost:8080/spring-rest/ex/foos Additionally, produces support multiple values as well:@RequestMapping( value = "/ex/foos", method = GET, produces = { "application/json", "application/xml" }) Keep in mind that these – the old way and the new way of specifying the accept
header – are basically the same mapping, so Spring won’t allow them
together – having both these methods active would result in:Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'fooController' bean method java.lang.String org.baeldung.spring.web.controller .FooController.getFoosAsJsonFromREST()to { [/ex/foos], methods=[GET],params=[],headers=[], consumes=[],produces=[application/json],custom=[]}: There is already 'fooController' bean methodjava.lang.String org.baeldung.spring.web.controller .FooController.getFoosAsJsonFromBrowser() mapped. A final note on the new produces and consumes mechanism – these behave differently from most other annotations: when specified at the type level, the method level annotations do not complement but override the type level information.4. RequestMapping with Path Variables
Parts of the mapping URI can be bound to variables via the @PathVariable annotation.4.1. Single @PathVariable
A simple example with a single path variable:@RequestMapping(value = "/ex/foos/{id}", method = GET)@ResponseBodypublic String getFoosBySimplePathWithPathVariable( @PathVariable("id") long id) { return "Get a specific Foo with id=" + id;}
Note that @PathVariable benefits from automatic type conversion, so we could have also declared the id as: @PathVariable long id 4.2. Multiple @PathVariable
More complex URI may need to map multiple parts of the URI to multiple values:@RequestMapping(value = "/ex/foos/{fooid}/bar/{barid}", method = GET)@ResponseBodypublic String getFoosBySimplePathWithPathVariables (@PathVariable long fooid, @PathVariable long barid) { return "Get a specific Bar with id=" + barid + " from a Foo with id=" + fooid;} This is easily tested with a curl in the same way: curl http://localhost:8080/spring-rest/ex/foos/1/bar/2 4.3. @PathVariable with RegEx
Regular expressions can also be used when mapping the @PathVariable; for example, we will restrict the mapping to only accept numerical values for the id:@RequestMapping(value = "/ex/bars/{numericId:[\\d]+}", method = GET)@ResponseBodypublic String getBarsBySimplePathWithPathVariable( @PathVariable long numericId) { return "Get a specific Bar with id=" + numericId;} This will mean that the following URIs will match: http://localhost:8080/spring-rest/ex/bars/1 But this will not:http://localhost:8080/spring-rest/ex/bars/abc RequestMapping with Request Parameters
@RequestMapping allows easy mapping of URL parameters with the @RequestParam annotation.We are now mapping a request to a URI such as:
http://localhost:8080/spring-rest/ex/bars?id=100 @RequestMapping(value = "/ex/bars", method = GET)@ResponseBodypublic String getBarBySimplePathWithRequestParam( @RequestParam("id") long id) { return "Get a specific Bar with id=" + id;} We are then extracting the value of the id parameter using the @RequestParam(“id”) annotation in the controller method signature.The send a request with the id parameter, we’ll use the parameter support in curl:
curl -i -d id=100 http://localhost:8080/spring-rest/ex/bars
In this example, the parameter was bound directly without having been declared first.
For more advanced scenarios, @RequestMapping can optionally define the parameters – as yet another way of narrowing the request mapping:
For more advanced scenarios, @RequestMapping can optionally define the parameters – as yet another way of narrowing the request mapping:
@RequestMapping(value = "/ex/bars", params = "id", method = GET)@ResponseBodypublic String getBarBySimplePathWithExplicitRequestParam( @RequestParam("id") long id) { return "Get a specific Bar with id=" + id;} Even more flexible mappings are allowed – multiple params values can be set, and not all of them have to be used: @RequestMapping( value = "/ex/bars", params = { "id", "second" }, method = GET)@ResponseBodypublic String getBarBySimplePathWithExplicitRequestParams( @RequestParam("id") long id) { return "Narrow Get a specific Bar with id=" + id;} And of course, a request to a URI such as: http://localhost:8080/spring-rest/ex/bars?id=100&second=something Will always be mapped to the best match – which is the narrower match, which defines both the id and the second parameter.6. RequestMapping Corner Cases
6.1. @RequestMapping – multiple paths mapped to the same controller method
Although a single @RequestMapping path value is usually used for a single controller method, this is just good practice, not a hard and fast rule – there are some cases where mapping multiple requests to the same method may be necessary. For that case, the value attribute of @RequestMapping does accept multiple mappings, not just a single one: @RequestMapping( value = { "/ex/advanced/bars", "/ex/advanced/foos" }, method = GET)@ResponseBodypublic String getFoosOrBarsByPath() { return "Advanced - Get some Foos or Bars";} Now, both of these curl commands should hit the same method:curl -i http://localhost:8080/spring-rest/ex/advanced/fooscurl -i http://localhost:8080/spring-rest/ex/advanced/bars 6.2. @RequestMapping – multiple HTTP request methods to the same controller method
Multiple requests using different HTTP verbs can be mapped to the same controller method:@RequestMapping( value = "/ex/foos/multiple", method = { RequestMethod.PUT, RequestMethod.POST })@ResponseBodypublic String putAndPostFoos() { return "Advanced - PUT and POST within single method";} With curl, both of these will now hit the same method: curl -i -X POST http://localhost:8080/spring-rest/ex/foos/multiple curl -i -X PUT http://localhost:8080/spring-rest/ex/foos/multiple 6.3. @RequestMapping – a fallback for all requests
To implement a simple fallback for all requests using a particular HTTP method – for example, for a GET: @RequestMapping(value = "*", method = RequestMethod.GET)@ResponseBodypublic String getFallback() { return "Fallback for GET Requests";} Or even for all requests:@RequestMapping( value = "*", method = { RequestMethod.GET, RequestMethod.POST ... })@ResponseBodypublic String allFallback() { return "Fallback for All Requests";} 7. New Request Mapping Shortcuts
Spring Framework 4.3 introduced a few new HTTP mapping annotations, all based on @RequestMapping:- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
@GetMapping("/{id}")public ResponseEntity getBazz(@PathVariable String id){ return new ResponseEntity<>(new Bazz(id, "Bazz"+id), HttpStatus.OK);}@PostMappingpublic ResponseEntity newBazz(@RequestParam("name") String name){ return new ResponseEntity<>(new Bazz("5", name), HttpStatus.OK);}@PutMapping("/{id}")public ResponseEntity updateBazz( @PathVariable String id, @RequestParam("name") String name) { return new ResponseEntity<>(new Bazz(id, name), HttpStatus.OK);}@DeleteMapping("/{id}")public ResponseEntity deleteBazz(@PathVariable String id){ return new ResponseEntity<>(new Bazz(id), HttpStatus.OK);} 8. Spring Configuration
The Spring MVC Configuration is simple enough – considering that our FooController is defined in the following package:package org.baeldung.spring.web.controller;@Controllerpublic class FooController { ... } We simply need a @Configuration class to enable the full MVC support and configure classpath scanning for the controller: @Configuration@EnableWebMvc@ComponentScan({ "org.baeldung.spring.web.controller" })public class MvcConfig { //}
Niciun comentariu:
Trimiteți un comentariu