2010-04-30 3 views
37

Gibt es eine Möglichkeit, auszudrücken, dass meine Spring Web MVC-Controller-Methode entweder durch eine Anforderung eine ID als Teil des URI-Pfads einreichen ...Spring Web MVC: Verwenden Sie dieselbe Anforderungszuordnung für Anforderungsparameter und Pfadvariable

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

... oder wenn der Kunde sendet in der ID als HTTP-Request-Parameter im Stil ...

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

Dies wo ein recht häufig URL-Schema der realen Welt zu mir scheint, ich Ich möchte keinen doppelten Code hinzufügen, aber ich konnte noch keine Antwort finden. Jeder Ratschlag ist sehr willkommen.

EDIT: Es stellt sich heraus, dass es derzeit scheint (mit Spring MVC < = 3,0) keine Möglichkeit, dies zu erreichen, siehe die Diskussion innerhalb Javi Antwort.

Antwort

50

Sie können beide Mapping-URLs für dieselbe Funktion und Einstellungs-ID als optional festlegen.

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

obwohl es auch zuordnen würde, wenn ID nicht gesendet wird, aber Sie können dies innerhalb der Methode steuern.

EDIT: Die bisherige Lösung funktioniert nicht, da @PathVariable nicht null gesetzt wird, wenn es nicht {null} ist, und es kann die URL (dank ngeek) nicht abbilden. Ich denke dann, dass die einzige mögliche Lösung ist, zwei Methoden zu erstellen, die jeweils mit seinem @MappingRequest zugeordnet sind und innerhalb einer von ihnen die andere Funktion aufrufen oder an die andere URL umleiten (redirect: or forward: Spring prefixes). Ich weiß, dass diese Lösung nicht das ist, wonach Sie suchen, sondern dass es das Beste ist, was Sie tun können. Tatsächlich duplizieren Sie Code nicht, aber Sie erstellen eine andere Funktion, um mit einer anderen URL zu arbeiten.

+1

Leider funktioniert dies nicht, da die Pfadvariable nicht aufgelöst werden kann. Ich habe auch eine Variante versucht, indem ich zu den Methodenparametern (@PathVariable ("id") Long id2) hinzugefügt habe, aber dann kann man eine Pfadvariable nicht optional machen, daher funktioniert diese vorgeschlagene Lösung nicht. Weitere Empfehlungen? – ngeek

+0

@geek Ich habe nicht bemerkt, dass @PathVariable nicht auf null gesetzt werden konnte, danke. Ich habe auch vergessen, @PathVariable zu schreiben, also habe ich meine Antwort bearbeitet, um sie hinzuzufügen, und ich denke, Sie können nicht vermeiden, 2 Methoden zu haben, die ich denke :(. – Javi

+1

Danke, dass Sie zu Ihrem Vorschlag Javi zurückkommen die gleiche interne Methode zu vermeiden, Code zu duplizieren.Ich denke immer noch, dass Spring MVC-Annotationen eine Möglichkeit bieten sollten, mehrere URL-Definitionen derselben Methode durch intrinsische Mittel zuzuordnen, wie Router in Rails oder Grails bereits erlauben. Vielen Dank für Ihre Hilfe – ngeek

4

Wenn Sie noch PathVariable Ansatz bleiben wollen, und wenn Sie 400 syntaktisch falsch Fehler immer dann folgen diese approach-

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

    System.out.println(pathVariables.get("id")); 

    } 
1

Die @RequestMapping Anmerkung Einstellung unterstützt nun die path statt name oder value zuschreiben. Mit path können Sie die gewünschte Zuordnung durch diese Frage erreichen:

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

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