in DevOps

Spring MVC @RequestMapping annotation

Let’s start with a simple example – mapping an HTTP request to a method using some basic criteria.

@RequestMapping – by Path

@RequestMapping(value = "/ex/foos", method = RequestMethod.GET)
@ResponseBody
public 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

@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 an 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 = RequestMethod.POST)
@ResponseBody
public String postFoos() {

    return "Post some Foos";

}

Again to test the POST via a curl command:

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

RequestMapping and HTTP Headers

 @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 = RequestMethod.GET)
@ResponseBody
public 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 = RequestMethod.GET)
@ResponseBody

public String getFoosWithHeaders() {

    return "Get some Foos with Header";

}

@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 = RequestMethod.POST,
  consumes="application/json",
  produces = "application/json" )
@ResponseBody
public String getFoosAsJsonFromBrowser() {

    return "Get some Foos with Header Old";

}

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 =RequestMethod.GET,
  produces = { "application/json", "application/xml" }
)

RequestMapping with Path Variables

Parts of the mapping URI can be bound to variables via the @PathVariable annotation.

Single @PathVariable

A simple example with a single path variable:

@RequestMapping(value = "/ex/foos/{id}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariable(
  @PathVariable("id") long id) {

    return "Get a specific Foo with id=" + id;

}

If the name of the method parameter matches the name of the path variable exactly, then this can be simplified by using @PathVariable with no value:

@RequestMapping(value = "/ex/foos/{id}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariable(
  @PathVariable String id) {
    return "Get a specific Foo with id=" + id;

}
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)
@ResponseBody
public String getFoosBySimplePathWithPathVariables
  (@PathVariable long fooid, @PathVariable long barid) {
    return "Get a specific Bar with id=" + barid +
      " from a Foo with id=" + fooid;
}
@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)
@ResponseBody
public String getBarsBySimplePathWithPathVariable(
  @PathVariable long numericId) {
    return "Get a specific Bar with id=" + numericId;
}

RequestMapping Corner Cases

 @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)
@ResponseBody
public String getFoosOrBarsByPath() {
    return "Advanced - Get some Foos or Bars";
}

@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 }
)
@ResponseBody
public String putAndPostFoos() {
    return "Advanced - PUT and POST within single method";
}

@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)
@ResponseBody
public String getFallback() {
    return "Fallback for GET Requests";
}
[UPDATE] New Request Mapping Shortcuts

Spring Framework 4.3 introduced a few new HTTP mapping annotations, all based on @RequestMapping:

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

These new annotations can improve the readability and reduce the verbosity of the code