56 votes

Comment empêcher les variables @ModelAttribute de Spring 3.0 MVC d'apparaître dans les URL ?

En utilisant Spring MVC 3.0.0.RELEASE, j'ai le contrôleur suivant :

@Controller
@RequestMapping("/addIntake.htm")
public class AddIntakeController{

  private final Collection<String> users;

  public AddIntakeController(){
    users = new ArrayList<String>();
    users.add("user1");
    users.add("user2");
    // ...
    users.add("userN");
  }

  @ModelAttribute("users")
  public Collection<String> getUsers(){
    return this.users;
  }

  @RequestMapping(method=RequestMethod.GET)
  public String setupForm(ModelMap model){

    // Set up command object
    Intake intake = new Intake();
    intake.setIntakeDate(new Date());
    model.addAttribute("intake", intake);

    return "addIntake";
  }

  @RequestMapping(method=RequestMethod.POST)
  public String addIntake(@ModelAttribute("intake")Intake intake, BindingResult result){

    // Validate Intake command object and persist to database
    // ...

    String caseNumber = assignIntakeACaseNumber();

    return "redirect:intakeDetails.htm?caseNumber=" + caseNumber;

  }

}

Le contrôleur lit les informations d'admission à partir d'un objet de commande rempli à partir d'un formulaire HTML, valide l'objet de commande, fait persister les informations dans la base de données et renvoie un numéro de cas.

Tout fonctionne parfaitement, sauf que lorsque je redirige vers la page intakeDetails.htm, j'obtiens une URL qui ressemble à ceci :

http://localhost:8080/project/intakeDetails.htm?caseNumber=1&users=user1&users=user2&users=user3&users=user4...

Comment empêcher la collection de l'utilisateur d'apparaître dans l'URL ?

38voto

sideways Points 256
model.asMap().clear();
return "redirect:" + news.getUrl();

:)

30voto

elaich Points 337

Depuis le printemps de 3.1 RequestMappingHandlerAdapter fournit un indicateur appelé ignoreDefaultModelOnRedirectque vous pouvez utiliser pour empêcher l'utilisation du contenu de la defautl modèle si le contrôleur de redirections.

18voto

skaffman Points 197885

L' @ModelAttribute méthode d'annotation est destiné à être utilisé pour exposer les données de référence pour la couche vue. Je ne peux pas dire pour sûr que dans ton cas, mais je ne dirais pas qu'une collection d'utilisateurs qualifiés que les données de référence. Je vous propose de vous transmettre cette information à travers le modèle de manière explicite dans votre @RequestMapping-annotée des méthodes de gestionnaire.

Si vous voulez toujours utiliser @ModelAttribute, il y a un blog d'entrée ici qui traite le problème de redirection.

Mais tous les exemples précédents ont un problème commun, comme tous @ModelAttribute les méthodes sont exécutées avant que le gestionnaire est exécuté, si le gestionnaire renvoie une rediriger le modèle les données seront ajoutées pour l'url sous la forme d'une chaîne de requête. Cette devrait être évitée à tout prix car il pourrait exposer quelques secrets sur la façon dont vous ont mis ensemble votre demande.

Sa proposition de solution (voir la partie 4 de ce blog) est d'utiliser un HandlerInterceptorAdapter pour rendre le commun des données de référence visible à l'affichage. Depuis les données de référence ne devrait pas être étroitement associé aux contrôleurs, cela ne devrait pas poser de problème, conception-sage.

18voto

axtavt Points 126632

Il n'existe pas de bonnes façons de résoudre ce problème (c'est-à-dire sans créer de composants personnalisés, sans une quantité excessive de configuration xml explicite et sans instanciation manuelle des éléments suivants RedirectView ).

Vous pouvez soit instancier RedirectView manuellement via son constructeur à 4 arguments, ou déclarez le bean suivant dans votre contexte (près des autres résolveurs de vues) :

public class RedirectViewResolver implements ViewResolver, Ordered {
    // Have a highest priority by default
    private int order = Integer.MIN_VALUE; 

    // Uses this prefix to avoid interference with the default behaviour
    public static final String REDIRECT_URL_PREFIX = "redirectWithoutModel:";     

    public View resolveViewName(String viewName, Locale arg1) throws Exception {
        if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
            String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
            return new RedirectView(redirectUrl, true, true, false);
        }
        return null;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }
}

5voto

kaliatech Points 8331

Je sais que cette question et cette réponse sont anciennes, mais je suis tombé dessus par hasard après avoir moi-même rencontré des problèmes similaires et je n'ai pas trouvé beaucoup d'autres informations.

Je pense que la réponse acceptée n'est pas très bonne. La réponse juste en dessous par axtavt est bien meilleure. La question n'est pas de savoir si l'annotation des attributs de modèle sur un contrôleur a du sens. Il s'agit de savoir comment émettre une redirection "propre" à partir d'un contrôleur qui utilise normalement les ModelAttributes. Le contrôleur lui-même requiert normalement les données de référence, mais parfois il a besoin de rediriger ailleurs pour des conditions exceptionnelles ou autre, et passer les données de référence n'a pas de sens. Je pense que c'est un modèle valide et commun.

(Pour info, j'ai rencontré ce problème de manière inattendue avec Tomcat. Les redirections ne fonctionnaient tout simplement pas et je recevais des messages d'erreur bizarres comme : java.lang.ArrayIndexOutOfBoundsException : 8192. J'ai fini par déterminer que la longueur maximale par défaut de l'en-tête de Tomcat est de 8192. Je n'avais pas réalisé que les ModelAttributes étaient ajoutés automatiquement à l'URL de redirection, et que cela faisait que la longueur de l'en-tête dépassait la longueur maximale de Tomcat).

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