it-swarm.com.de

Frühling - Weiterleitung nach POST (auch bei Validierungsfehlern)

Ich versuche herauszufinden, wie man das BindingResult "bewahren" kann, damit es in einem nachfolgenden GET über das Spring <form:errors>-Tag verwendet werden kann. Der Grund, warum ich dies tun möchte, liegt in den SSL-Beschränkungen von Google App Engine. Ich habe ein Formular, das über HTTP angezeigt wird und der Beitrag auf eine HTTPS-URL lautet. Wenn ich nur Weiterleiten statt Weiterleiten, wird dem Benutzer die URL https://whatever.appspot.com/my/form angezeigt. Ich versuche das zu vermeiden. Irgendwelche Ideen, wie man das angehen kann?

Im Folgenden möchte ich etwas tun, aber ich sehe nur Validierungsfehler, wenn ich return "create" verwende.

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(
    @ModelAttribute("register") @Valid final Register register,
    final BindingResult binding) {

    if (binding.hasErrors()) {
        return "redirect:/register/create";
    }

    return "redirect:/register/success";
}
57
Taylor Leese

Seit Spring 3.1 können Sie RedirectAttributes verwenden. Fügen Sie die Attribute hinzu, die vor der Umleitung verfügbar sein sollen. Fügen Sie sowohl das BindingResult als auch das Objekt hinzu, das Sie zum Validieren verwenden, in diesem Fall Register.

Für BindingResult verwenden Sie den Namen: "org.springframework.validation.BindingResult. [Name Ihres ModelAttribute]]".

Für das Objekt, das Sie zur Überprüfung verwenden, verwenden Sie den Namen von ModelAttribute.

Um RedirectAttributes verwenden zu können, müssen Sie dies in Ihre Konfigurationsdatei einfügen. Unter anderem fordern Sie Spring dazu auf, einige neuere Klassen zu verwenden: 

<mvc:annotation-driven />

Jetzt werden die Fehler angezeigt, wo immer Sie umleiten

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) {

if (binding.hasErrors()) {
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding);
    attr.addFlashAttribute("register", register);
    return "redirect:/register/create";
}

return "redirect:/register/success";
}
65
Oscar

Wenn Sie dieser RedirectAttributes-Methode folgen, sollten Sie nicht nur vergessen, dass Sie die modelAttribute tatsächlich an die weitergeleitete Seite übergeben. Dies bedeutet, wenn Sie eine neue Instanz dieses modelAttribute für die umgeleitete Seite (in einem Controller) erstellen, Sie verlieren die Validierungsfehler Wenn also Ihre POST Controller-Methode in etwa so aussieht:

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) {

if (binding.hasErrors()) {
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding);
    attr.addFlashAttribute("register", register);
    return "redirect:/register/create";
}

return "redirect:/register/success";
}

Dann müssen Sie wahrscheinlich eine Änderung in Ihrem Register vornehmen und die Seite GET Controller erstellen. Davon:

@RequestMapping(value = "/register/create", method = RequestMethod.GET)
public String registerCreatePage(Model model) {
    // some stuff
    model.addAttribute("register", new Register());
    // some more stuff
}

zu

@RequestMapping(value = "/register/create", method = RequestMethod.GET)
public String registerCreatePage(Model model) {
    // some stuff
    if (!model.containsAttribute("register")) {
        model.addAttribute("register", new Register());
    }
    // some more stuff
}

Quelle: http://gerrydevstory.com/2013/07/11/preservation-error-messages-on-spring-mvc-form-post-redirect-get/

52
Utku Özdemir

Ich würde fragen, warum Sie die Weiterleitung brauchen. Warum nicht einfach die gleiche URL einreichen und auf einen POST anders reagieren? Dennoch, wenn Sie das wirklich wollen:

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(
    @ModelAttribute("register") @Valid final Register register,
    final BindingResult binding,
    HttpSession session) {

    if (binding.hasErrors()) {
        session.setAttribute("register",register);
        session.setAttribute("binding",binding);
        return "redirect:/register/create";
    }

    return "redirect:/register/success";
}

Dann in Ihrer "create" -Methode:

model.put("register",session.getAttribute("register"));
model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));
1
rjsang

Die einzige Möglichkeit, Objekte zwischen Anforderungen bestehen zu lassen (dh eine Umleitung), besteht darin, das Objekt in einem Sitzungsattribut zu speichern. Sie würden also "HttpServletRequest request" in die Methodenparameter für beide Methoden (dh "get" und "post") aufnehmen und das Objekt über request.getAttribute ("binding") abrufen. Das heißt, und nachdem Sie es nicht selbst ausprobiert haben, müssen Sie möglicherweise herausfinden, wie Sie die Bindung erneut an das Objekt in der neuen Anforderung binden. 

Eine andere "unansehnlichere" Methode besteht darin, die Browser-URL einfach mit Javascript zu ändern

1
klonq

Das Problem ist, dass Sie zu einem neuen Controller umleiten, anstatt die Ansicht zu rendern und die verarbeitete Formularseite zurückzugeben. Sie müssen etwas im Sinne von tun:

String FORM_VIEW = wherever_your_form_page_resides

...

if (binding.hasErrors())
    return FORM_VIEW;

Ich würde die Pfade außerhalb von Methoden wegen Code-Duplizierung von Strings halten.

1
Lewis

Ich kenne das genaue Problem mit Google App Engine nicht, aber die Verwendung des ForwardedHeaderFilter kann dazu beitragen, das vom Client verwendete ursprüngliche Schema zu erhalten. Dieser Filter wurde in Spring Framework 4.3 hinzugefügt, aber einige Servlet-Container bieten ähnliche Filter. Der Filter ist autark, sodass Sie bei Bedarf auch nur die Quelle abrufen können.

0