web-dev-qa-db-fra.com

Redirection du contrôleur MVC Spring en utilisant des paramètres d'URL au lieu de répondre

J'essaie d'implémenter des URL RESTful dans mon application Spring MVC. Tout va bien sauf le traitement des soumissions. J'ai besoin de rediriger le formulaire d'origine ou 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 Spring , si vous redirigez des paramètres, ils seront mis dans l'URL. Et ça ne marche pas pour moi. Quelle serait la manière la plus élégante de contourner cela?

39
user130532

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 cette 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 à mon contexte d'application Web. Fonctionne très bien!

7
user130532

J'ai eu le même problème. résolu comme ça:

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

Et puis ma méthode de contrôleur ressemble à 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;
}

Fonctionne parfaitement sauf si vous souhaitez envoyer des données simples, pas des collections, par exemple. Ensuite, vous devrez utiliser la session, je suppose.

34
Mat

Ce problème est causé (comme d'autres l'ont déjà indiqué) par la persistance d'attributs de modèle dans la chaîne de requête. Ceci est généralement indésirable 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 les chaînes pour les redirections dans Spring MVC, mais d'utiliser un RedirectView qui peut être configuré pour ne pas exposer les attributs de 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écurisée" comme:

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 de bean:

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

Là encore, vous pouvez résumer cela dans sa propre classe pour éviter les répétitions (par exemple, SafeRedirectView).


Une remarque sur "effacer le modèle" - cela ne signifie pas "ne pas exposer le modèle" dans toutes les circonstances. Un site sur lequel j'ai travaillé avait de nombreux filtres qui ajoutaient des éléments au modèle. Cela signifiait qu'effacer le modèle avant la redirection n'empêcherait pas une longue chaîne de requête. Je suggérerais également que "ne pas exposer les attributs du modèle" est une approche plus sémantique que "effacer le modèle avant la redirection".

11
MatCarey

Vous pouvez également demander à processForm() de renvoyer un objet View et de lui renvoyer le type concret RedirectView, qui possède un paramètre pour setExposeModelAttributes().

Lorsque vous renvoyez un nom de vue préfixé par "redirect:" _, Spring MVC transforme cela en un objet RedirectView de toute façon, il le fait simplement avec setExposeModelAttributes en true (ce qui, à mon avis, est une valeur étrange à utiliser par défaut).

8
matt b

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

Modifié pour ajouter: si cela est difficile à faire manuellement, vous pouvez écrire une sous-classe de RedirectView qui ajoute un attribut "message" et encapsule le processus de son insertion dans la session. Pas sûr, cependant, s'il existe un moyen facile de résumer le message 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 cet état n'est pas reporté; de toute façon, si vous souhaitez conserver l’état, vous devez utiliser les différentes méthodes habituelles de maintien de l’état dans les applications Web: la session, un cookie, une chaîne de requête ...

4
Jacob Mattison

Hé, vous pouvez juste faire une chose simple au lieu d'utiliser model pour envoyer un paramètre, utilisez l'objet HttpServletRequest et faites ceci

HttpServletRequest request;
request.setAttribute("param", "value")

maintenant vos paramètres ne seront pas montrés dans votre entête d'URL espérons que cela fonctionne :)

3
Sudhanshu Gaur
@RequestMapping(path="/apps/add", method=RequestMethod.POST)
public String addApps(String appUrl, Model model, final RedirectAttributes redirectAttrs) {
    if (!validate(appUrl)) {
       redirectAttrs.addFlashAttribute("error", "Validation failed");
    }
    return "redirect:/apps/add"
} 

@RequestMapping(path="/apps/add", method=RequestMethod.GET)
public String addAppss(Model model) {
    String error = model.asMap().get("error");
}
1
Anton