10
votes

Population modèle complexe de Spring MVC de plusieurs sources

Eh bien, ma question peut sembler un peu floue, mais ici, c'est de toute façon. Je construis une application Web à l'aide du ressort MVC 3.1.M1, JSP 2.1 (sans tuiles, j'utilise des fichiers de tags JSP unis pour composer mes dispositions).

Fondamentalement, mes pages sont construites à l'aide de dispositions de certaines parties communes - en-tête, pied de page, bannière, menu, etc. La plupart de ces pièces sont dynamiques, c'est-à-dire contenir des informations connexes actuelles de l'utilisateur.

JSP n'a pas de notion "composante", je ne peux donc pas définir une partie de mon modèle et son code Java support à un endroit, couplé ensemble. Dans mes @Controlers, je dois remplir mon modèle, y compris des données pour en-tête, pied de page, menu et autres choses. Ce que je veux vraiment faire, c'est éviter cette duplication de code. La classe Abstract Basecontroller avec certaines méthodes de population de modèles génériques n'a pas l'air bien aussi.

JSP et Spring MVC sont très souvent utilisés ensemble, donc je m'attends à ce que certaines pratiques existent sur ce sujet. Permet de discuter de cela.


3 commentaires

Dans votre JSP, on dirait que vous avez plus d'un objet modèle, correct?


Eh bien, c'est un sujet à discuter. Actuellement, j'ai 1 objet modèle, mais je peux la diviser en deux ou plus si cela m'aide à supprimer la duplication de code et à obtenir une architecture simple.


@MKORYAK @ O-RICHIE-NAL J'ai trouvé un bel article sur ce sujet DIFFORDEVEVÉLOPIEL.WordPress.com/2008/02/28/... . Il est relativement vieux et couvre un cas plus simple (données de référence à l'échelle de l'application, mais pas à l'échelle de la mise en page ou à l'échelle de la composante), mais toujours très utile.


5 Réponses :


1
votes

Eh bien, vous avez plusieurs options, bien qu'ils ne soient pas parfaits non plus ..

  1. contrôleur abstrait comme vous avez mentionné
  2. Créer un service qui vous retournera les données de modèle .. Maintenant, vous avez déplacé le problème dans la couche de service où il n'appartient sans doute pas, mais au moins vos contrôleurs peuvent simplement effectuer un appel de service lors de chaque méthode du contrôleur.
  3. Créez un filtre et remplissez les parties communes du modèle dans le filtre.
  4. Vous pouvez probablement créer du monstre avec des annotations, par exemple, annotant les méthodes de contrôleur, puis poster les procédés des objets du contrôleur pour injecter les données (ceci, je ne sais pas comment faire exactement, mais il doit y avoir un moyen)
  5. Spring AOP pourrait être capable de vous aider à faire # 4 plus gracieusement

    Ce ne sont que quelques idées pour obtenir une discussion sur


1 commentaires

Cool, la discussion a commencé. J'ai des informations aussi après la lecture de la référence de Spring MVC entier ce soir, l'ajoutez demain.



4
votes

Le Springframework contient des intercepteurs de gestionnaire dans le cadre du mécanisme de cartographie du gestionnaire.
Dans l'intercepteur, vous pouvez utiliser la méthode posthandle avant que le gestionnaire réel soit exécuté.

Un tel intercepteur doit implémenter le org.springframework.web.servlet.handlerinterceptor ou le org.springframework.web.servlet.handler.handlerinterceptorAdapter Pour une implémentation simplifiée. xxx

et la configuration de la cartographie du gestionnaire. < Pré> xxx


2 commentaires

Merci pour la réponse, O-Richie! Mais que se passe-t-il si j'ai quelques mises en page - certains avec menu, certains sans et veulent peupler le modèle avec des données de menu uniquement lorsque ma page en a besoin?


Le paramètre du gestionnaire contient le gestionnaire exécuté ou vous pouvez utiliser la demande.GetRequeri () pour obtenir l'URL demandée.



4
votes

OK, j'ai donc passé du temps avec les applications de référence et d'échantillonnage du printemps MVC, et j'ai trouvé des moyens supplémentaires d'accomplir ma mission. Ici, ils sont:

1) Numéro un, mauvais et inutilisable, juste à mentionner ici. Abstract BaseController avec des méthodes telles que populationheaderData (modèle modèle), populationfooterdata (modèle modèle) et ainsi de suite. Toutes les méthodes @RequestMapping dans toutes les classes de contrôleur qui prolongent le basocontrôleur appellent ces méthodes pour remplir des données de modèle spécifiques à la mise en page.

Avantages:

: la duplication de code reste la même, mais la quantité de code dupliqué est réduite

2) @modelattribute méthodes, c'est-à-dire un élément implicite enrichissement. Ressemble à xxx

et en jsp, xxx

les pros: pas besoin d'appeler modèle Méthodes d'enrichissement explicitement - cela fonctionne simplement

contre: c'est une chose délicate ici. Spring MVC utilise le modèle de modèles "Push" au lieu de "tirer". Ce que cela signifie dans ce cas est que lorsque l'une des méthodes de @RequestMapping, définies dans cette classe, est appelée, toutes les méthodes @Modelattribute de cette classe sont invoquées. Il n'y a pas de différence si le modèle a vraiment besoin de visitorname et si le modèle existe réellement pour une action spécifique. Cela inclut des demandes postales de soumission de formulaire, etc. En fait, cette forces nous pour modifier la séparation des contrôleurs. Par exemple, toutes les soumissions de formulaire doivent être dans des classes de contrôleur distinctes et des méthodes de manutention doivent être groupées d'une manière ou d'une autre. Je dois en penser plus à ce sujet, peut-être que ce n'est pas si mauvais comme il a l'air de premier coup d'œil.

Plus de contre: Supposons que nous ayons des mises en page A et B avec le même non statique En-tête, et B et C avec le même pied de page non statique (toutes les autres parties sont différentes). Nous ne pouvons pas implémenter la classe de base pour la mise en page B, car il n'y a pas de héritage multiple dans Java.

question au public: Spring MVC Références States "Les types de retour suivants sont pris en charge pour les méthodes de manutention: un objet ModelandView, avec le modèle implicitement enrichi d'objets de commande et des résultats de @modelattribute des méthodes d'accessoir de référence annotées ...". Qu'est-ce que ces objets de commande sont?

3) ma propre méthode de type traction. Nous pouvons créer des contextes personnalisés sous une forme de xxx

puis, exposez ces haricots à JSP el via xxx

et dans Header.tag (fichier d'étiquette JSP pour en-tête réutilisé) xxx

les pros: "Tirez" STRATY (personne ne demande - rien n'est exagéré), facile à Faire des contextes @scope ("Demande") et activer la mise en cache à l'échelle de la demande, aucun problème avec plusieurs héritage. Juste codé dans un endroit, configuré en un seul endroit et peut être utilisé dans n'importe quel fichier JSP ou Tag comme une expression habituelle.

contre: mélange de poussée et tirez dans un cadre ( Doit en penser plus à ce sujet), aucun support de printemps MVC dans les classes de mise en œuvre de contexte (je veux dire ces arguments prépopulés méchants dans des méthodes de manutention contrôleur), juste des haricots de printemps.


2 commentaires

Les objets de commande sont des paramètres de demande (après la conversion implicite) qui sont des arguments sur le contrôleur. je pense.


Vous pouvez également appeler directement le service à partir de votre JSP: Bienvenue, $ {visiteursservice.Visitorname}! . Je fais tout cela tout le temps, illocule uniquement des attributs de modèle dans le contrôleur qui sont calculés à la suite de la saisie de l'utilisateur.



2
votes

Enfin, j'ai décidé de coller avec une approche @modelattribute, malgré ses limitations.

/**
 * Base class for all page controllers (i.e., not form submits)
 * @author malexejev
 * 23.03.2011
 */
public abstract class AbstractPageController {

    @Autowired
    private VisitorService visitorService;

    @Autowired
    private I18nSupport i18nSupport;

    @Value("${xxx.env}")
    private String environment;

    /**
     * Implicit model enrichment with reference data.
     * No heavy operations allowed here, since it is executed before any handler method of 
     * all extending controllers
     */
    @ModelAttribute("appContext")
    public Map<String, Object> populateReferenceData(HttpServletRequest request) {
        Map<String, Object> dataMap = new HashMap<String, Object>();

        // FIXME some data is app-wide and constant, no need to re-create such map entries
        // I should take care about it when more reference data is added
        dataMap.put("visitorName", visitorService.getVisitorName());
        dataMap.put("env", environment);
        dataMap.put("availableLanguages", i18nSupport.getAvailableLanguages());
        dataMap.put("currentPath", request.getPathInfo() != null ? request.getPathInfo() : request.getServletPath());

        return Collections.unmodifiableMap(dataMap);
    }

}


0 commentaires

0
votes

Intercepteur de gestionnaire convient aux données partagées qui sont utilisées dans chaque page.

Si vous voulez des "composants" grains fins, vous devez vraiment reconsidérer à l'aide de tuiles Apache. De là, vous pouvez utiliser un "contrôleur" ( ViewPreeparer ) Pour chaque tuile comme indiqué ici:

http://richardbarabe.wordpress.com / 2009/02/19 / Apache-Tiles-2-ViewPreeparer-Exemple /


0 commentaires