문제

I am doing a Spring web. For a controller method, I am able to use RequestParam to indicate whether a parameter it is required or not. For example:

@RequestMapping({"customer"}) 
public String surveys(HttpServletRequest request, 
@RequestParam(value="id", required = false) Long id,            
Map<String, Object> map)

I would like to use PathVariable such as the following:

@RequestMapping({"customer/{id}"}) 
public String surveys(HttpServletRequest request, 
@PathVariable("id") Long id,            
Map<String, Object> map) 

How can I indicate whether a path variable is required or not? I need to make it optional because when creating a new object, there is no associated ID available until it is saved.

Thanks for help!

도움이 되었습니까?

해결책 2

There's no way to make it optional, but you can create two methods with one having the @RequestMapping({"customer"}) annotation and the other having @RequestMapping({"customer/{id}"}) and then act accordingly in each.

다른 팁

VTTom`s solution is right, just change "value" variable to array and list all url possibilities: value={"/", "/{id}"}

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}

I know this is an old question, but searching for "optional path variable" puts this answer high so i thought it would be worth pointing out that since Spring 4.1 using Java 1.8 this is possible using the java.util.Optional class.

an example would be (note the value must list all the potential routes that needs to match, ie. with the id path variable and without. Props to @martin-cmarko for pointing that out)

@RequestMapping(method=GET, value={"/", "/{id}"})
public void get(@PathVariable Optional<Integer> id) {
  if (id.isPresent()) {
    id.get()   //returns the id
  }
}

VTToms answer will not work as without id in path it will not be matched (i.e will not find corresponding HandlerMapping) and consequently controller will not be hit. Rather you can do -

@RequestMapping({"customer/{id}","customer"}) 
public String surveys(HttpServletRequest request, @PathVariable Map<String, String> pathVariablesMap, Map<String, Object> map) {
    if (pathVariablesMap.containsKey("id")) {
        //corresponds to path "customer/{id}"
    }
    else {
        //corresponds to path "customer"
    }
}

You can also use java.util.Optional which others have mentioned but it requires requires Spring 4.1+ and Java 1.8..

There is a problem with using 'Optional'(@PathVariable Optional id) or Map (@PathVariable Map pathVariables) in that if you then try to create a HATEOAS link by calling the controller method it will fail because Spring-hateoas seems to be pre java8 and has no support for 'Optional'. It also fails to call any method with @PathVariable Map annotation.

Here is an example that demonstrates the failure of Map

   @RequestMapping(value={"/subs","/masterclient/{masterclient}/subs"}, method = RequestMethod.GET)
   public List<Jobs>  getJobListTest(
         @PathVariable  Map<String, String> pathVariables,
         @RequestParam(value="count", required = false, defaultValue = defaultCount) int count) 
   {

      if (pathVariables.containsKey("masterclient")) 
      {
         System.out.println("Master Client = " + pathVariables.get("masterclient"));
      } 
      else 
      {
         System.out.println("No Master Client");
      }




  //Add a Link to the self here.
  List list = new ArrayList<Jobs>();
  list.add(linkTo(methodOn(ControllerJobs.class).getJobListTest(pathVariables, count)).withSelfRel());

  return list;

}

I know this is an old question, but as none of the answers provide some updated information and as I was passing by this, I would like to add my contribution:

Since Spring MVC 4.3.3 introduced Web Improvements,

@PathVariable(required = false) //true is default value

is legal and possible.

@RequestMapping(path = {"/customer", "/customer/{id}"})
public String getCustomerById(@PathVariable("id") Optional<Long> id) 
        throws RecordNotFoundException 
{
    if(id.isPresent()) {
        //get specific customer
    } else {
        //get all customer or any thing you want
    }
}

Now all URLs are mapped and will work.

/customer/123

/customer/1000

/customer - WORKS NOW !!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top