30 votes

Spring MVC Controller redirect en utilisant des paramètres d'URL au lieu de la réponse

J'essaie d'implémenter des urls RESTful dans mon application Spring MVC. Tout va bien sauf la gestion des soumissions de formulaires. J'ai besoin de rediriger soit vers le formulaire original, soit vers une page "succès".

@Controller
@RequestMapping("/form")
public class MyController {

    @RequestMapping(method = RequestMethod.GET)
    public String setupForm() {
        // do my stuff
        return "myform";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(ModelMap model) {            
        // process form data

        model.addAttribute("notification", "Successfully did it!");
        return "redirect:/form";
    }
}

Cependant, comme je l'ai lu dans le Documentation sur le printemps Si vous redirigez, tous les paramètres seront placés dans l'url. Et cela ne fonctionne pas pour moi. Quel serait le moyen le plus gracieux de contourner ce problème ?

22voto

Mat Points 726

J'ai eu le même problème et je l'ai résolu comme suit :

return new ModelAndView("redirect:/user/list?success=true");

Ma méthode de contrôle ressemble alors à ceci :

public ModelMap list(@RequestParam(required=false) boolean success) {
    ModelMap mm = new ModelMap();
    mm.put(SEARCH_MODEL_KEY, campaignService.listAllCampaigns());
    if(success)
        mm.put("successMessageKey", "campaign.form.msg.success");
    return mm;
}

Cela fonctionne parfaitement, sauf si vous voulez envoyer des données simples, pas des collections par exemple. Dans ce cas, il faut utiliser la session.

8voto

matt b Points 73770

Vous pouvez avoir processForm() renvoie un objet View à la place, et lui fait renvoyer le type concret RedirectView qui comporte un paramètre pour setExposeModelAttributes() .

Lorsque vous renvoyez un nom de vue précédé du préfixe "redirect:" Spring MVC le transforme en RedirectView de toute façon, il le fait simplement avec setExposeModelAttributes à true (ce qui me semble être une valeur étrange par défaut).

7voto

predhme Points 1377

http://jira.springframework.org/browse/SPR-6464 m'a fourni ce dont j'avais besoin pour faire fonctionner les choses jusqu'à ce que Spring MVC offre la fonctionnalité (potentiellement dans la version 3.0.2). Bien que j'aie simplement implémenté les classes qu'ils ont temporairement et ajouté le filtre au contexte de mon application web. Cela fonctionne très bien !

6voto

MatCarey Points 589

Ce problème est dû (comme d'autres l'ont indiqué) à la persistance des attributs du modèle dans la chaîne de requête - ce qui n'est généralement pas souhaitable et risque de créer des failles de sécurité ainsi que des chaînes de requête ridicules. Ma solution habituelle est de ne jamais utiliser de chaînes de caractères pour les redirections dans Spring MVC, mais plutôt d'utiliser une RedirectView qui peut être configurée pour ne pas exposer les attributs du modèle (voir : http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html )

RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes)

J'ai donc tendance à utiliser une méthode util qui effectue une "redirection sûre", comme par exemple :

public static RedirectView safeRedirect(String url) {
    RedirectView rv = new RedirectView(url);
    rv.setExposeModelAttributes(false);
    return rv;
}

L'autre option consiste à utiliser le XML de configuration des haricots :

<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView">
   <property name="exposeModelAttributes" value="false" />
   <property name="url" value="/myRedirect"/>
</bean>

Encore une fois, vous pouvez abstraire ceci dans sa propre classe pour éviter les répétitions (par exemple, SafeRedirectView).


Une remarque à propos de "l'effacement du modèle" - ce n'est pas la même chose que de "ne pas exposer le modèle" dans toutes les circonstances. Un site sur lequel j'ai travaillé comportait de nombreux filtres qui ajoutaient des éléments au modèle, ce qui signifiait que l'effacement du modèle avant la redirection n'empêcherait pas l'apparition d'une longue chaîne de requête. Je dirais également que "ne pas exposer les attributs du modèle" est une approche plus sémantique que "effacer le modèle avant de rediriger".

4voto

Jacob Mattison Points 32137

Si vous ne souhaitez pas que le message de réussite figure dans l'URL, vous pouvez le placer dans la session (dans la méthode processForm), puis le vérifier (et le supprimer) dans la méthode setupForm.

J'ai ajouté : si c'est pénible à faire manuellement, vous pourriez écrire une sous-classe de RedirectView qui ajouterait un attribut "message" et intégrerait le processus d'insertion de ce message dans la session. Par contre, je ne suis pas sûr qu'il y ait un moyen facile de récupérer le message hors de la session...

Honnêtement, je ne pense pas qu'il y ait une réponse facile - la nature d'une redirection HTTP est que l'état n'est pas transféré ; si vous voulez maintenir l'état de toute façon, vous êtes coincé avec les différentes façons habituelles de maintenir l'état dans les applications web : la session, un cookie, une chaîne de requête...

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