Spring RequestMapping

1. Overview

In this article, we will discuss one of the main annotations in Spring MVC – the @RequestMapping – this is used to map web requests to Spring Controller methods.

Throughout the article, we will test each of the mappings showed via simple curl commands.

2. RequestMapping Basic Example

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

2.1. @RequestMapping – by Path

?
1
2
3
4
5
@RequestMapping(value = "/foos")
@ResponseBody
public String getFoosBySimplePath() {
return "Get some Foos";
}
To test out this mapping with a simple curl command, run:

?
1
curl -i http://localhost:8080/spring-rest/foos
2.2. @RequestMapping – the HTTP Method

By default, the HTTP method mapped by a @RequestMapping is GET – this can of course be changed – for example to map to a POST request:

?
1
2
3
4
5
@RequestMapping(value = "/foos", method = RequestMethod.POST)
@ResponseBody
public String postFoos() {
return "Post some Foos";
}
To test the POST via a curl comamnd:

?
1
curl i -X POST http://localhost:8080/spring-rest/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:

?
1
2
3
4
5
@RequestMapping(value = "/foos", headers = "key=val")
@ResponseBody
public String getFoosWithHeader() {
return "Get some Foos with Header";
}
And even multiple headers via the header attribute of @RequestMapping:

?
1
2
3
4
5
@RequestMapping(value = "/foos", headers = { "key1=val1", "key2=val2" })
@ResponseBody
public String getFoosWithHeaders() {
return "Get some Foos with Header";
}
To test the operation, we’re going to use the curl header support:

?
1
curl -i -H "key:val" http://localhost:8080/spring-rest/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:

?
1
2
3
4
5
@RequestMapping(value = "/foos", method = RequestMethod.GET, headers = "Accept=application/json")
@ResponseBody
public String getFoosAsJsonFromBrowser() {
return "Get some Foos with Header Old";
}
The 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:

?
1
curl -H "Accept:application/json,text/html" http://localhost:8080/spring-rest/foos
Starting with Spring 3.1, a the @RequestMapping annotation now has a produces and a consumes attributes, specifically for this purpose:

?
1
2
3
4
5
@RequestMapping(value = "/foos", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public 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:

?
1
curl -H "Accept:application/json" http://localhost:8080/spring-rest/foos
Additionally, produces support multiple values as well:

?
1
@RequestMapping(value = "/foos", produces = { "application/json", "application/xml" })
Keep in mind that these are basically the same mapping, so Spring won’t accept them together – having both these methods active would result in:

?
1
2
3
4
5
6
7
Caused by: java.lang.IllegalStateException: Ambiguous mapping found.
Cannot map 'fooController' bean method
public java.lang.String org.baeldung.spring.web.controller.FooController.getFoosAsJsonFromREST()
to {[/foos],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}:
There is already 'fooController' bean method
public java.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 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:

?
1
2
3
4
5
@RequestMapping(value = "/foos/{id}")
@ResponseBody
public String getFoosBySimplePathWithPathVariable(@PathVariable("id") long id) {
return "Get a specific Foo with id=" + id;
}
This can be tested with curl:

?
1
curl http://localhost:8080/spring-rest/foos/1
If the name of the method argument matches the name of the path variable exactly, then this can be simplified by using @PathVariable with no value:

?
1
2
3
4
5
@RequestMapping(value = "/foos/{id}")
@ResponseBody
public String getFoosBySimplePathWithPathVariable(@PathVariable String 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:

?
1
@PathVariable long id
4.2. Multiple @PathVariable

More complex URI may need to map multiple parts of the URI to multiple values:

?
1
2
3
4
5
@RequestMapping(value = "/foos/{fooid}/bar/{barid}")
@ResponseBody
public 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 curl in the same way:

?
1
curl http://localhost:8080/spring-rest/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:

?
1
2
3
4
5
@RequestMapping(value = "/bars/{numericId:[\\d]+}")
@ResponseBody
public String getBarsBySimplePathWithPathVariable(@PathVariable final long numericId) {
return "Get a specific Bar with id=" + numericId;
}
This will mean that the following URIs will match:

?
1
http://localhost:8080/spring-rest/bars/1
But this will not:

?
1
http://localhost:8080/spring-rest/bars/abc
5. RequestMapping with Request Parameters

@RequestMapping allows easy mapping of URL parameters with the @RequestParam annotation.

We are now mapping a request to an URI such as:

?
1
http://localhost:8080/spring-rest/bars?id=100
?
1
2
3
4
5
@RequestMapping(value = "/bars")
@ResponseBody
public 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:

?
1
curl -i -X POST id=100 http://localhost:8080/spring-rest/bars
In this example, the parameter was bound directly without having been declared first.

For more advanced scenarios, @RequestMapping can explicitly define the parameters to be mapped as yet another way of narrowing the request mapping:

?
1
2
3
4
5
@RequestMapping(value = "/bars", params = "id")
@ResponseBody
public 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 defined, and not all of them have to be used:

?
1
2
3
4
5
@RequestMapping(value = "/bars", params = { "id", "second" })
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParams(@RequestParam("id") long id) {
return "Narrow Get a specific Bar with id=" + id;
}
And of course, a request to an URI such as:

?
1
http://localhost:8080/spring-rest/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:

?
1
2
3
4
5
@RequestMapping(value = { "/advanced/bars", "/advanced/foos" })
@ResponseBody
public String getFoosOrBarsByPath() {
return "Advanced - Get some Foos or Bars";
}
Now, both of these curl commands should hit the same method:

?
1
2
curl -i http://localhost:8080/spring-rest/advanced/foos
curl -i http://localhost:8080/spring-rest/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:

?
1
2
3
4
5
@RequestMapping(value = "/foos/multiple", method = { RequestMethod.PUT, RequestMethod.POST })
@ResponseBody
public String putAndPostFoos() {
return "Advanced - PUT and POST within single method";
}
With curl, both of these will now hit the same method:

?
1
2
curl -i -X POST http://localhost:8080/spring-rest/foos/multiple
curl -i -X PUT http://localhost:8080/spring-rest/foos/multiple
6.3. @RequestMapping – a fallback for all requests

To implement a simple fallback for all requests using a specific HTTP method:

?
1
2
3
4
5
@RequestMapping(value = "*")
@ResponseBody
public String getFallback() {
return "Fallback for GET Requests";
}
Or even for all request:

?
1
2
3
4
5
@RequestMapping(value = "*", method = { RequestMethod.GET, RequestMethod.POST ... })
@ResponseBody
public String allFallback() {
return "Fallback for All Requests";
}
7. Spring Configuration

The Spring MVC Configuration is simple enough – considering that our FooController is defined in the following package:

?
1
2
3
4
package org.baeldung.spring.web.controller;

@Controller
public class FooController { ... }
Starting with Spring 3.1, we will only need a @Configuration class to enable the full MVC support and configure classpath scanning for the controller:

?
1
2
3
4
5
6
@Configuration
@EnableWebMvc
@ComponentScan({ "org.baeldung.spring.web.controller" })
public class MvcConfig {
//
}
8. Conclusion

This article focus on the @RequestMapping annotation in Spring 3 - discussing a simple usecase, the mapping of HTTP headers, binding parts of the URI with @PathVariable and working with URI parameters and the @RequestParam annotation.

The implementation of this simple project can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值