The new Certification Class of Learn Spring Security is out:


1. Overview

In this article, we’ll focus on one of the main annotations in Spring MVC – @RequestMapping.

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)
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

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)
public 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)
public String getFoosWithHeader() {
    return "Get some Foos with Header";

And even multiple headers via the header attribute of @RequestMapping:

  value = "/ex/foos", 
  headers = { "key1=val1", "key2=val2" }, method = GET)
public 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:

  value = "/ex/foos", 
  method = GET, 
  headers = "Accept=application/json")
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:

curl -H "Accept:application/json,text/html" 

Starting with Spring 3.1, the @RequestMapping annotation now has the produces and the consumes attributes, specifically for this purpose:

  value = "/ex/foos", 
  method = RequestMethod.GET, 
  produces = "application/json"
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:

curl -H "Accept:application/json" 

Additionally, produces support multiple values as well:

  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 
{ [/ex/foos],
There is already 'fooController' bean method

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.

And of course, if you want to dig deeper into building a REST API with Spring – check out the new REST with Spring course.

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)
public String getFoosBySimplePathWithPathVariable(
  @PathVariable("id") long id) {
    return "Get a specific Foo with id=" + id;

This can be tested with curl:

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

@RequestMapping(value = "/ex/foos/{id}", method = GET)
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:

@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)
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 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)
public String getBarsBySimplePathWithPathVariable(
  @PathVariable long numericId) {
    return "Get a specific Bar with id=" + numericId;

This will mean that the following URIs will match:


But this will not:


Further reading:

Serve Static Resources with Spring

How to map and handle static resources with Spring MVC - use the simple configuration, then the 3.1 more flexible one and finally the new 4.1 resource resolvers.

Read more

Getting Started with Forms in Spring MVC

Learn how to work with forms using Spring MVC - mapping a basic entity, submit, displaying errors.

Read more

Http Message Converters with the Spring Framework

How to configure HttpMessageConverters for a REST API with Spring, and how to use these converters with the RestTemplate.

Read more

5. 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:

@RequestMapping(value = "/ex/bars", method = GET)
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:

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:

@RequestMapping(value = "/ex/bars", params = "id", method = GET)
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 set, and not all of them have to be used:

  value = "/ex/bars", 
  params = { "id", "second" }, 
  method = GET)
public 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:


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:

  value = { "/ex/advanced/bars", "/ex/advanced/foos" }, 
  method = GET)
public 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/foos
curl -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:

  value = "/ex/foos/multiple", 
  method = { RequestMethod.PUT, RequestMethod.POST }
public 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)
public String getFallback() {
    return "Fallback for GET Requests";

Or even for all requests:

  value = "*", 
  method = { RequestMethod.GET, RequestMethod.POST ... })
public 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

These new annotations can improve the readability and reduce the verbosity of the code. Let us look at these new annotations in action by creating a RESTful API that supports CRUD operations:

public ResponseEntity<?> getBazz(@PathVariable String id){
    return new ResponseEntity<>(new Bazz(id, "Bazz"+id), HttpStatus.OK);

public ResponseEntity<?> newBazz(@RequestParam("name") String name){
    return new ResponseEntity<>(new Bazz("5", name), HttpStatus.OK);

public ResponseEntity<?> updateBazz(
  @PathVariable String id,
  @RequestParam("name") String name) {
    return new ResponseEntity<>(new Bazz(id, name), HttpStatus.OK);

public ResponseEntity<?> deleteBazz(@PathVariable String id){
    return new ResponseEntity<>(new Bazz(id), HttpStatus.OK);

A deep dive into these can be found here.

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;

public class FooController { ... }

We simply need a @Configuration class to enable the full MVC support and configure classpath scanning for the controller:

@ComponentScan({ "org.baeldung.spring.web.controller" })
public class MvcConfig {

9. Conclusion

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

If you’d like to learn how to use another core annotation in Spring MVC, you can explore the @ModelAttribute annotation here.

The full code from the article is available on Github. This is a Maven project, so it should be easy to import and run as it is.

Go deeper into Spring Security with the course:


  • sorry, how i can get source code from git, i have try but i cann’t

  • I really love the way you structured this post. It is extremely informative in a way that’s very easy to scan. I learned a few things I didn’t know about Spring, which I’ve been using for quite a long time now, in just minutes. Thanks for taking the time to share!

    • I’m glad you found the article helpful.

    • Lajos Incze


    • Jonathan Gibran Hernandez Antu

      I think the same

  • grooha

    OK, but what’s about multiple values pass in a 1 param, e.g.? http://…/age=23&fav=12&fav=15

    As you can see, we have two parameters: age, and fav. The fav param. has two values: 12, and 15. Suppose, that there is a class:

    public class MyClass {
    private int age;
    private int fav;


    No problem with a single value for fav – it will be binded to int fav in the MyClass class. But in that case we have two values… I suppose, Spring MVC will bind only the first value (12) to fav, right? What should I do to make this code working?

    • Interesting question – if you have a choice, I would suggest keeping the parameter names unique (you can have the values as comma separated and then parse them out). If that’s not an option, I would try to map it to an array – and if Spring isn’t able to do so, you can always open a JIRA.
      You can always go lower level and simply inject into your controller method the http request, and parse out the parameters yourself.

      • grooha

        Thanks for your answer. I’ve considered parsing out all needed params in my controller, maybe it will be the best choice. I will let you know and publish a working solution – maybe it will help someone in the future. Thanks again!

  • Manish Sahni

    Hi Eugen,
    Nice informative artice on Rest .How can we pass a Object from the client and handle it in the Rest using Spring.I am new to Rest and seen some articles hat describes we can send it as a JSON string or XML.
    Is thier any other way to achieve this other than these ?

    • Hey Manish – sure, you can map an object passed in the body of the request in your controller layer – you’ll need to use the @RequestBody annotation for that. You can check out this introductory article to see how that works. Hope it helps. Cheers,

  • Tobi Bod

    Great article and summary of RequestMapping! Thanks for your effort!

  • As I just tested, the default method, when you don’t provide anything, seems to be not only GET as you mention in 2.2, but all. (It always confuses me, and spring documentation seems to be silent on it, so I just thought checked it out.)

    • You’re right – it has no default – nice catch. I’ll update that section. Cheers,

      • Rubén Pahíno Verdugo

        given that, is 6.3 correct? I mean… you say this:

        To implement a simple fallback for all requests using a SPECIFIC HTTP method:
        @RequestMapping(value = “*”)

        but I understand that that’s the mapping for all methods. Am I wrong?


        • Same situation – it was missing the method as well – fixed. Thanks for the to the point feedback. Cheers,

  • venkat

    PathVariable with ReqEx syntax seems to be incorrect.

    @RequestMapping(value = “/ex/bars/{numericId:[d]+} , it should be @RequestMapping(value = “/ex/bars/{numericId:[\d]+}

    • Hey Venkat – yes it should. It is like that in the code, but for some reason, the article wasn’t matching that – thanks for pointing it out. Updated.

      • Kisna

        For some reason, few request patterns/paths are being suppressed by Tomcat itself from even before being handled by application. It is easy to reproduce, here is an example: just add /%%test%%/ to path:

        • Yes, definitely – the request needs to actually make it through Tomcat and hit the servlet in order to even consider the Spring mappings.

  • Kisna

    Shouldn’t the fallback suppose to handle all other requests that are not mapped? Don’t see it being handled by debugging, instead get 404 and a “No mapping found” in the logs.

    @RequestMapping(value = “*”, method = RequestMethod.GET)
    public @ResponseBody String getFallback(HttpServletRequest req, Exception exception)
    throws Exception {
    logger.error(“Request=” + req.getRequestURI() + ” not mapped, returning empty “);
    return REDIRECT + “”;

    • Hey Kisna – I wasn’t able to replicate the problem – basically, I couldn’t find any example where the fallback didn’t work. So – if you have an example, open up an issue over on github with the details of that example and I’d be happy to take a look. Cheers,

  • Grant Lay

    Nice article. A question, what is the best way to map a delete function that returns void?

    • A couple of things. First – of course use the DELETE verb, second – return a 204 No Content. Alternatively you can simply return a 200 and tell the client what to do next (if the API is more advanced), but the 204 is a solid simple way to go. Hope it helps. Cheers,

  • Grant Lay

    Handy tips on the params attribute, I was previously using if else statements within a single controller method. Now I can separate into multiple controller methods and it seems much cleaner now.

    Is there a way to achieve the same thing (multiple controller methods) using different @RequestBody types?

  • Scott Stanlick

    Great job. Specifying @RequestParam on a controller argument is by default required. It has an attribute you can optionally switch to false. Therefore, specifying the parms again on the @RequestMapping is superflous. Also the @Configuration will automatically scan for components rooted in the same package as the type annotated with @Configuration. I only mention this because less code is better code!

    • Hey Scott – first off, thanks for the feedback – definitely helpful. So – on the fact that the params are optional for the @RequestMapping – yes, pretty much. The only usecase (I’m aware of) for still doing that is to help the handler resolution process by basically narrowing the mapping.
      Now – about the @Configuration scanning its own package – that’s cool, I didn’t know that. In this case however, I’m not sure if that necessarily helps, because the config class may not be in the same package with the controller (it usually isn’t).
      Thanks again for the feedback, and if you notice anything else – keep that coming 🙂

  • Jeremy Pulcifer

    Given that this discussion is specific to rest api development, perhaps @RestController could be used instead of @Controller?

    Edit: I now notice that this (excellent) blog post is a couple of years old, pre-Spring 4.

    • Hey Jeremy – yes, the article is a couple of years old, but I always update articles as things get released, so I have looked at this one recently as well. The reason it’s not mentioning the @RestController is three-fold. First – the new Spring Boot annotation isn’t super different – it really just ads a @ResponseBody that you no longer have to do manually. Second – the article is only showing the controller code incidentally at the very end, just for reference. And finally – the article itself is not necessarily about REST. I do have a lot of REST focused articles here on the site, but this isn’t specifically one of them.
      Hope that makes sense. Cheers,

      • Jeremy Pulcifer

        Fair enough! Really appreciate your work.

        • Thanks for following up – glad it makes sense. And of course, feel free to always reach out if you have questions. Cheers,

  • MountainKiddo

    Is there a way to get the whole query string without it being parsed? As in:
    I want to get everything following the ? as one string. Yes I will parse it later, but this allows my controller to be more generic.
    Thanks for your posts! I enjoy getting them.

    • Hey Kiddo – sure, you can inject the actual HTTP request into your controller and then retrieve the full URL out of that. There’s also a handy ServletUriComponentsBuilder you can use for that as well. Cheers,

  • Vikram Josh

    can you please put some web oriented example by using matrix variables mapping ?
    Means, they should show view part and controller part for handling the matrix variables, as we should understand how to design view part for the matrix variable functionality?

    Thanks in Advance…..

    • Hey Josh – email is better if you want to request a topic. Sure – I can put that on the content calendar of the site. Cheers,

  • somdip sanyal

    I want to know the regex for this kind of URL pattern

    where MSG456 is the code which I want as in Path Variable . Can you please help me with this.

    • Hey Somdip – in that case you probably don’t need a regex – you simply need to define the URL pattern: @RequestMapping(value = “/women/{id}”)
      That way you can access that id directly.

  • bostown03

    Great work on this post! Thank you for sharing and taking the time.

  • Alexander Buss

    Hi Eugen, great post!
    But how do I deal with following: I have the following @RequestMapping /users/{userId}
    when I call following url: http://localhost:8888/users/john.doe I get only john in the @PathVariable String userId instead john.doe
    Is it not allowed to have dot (.) in last path of the url? Is .doe interpreted as file extension? How is it possible to solve this?

    • Yeah, I ran into that a while back as well. The issue was that, by default, the Content Negotiation strategy was seeing the last part (after the dot) as an extension. You need to disable that strategy (I assume you’re not using it). Here’s some detail on that.
      Hope it helps. Cheers,

  • Saikat Gupta

    Hi Eugen, It’s a great post. Really loved this.

  • Sergey Frolov

    Thank you for this article – very useful.

  • Great post, very well structured

  • naveen


  • Mirco Gatz

    thanks for the article! simple, clean, very useful!!

  • Matrica Joshi

    Thank you for the article. I have a question. Can I pass multiple string parameters and also one multivaluemap parameters for get call. For example-
    public String getBarBySimplePathWithRequestParam( @RequestParam(“id”) long id, @RequestParam(“name”) String name,@RequestParam(“filters”)MultivalueMap filters)
    What would be the url for this type of call – http://localhost:8080/spring-rest/api?id=1&name=name&filters=%5B'abc'='xyz‘, ‘def’=’ghi’, ‘abc’=’jkl’]

    • Hey Joshi,
      That’s an interesting question – I’m not sure without actually trying it out. Theoretically you should, but as it’s most often the case with these very complex URIs, you need to actually try it and see if the framework does the resolution correctly it out of the box.
      Now – if it doesn’t, there are things you can do (like debug through the exact handler resolution to see why it doesn’t) – but that’s the general high level approach I would take.
      Hope that helps. Cheers,

  • Sujit Tripathy

    Hey Eugen,
    Thanks for the nice article post. I was trying on the Spring request mapping and got a question. Is it possible to send Objects in Request mapping GET as Request or Path variable. For example- On a page I am displaying 10 rows of Book object where individual row is one object of book, I want to edit the book entity by sending the model book object to a spring request GET mapping. I am able to achieve this by sending as Path variable and got the actual Book object from DB (below is the code snippet) however I am wondering if I can get the direct Book object from the record list so that I can avoid the DB call. Is it feasible?

    public String edit(@PathVariable Integer isbn, Model model){
    Book book=bookRepository.findOne(isbn); // Spring data H2 call
    return “EditBookDetails”;

    • That’s an interesting question – let’s break it down.
      First – you’re aiming to do an edit operation via a GET, if I’m understanding that correctly. Semantically, GET isn’t the best way to go there – maybe consider a PUT (or a PATCH) instead.
      Next – if you’re aiming to send a representation of your Resource over the wire, no – the URL isn’t a good place for that. Rather the body of the HTTP request is a better way to go.
      So, the simple answer is – yes, you can certainly do that, just do it via the body and not the URL.
      Finally – I would also note that, if you do avoid the DB call, it’s important to be aware of the fact that you may be working with stale data in the absence of any locking logic on that data.
      Hope that helps. Cheers,

      • Sujit Tripathy

        Thanks for the response. Will try the post way to send object. The DB call is primarily for the updating the object via spring data so not quite understood about the stale data.

        • Sounds good.
          So, about the stale data, I assumed you were referring to first retrieving the data from the DB, then copying over the changes and then doing the update operation. That’s why I was talking about stale data.
          But if that’s not the case, and if you’re simply doing an update operation (that hits the DB) – how would the way you send the data over the wire affect that? The update still needs to happen regardless.

  • RU

    If i have many request parameters, is there a way to bind them to attributes of a Request class, instead of having all of them listed as params to the method?

    public Response getResponse(@RequestParam(“id”) long id,@RequestParam(“id1”) long id1, @RequestParam(“id2”) long id2, @RequestParam(“idx”) long idx) {
    //code goes here

    //Is something like this possible?
    public Response getRespose(Request req) {
    //Code goes here

    public class Request{
    long id1;
    long id2;
    long id3;

  • Yousif Al-Yousifi

    Great! I will use this as a quick reference from now on.

  • Tarek Sahalia

    Hey man, that’s the way book writer and tutorial makers need to follow. thank you very much.

  • Grayson

    Anyone happen to know if there is a better way than this to have multiple paths mapped to the same controller method with one of the paths containing a numeric path variable? And no, I don’t want to just pass the variable as a param. This works fine, I was just wondering if there was a more conventional / even easier way to do it.

    @GetMapping({ "/getsomething", "/{domainId}/getsomething" })
    public Map getSomething(@PathVariable String accountId, @PathVariable Optional domainId) {
    return service.getSomething(accountId, domainId.isPresent() ? Integer.parseInt(domainId.get()) : 0);

    • Grzegorz Piwowarek

      Good question. Unfortunately, I do not think it can be done better and I will am curious to see other answers too.