Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Web MVC: Use same request mapping for request parameter and path variable

Is there a way to express that my Spring Web MVC controller method should be matched either by a request handing in a ID as part of the URI path ...

@RequestMapping(method=RequestMethod.GET, value="campaigns/{id}") public String getCampaignDetails(Model model, @PathVariable("id") Long id) { 

... or if the client sends in the ID as a HTTP request parameter in the style ...

@RequestMapping(method=RequestMethod.GET, value="campaigns") public String getCampaignDetails(Model model, @RequestParam("id") Long id) { 

This seems to me a quite common real-world URL scheme where I don't want to add duplicate code, but I wasn't able to find an answer yet. Any advice highly welcome.

EDIT: It turns out that there seems currently (with Spring MVC <= 3.0) no way to achieve this, see discussion inside Javi's answer.

like image 847
ngeek Avatar asked Apr 30 '10 15:04

ngeek


People also ask

Can we use both PathVariable and RequestParam?

@RequestParam and @PathVariable can both be used to extract values from the request URI, but they are a bit different.

Can two controllers have same request mapping?

You cannot. A URL can only be mapped to a single controller. It has to be unique.

What is difference between path variable and request parameter?

1) The @RequestParam is used to extract query parameters while @PathVariable is used to extract data right from the URI.

Can we use Requestbody and RequestParam together?

nothing. So it fails with 400 because the request can't be correctly handled by the handler method. The handler for @RequestParam acts first, reading what it can of the HttpServletRequest InputStream to map the request parameter, ie.


1 Answers

You can set both mapping url for the same function and setting id as optional.

@RequestMapping(method=RequestMethod.GET, value={"/campaigns","/campaigns/{id}"}) public String getCampaignDetails(Model model,      @RequestParam(value="id", required=false) Long id,      @PathVariable("id") Long id2) { } 

though it would map as well when id is not sent, but you can control this inside the method.

EDIT: The previous solution doesn't work because @PathVariable is not set to null when there isn't {null} and it cannot map the URL (thanks ngeek). I think then that the only possible solution is to create two methods each one mapped with its @MappingRequest and inside one of them call the other function or redirect to the other URL (redirect: or forward: Spring prefixes). I know this solution is not what you're looking for but think it's the best you can do. Indeed you're not duplicating code but you're creating another function to handle another URL.

like image 144
Javi Avatar answered Oct 14 '22 00:10

Javi