web-dev-qa-db-fra.com

Spring MVC: comment indiquer si une variable de chemin est requise ou non?

Je fais une toile de printemps. Pour une méthode de contrôleur, je peux utiliser RequestParam pour indiquer si un paramètre est requis ou non. Par exemple:

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

J'aimerais utiliser PathVariable tel que:

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

Comment puis-je indiquer si une variable de chemin est requise ou non? Je dois le rendre facultatif car lors de la création d'un nouvel objet, aucun ID associé n'est disponible jusqu'à ce qu'il soit enregistré.

Merci pour l'aide!

37
curious1

Il n'y a aucun moyen de le rendre facultatif, mais vous pouvez créer deux méthodes, l'une ayant l'annotation @RequestMapping({"customer"}) et l'autre ayant @RequestMapping({"customer/{id}"}), puis agissant en conséquence dans chacune d'elles.

37
Tristan

VTTom`s solution a raison, il suffit de changer la variable "valeur" en tableau et de répertorier toutes les possibilités d’URL: valeur = {"/", "/ {id}"}

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

Je sais que c’est une vieille question, mais la recherche de «variable de chemin facultative» place cette réponse au centre de la hiérarchie. J’ai donc pensé qu’il serait utile de préciser que, depuis Spring 4.1, l’utilisation de Java 1.8 est possible avec la classe Java.util.Optional.

voici un exemple (notez que la valeur doit répertorier toutes les routes potentielles à associer, c'est-à-dire avec la variable id path et sans. Props à @ martin-cmarko pour l'avoir signalée)

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

Réponse de VTToms ne fonctionnera pas car sans id dans le chemin, il ne sera pas mis en correspondance (c'est-à-dire ne trouvera pas HandlerMapping correspondant) et par conséquent le contrôleur ne sera pas touché. Vous pouvez plutôt faire - 

@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"
    }
}

Vous pouvez également utiliser Java.util.Optional comme d'autres l'ont mentionné, mais cela nécessite Spring 4.1+ et Java 1.8 .. 

3
Aniket Thakur

L'utilisation de 'Optional' (@ PathVariable Optional id) ou de Map (@PathVariable Map pathVariables) pose un problème, car si vous essayez ensuite de créer un lien HATEOAS en appelant la méthode du contrôleur, celui-ci échouera car Spring-hateoas semble être en avance. Java8 et ne prend pas en charge «facultatif». Il ne parvient pas non plus à appeler une méthode avec l'annotation @PathVariable Map.

Voici un exemple qui montre l'échec de 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;

}

0
Ashutosh