In this article, we are going discuss about one of the main annotation in Spring MVC @RequestMapping – used to mapping a web request to Spring Controller's handler methods.
All incoming requests are handled by the Dispatcher Servlet and it route them through Spring. When it receives a web request, it determines which controllers should handle the incoming request.
Dispatcher Servlet initially scans all the classes that are annotated with the @Controller annotation. The dispatching process depends on the various @RequestMapping annotations declared in a controller class and its handler methods.
There are three levels of request mapping in Spring MVC
- @RequestMapping annotations at only method level
- @RequestMapping annotations at class level
- Mapping requests by request type
@RequestMapping can be applied to the controller class as well as methods. This annotation for mapping web requests onto specific handler classes and/or handler methods.
@ImageSource-SlideShare.net
@RequestMapping annotations at only method level
In this case we are using @RequestMapping annotations is to declare the handler methods directly. The handler method is annotated with @RequestMapping annotation containing a URL pattern. If this pattern of a handler @RequestMapping annotation matches the request URL, DispatcherServlet it dispatches the request to this handler for it to process the request.
1. @RequestMapping Basics
Let’s discuss with a simple example – mapping an HTTP request to a method using some straightforward criteria.
1.1 @RequestMapping – by Path
@RequestMapping(value = "/doj/spring")
@ResponseBody
public String getDOJSpringCourse(){
return "Get DOJ Course for Spring";
}
Popular Tutorials
For testing hit following URL on browser:
GET http://localhost:8080/SpringApp/doj/spring
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html
Content-Length: 25
Date: Fri, 18 Mar 2016 10:38:14 GMT
Get DOJ Course for Spring
1.2 @RequestMapping – the HTTP Method
There is no by default HTTP method mapped by a @RequestMapping – so it maps to any type of HTTP request; we sh to add the method :
@RequestMapping(value = "/doj/spring", method = RequestMethod.POST)
@ResponseBody
public String postDOJSpringCourse(){
return "Post DOJ Course for Spring";
}
POST http://localhost:8080/SpringApp/doj/spring
Content-Type: application/json
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html
Content-Length: 26
Date: Fri, 18 Mar 2016 10:38:22 GMT
Post DOJ Course for Spring
2. RequestMapping with HTTP Headers
2.1. @RequestMapping with the headers attribute
The mapping can be narrowed even further by specifying a header for the request:
@RequestMapping(value = "/doj/spring", headers = "key=val")
@ResponseBody
public String getDOJSpringCourseWithHeaders(){
return "Get DOJ Course for Spring with headers";
}
And even multiple headers via the header attribute of @RequestMapping:
@RequestMapping(value = "/doj/spring", headers = {"key1=val1", "key2=val2"})
@ResponseBody
public String getDOJSpringCourseWithHeaders(){
return "Get DOJ Course for Spring with headers";
}
2.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 = "/doj/spring", headers = "Accept=application/json")
@ResponseBody
public String getDOJSpringCourseJSON(){
return "Get DOJ Course for Spring as JSON";
}
GET http://localhost:8080/SpringApp/doj/spring
key: value
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Content-Length: 33
Date: Fri, 18 Mar 2016 10:57:03 GMT
Get DOJ Course for Spring as JSON
@RequestMapping annotation now has a produces and a consumes attributes, specifically for this purpose:
@RequestMapping(value = "/doj/spring", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public String getDOJSpringCourseJSONFromREST(){
return "Get DOJ Course for Spring as JSON from REST";
}
GET http://localhost:8080/SpringApp/doj/spring
key: value
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Content-Length: 43
Date: Fri, 18 Mar 2016 11:00:28 GMT
Get DOJ Course for Spring as JSON from REST
Additionally, produces support multiple values as well:
@RequestMapping(value = "/doj/spring", produces = { "application/json", "application/xml" })
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.
3. RequestMapping with Path Variables
Parts of the mapping URI can be bound to variables via the @PathVariable annotation.
3.1. Single @PathVariable
@RequestMapping(value = "/doj/spring/{id}")
@ResponseBody
public String getDOJCourseWithPathVariable(@PathVariable("id") int id) {
return "Get a DOJ Course with id=" + id;
}
GET http://localhost:8080/SpringApp/doj/spring/2000
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html
Content-Length: 29
Date: Fri, 18 Mar 2016 11:11:40 GMT
Get a DOJ Course with id=2000
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:
@RequestMapping(value = "/doj/spring/{id}")
@ResponseBody
public String getDOJCourseWithPathVariable(@PathVariable int id) {
return "Get a DOJ Course with id=" + id;
}
3.2. Multiple @PathVariable
More complex URI may need to map multiple parts of the URI to multiple values:
@RequestMapping(value = "/doj/{course}/{id}")
@ResponseBody
public String getDOJCourseWithPathVariable(@PathVariable("course") String course ,@PathVariable("id") long id) {
return "Get a DOJ Course with id=" + id+" course name ="+course;
}
GET http://localhost:8080/SpringApp/doj/spring/2000
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html
Content-Length: 49
Date: Fri, 18 Mar 2016 11:16:19 GMT
Get a DOJ Course with id=2000 course name =spring
3.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 = "/doj/{course}/{numericId:[\\d]+")
@ResponseBody
public String getDOJCourseWithPathVariable(@PathVariable("course") String course ,@PathVariable("id") long id) {
return "Get a DOJ Course with id=" + id+" course name ="+course;
}
This will mean that the following URIs will match:
http://localhost:8080/SpringApp/doj/spring/2000
But this will not:
http://localhost:8080/SpringApp/doj/spring/xyz
4. 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:
@RequestMapping(value = "/doj/spring")
@ResponseBody
public String getDOJCourseByRequestParam(@RequestParam("id") long id) {
return "Get a DOJ Course with id=" + id;
}
We are then extracting the value of the id parameter using the @RequestParam(“id”) annotation in the controller method signature.
GET http://localhost:8080/SpringApp/doj/spring?id=2000
-- response --
200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html
Content-Length: 29
Date: Fri, 18 Mar 2016 11:29:25 GMT
Get a DOJ Course with id=2000
@RequestMapping can optionally define the parameters – as yet another way of narrowing the request mapping:
@RequestMapping(value = "/doj/spring", params = "id")
@ResponseBody
public String getDOJCourseByRequestParam(@RequestParam("id") long id) {
return "Get a DOJ Course with id=" + id;
}
Even more flexible mappings are allowed – multiple params values can be defined, and not all of them have to be used:
@RequestMapping(value = "/doj/spring", params = {"id","course"})
@ResponseBody
public String getDOJCourseByRequestParam(@RequestParam("id") long id, @RequestParam("course") String course) {
return "Get a DOJ Course with id=" + id+" Course="+course;
}
5. RequestMapping Corner Cases
5.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 = {"/doj/spring/index", "/doj/spring/home"})
@ResponseBody
public String getDOJHome() {
return "Get a DOJ Home Page";
}
5.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 = {"/doj/spring/home"}, method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String getDOJHome() {
return "Get a DOJ Home Page";
}
5.3. @RequestMapping – a fallback for all requests
To implement a simple fallback for all requests using a specific HTTP method:
@RequestMapping(value = {"*"})
@ResponseBody
public String getDOJDefaultPage() {
return "Get a DOJ Default Page";
}
@RequestMapping annotations at class level
In this case we are using @RequestMapping annotations at the class level. It is used for filter all incoming request at class level first before forwarding to handler methods. If the incoming request matches the pattern defined in controller class, then it search the controller methods mappings.
@Controller
@RequestMapping("/login/")
public class Login{
@RequestMapping("doLogin")
public ModelAndView doLogin(
@RequestParam(value = "username") String username,
@RequestParam(value = "password") String password) {
//....
//....
return null;
}
@RequestMapping(value={"logout","signout"})
public ModelAndView logout(
@RequestParam(value = "username") String username) {
//....
//....
return null;
}
}
Conclusion
This article focus on the @RequestMapping annotation in Spring – 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.