@RequestMapping in Spring

@RequestMapping in Spring

@RequestMapping annotation is used to map a URL pattern to a controller method.

It tells Spring how to route an incoming HTTP requests to the appropriate handler method in your controller.

This annotation is versatile and can be applied at class-level, and method-level.

Mapping URLs


Method-Level Mapping

@RequestMapping can be applied to individual handler methods of the controller, specifying the associated URL patterns.

For instance:

@Controller
class ProductController {    

    @RequestMapping("/products")    
    public String listProducts() {        
            // ...    
    }   

    @RequestMapping(value={"/products/newest","/products/latest"})    
    public String latestProducts() {
        // ...    
    }

}
  • Here, the listProducts() handler method handles requests to <BASE_URL>/products.

  • If multiple URLs need to be mapped to a single handler method, then the array of those URLs can be specified in @RequestMapping annotation.

    For instance, the latestProducts() handler method is mapped to both<BASE_URL>/products/newest and <BASE_URL>/products/latest URLs.

Class-Level Mapping

@RequestMapping can be applied at the Class level (on the Controller class) to define the base URL for all the enclosed handler methods.

All the handler methods of the controller becomes relative to the base URL of controller.

For example:

@Controller
@RequestMapping("/products")
public class ProductController {

    @RequestMapping    
    public String listProducts() {
        // ...    
    }    

    @RequestMapping(value={"/newest","/latest"})
    public String latestProducts() {
        // ...
    }

    @RequestMapping("/details/{id}")
    public String productDetails(@PathVariable("id") Long productId) {
        // ...
    }
}
  • ProductController gets mapped to <BASE_URL>/products, all the enclosed handler methods will be relative to it.

  • The handler method URLs remain same as previous example.

HTTP method-specific Mappings

@RequestMapping can be customized to handle specific HTTP methods, such as GET, POST, PUT, DELETE, etc.

For example:

@Controller
@RequestMapping("/products")
public class ProductController {
    // ...
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String createProduct() {
        // ...    
    }

    //Multiple HTTP Request Methods mapped to same handler method
    @RequestMapping(value = "{id}/description", 
                    method = { RequestMethod.PUT, RequestMethod.POST })
    public String createOrUpdateDescription(@PathVariable("id") Long productId) {
      // ...    
    }
}
  • In this case, the createProduct method only responds to POST requests to <BASE_URL>/products/create.

  • Multiple HTTP methods can be mapped to the same handler method, the HTTP method array needs to be specified in @RequestMapping annotation.

    Ex: the createOrUpdateDescription() handler method is mapped to <BASE_URL>/{id}/newest URL for both POST and PUT HTTP methods.

Spring also provides HTTP method-specific URL mappings based on @RequestMapping annotaion.

AnnotationHTTP Method
@GetMappingGET
@PostMappingPOST
@PutMappingPUT
@PatchMappingPATCH
@DeleteMappingDELETE

These annotations improve the readability and reduce the verbosity of the code.

Request mapping with path variables


@Controller
@RequestMapping("/products")
public class ProductController {
    // ...    

    // Request mapping with path variable
    @RequestMapping("/details/{id}")
    public String productDetails(@PathVariable("id") Long productId) {
        // ...    
    }
}
  • The productDetails() handler method will respond to URLs like <BASE_URL>/products/details/123.

  • If the name of the method parameter matches the name of the path variable exactly, then only specifying @PathVariable would be enough.

Request Parameters and Headers


You can further narrow down mappings by specifying request parameters and headers:

@RequestMapping(value = "/search", 
                params = "query=term", 
                headers = "Accept=application/json")
public String searchProducts() {
    // ...
}

This method will only handle requests to <BASE_URL>/products/search with the query parameter “query” set to “term” and an “Accept” header of “application/json.

Request Mapping: fallback for all requests


Fallback handler method for all GET requests

@Controller
@RequestMapping("/products")
public class ProductController {
    // ..    
    @RequestMapping(value = "*", method = RequestMethod.GET)
    @ResponseBody    
    public String fallback() {
        return "Fallback for GET Requests";    
    }
}
  • All the unmapped URLs matching <BASE_URL>/products/* for HTTP GET requests will be handled by this handler.

  • The same handler method can be mapped to multiple HTTP methods like:

      @RequestMapping(value = "*", 
                  method = { RequestMethod.GET, RequestMethod.POST})
    

Summarizing the @RequestMapping annotation


The @RequestMapping annotation is used to map a URL to a handler method.

It accepts following optional values:

  • produces – Specifies the media types that the handler can produce as a response.

  • consumes – Specifies the request's media types that the handler can consume.

  • headers – Allows to specify headers for the incoming requests. Narrows the mapping based on specific header values.

  • name – Assigns a name to the mapping for documentation and reference.

  • params – Specifies parameters that must be present in the request for the mapping to be applicable. Narrows the mapping based on the presence and values of request parameters

  • path or value – Defines the primary URL path for triggering the handler.

The HTTP method-specific annotations (@GetMapping, @PostMapping , @PutMapping , @PatchMapping , and @DeleteMapping) are composed using @RequestMapping thus these attributes are present in them as well.

Example demonstrating the use of consumes, headers, params, path, and produces:

@RestController
@RequestMapping("/api")
public class ExampleController {

    @GetMapping(value = "/example",
                consumes = MediaType.APPLICATION_JSON_VALUE,
                produces = MediaType.APPLICATION_JSON_VALUE,
                params = "param=value",
                headers = "custom-header=custom-value")
    public ResponseEntity<Map<String, String>> exampleHandler() {
        Map<String, String> response = new HashMap<>();
        response.put("message", "Request handled successfully.");
        return ResponseEntity.ok(response);
    }
}

In this example:

  • The handler method is mapped to the URL path /api/example.

  • It specifies that it consumes and produces JSON data using consumes and produces.

  • The handler method will only be invoked if the request contains a parameter named "param" with the value "value" (params = "param=value").

  • It also checks for a custom header named "custom-header" with the value "custom-value" using headers.

    If these conditions are not met, the handler method will not be invoked, demonstrating the use of @RequestMapping attributes to define precise mapping conditions.

    Sample Request:

      GET /api/example?param=value HTTP/1.1
      Host: localhost:8080
      Content-Type: application/json
      custom-header: custom-value
    

    Sample Response (HTTP 200 OK):

      {
          "message": "Request handled successfully."
      }