204 votes

Avec Spring, puis-je créer une variable de chemin facultative ?

Avec Spring 3.0, puis-je avoir une variable de chemin facultative ?

Par exemple

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

Ici, je voudrais /json/abc o /json pour appeler la même méthode.
Un contournement évident déclare type comme paramètre de la demande :

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testAjax(
        HttpServletRequest req,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam("track") String track) {
    return new TestBean();
}

et ensuite /json?type=abc&track=aa o /json?track=rr fonctionnera

208voto

James Points 5907

Vous ne pouvez pas avoir de variables de chemin facultatives, mais vous pouvez avoir deux méthodes de contrôleur qui appellent le même code de service :

@RequestMapping(value = "/json/{type}", method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
        HttpServletRequest req,
        @PathVariable String type,
        @RequestParam("track") String track) {
    return getTestBean(type);
}

@RequestMapping(value = "/json", method = RequestMethod.GET)
public @ResponseBody TestBean testBean(
        HttpServletRequest req,
        @RequestParam("track") String track) {
    return getTestBean();
}

5 votes

@Shamik : C'est une raison impérieuse no d'utiliser des variables de chemin, à mon avis. La prolifération combinatoire peut rapidement devenir incontrôlable.

9 votes

En fait non, car le chemin ne peut pas être aussi complexe tout en étant rempli de composants optionnels. Si vous avez plus d'un ou au maximum deux éléments de chemin facultatifs, vous devriez sérieusement envisager de changer quelques-uns d'entre eux en paramètres de requête.

1 votes

Et pour certaines personnes, le fait que la deuxième méthode du contrôleur appelle la première méthode du contrôleur peut également fonctionner, si par exemple le paramètre différent peut être fourni par d'autres moyens.

127voto

Aniket Thakur Points 10135

Si vous utilisez Spring 4.1 et Java 8, vous pouvez utiliser java.util.Optional qui est pris en charge dans @RequestParam , @PathVariable , @RequestHeader y @MatrixVariable dans Spring MVC -

@RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Optional<String> type,
    @RequestParam("track") String track) {      
    if (type.isPresent()) {
        //type.get() will return type value
        //corresponds to path "/json/{type}"
    } else {
        //corresponds to path "/json"
    }       
}

79voto

Paul Wardrip Points 844

Il n'est pas très connu que vous pouvez également injecter une carte des variables de chemin en utilisant l'annotation @PathVariable. Je ne sais pas si cette fonctionnalité est disponible dans Spring 3.0 ou si elle a été ajoutée plus tard, mais voici une autre façon de résoudre l'exemple :

@RequestMapping(value={ "/json/{type}", "/json" }, method=RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Map<String, String> pathVariables,
    @RequestParam("track") String track) {

    if (pathVariables.containsKey("type")) {
        return new TestBean(pathVariables.get("type"));
    } else {
        return new TestBean();
    }
}

30voto

Maleck13 Points 552

Vous pourriez utiliser un :

@RequestParam(value="somvalue",required=false)

pour les paramètres facultatifs plutôt qu'une pathVariable

1 votes

C'est spécifique à la version, il semble. C'est impossible pour Spring 3.

5 votes

J'utilise actuellement cette méthode pour un projet Spring 3.1, et la documentation indique que cela fonctionne pour 2.5+, donc cela fonctionne certainement pour Spring 3. EDIT : source .

22 votes

C'est vrai, mais ce n'est pas le sujet de la question. Utilisation de demande paramètres est en effet mentionné dans la question comme "Une solution de rechange évidente" mais la question elle-même porte sur chemin paramètres. Ce n'est pas une solution pour les paramètres de chemin facultatifs.

15voto

wildloop Points 2814

Exemples de Spring 5 / Spring Boot 2 :

blocage

@GetMapping({"/dto-blocking/{type}", "/dto-blocking"})
public ResponseEntity<Dto> getDtoBlocking(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return ResponseEntity.ok().body(dtoBlockingRepo.findByType(type));
}

réactif

@GetMapping({"/dto-reactive/{type}", "/dto-reactive"})
public Mono<ResponseEntity<Dto>> getDtoReactive(
        @PathVariable(name = "type", required = false) String type) {
    if (StringUtils.isEmpty(type)) {
        type = "default";
    }
    return dtoReactiveRepo.findByType(type).map(dto -> ResponseEntity.ok().body(dto));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X