2010-01-26 11 views
8

Nous sommes en train d'ajouter de nouvelles fonctionnalités à une ancienne webapp qui n'utilisait que JSP sans framework pour le front. Nous avons ajouté Spring récemment, et nous aimerions autowire nos beans dans notre JSP modifiée, tout en ne réécrivant pas tout pour utiliser SpringMVC, Struts2 ou Tapestry5.Quelle est la manière la plus propre d'autowire Spring Beans dans un JSP?

Nous utilisons autowiring par type, il conduit à obtenir un code comme celui-ci dans la JSP, tout en obtenant au préalable le contexte d'application Web (comme « wap »):

MyDao myDao = (MyDao) wap.getBeansOfType(MyDao.class).values().toArray()[0]; 

Nous voudrions pas pour utiliser un tel code, mais plutôt automagiquement injecter nos beans directement dans nos JSP comme nous le ferions dans un business bean en utilisant l'annotation @Autowired.

En fait, nous cherchons les moyens les plus propres d'injecter nos beans dans nos JSP. Qu'est ce que tu utilises ?

+0

la bonne chose à propos SpringMVC est que vous n'avez pas à avaler la pilule entière. Vous pouvez choisir les parties du ressort que vous souhaitez utiliser. Il serait probablement plus propre de faire ce que Stephen C a indiqué et commencer à refactoriser. – SWD

Répondre

9

Vous pouvez utiliser ContextExposingHttpServletRequest de printemps:

HttpServletRequest décorateur qui fait que tous les grains de printemps dans une donnée WebApplicationContext accessible demande attributs, par paresseux vérifier une fois un attribut obtient accédée.

Cela nécessiterait votre code de contrôleur pour envelopper le HttpServletRequest d'origine dans un ContextExposingHttpServletRequest, puis vers l'avant que à la JSP. Il peut soit exposer des beans nommés spécifiques, soit chaque bean dans le contexte.

Bien sûr, cela ne fait que déplacer le problème de vos JSP vers le code de votre contrôleur, mais c'est peut-être un problème plus gérable.

+1

Que pensez-vous de changer cela en un filtre (plutôt qu'une servlet) sur les JSP qui récupèrent tous les beans du contexte Spring et les placent dans la portée de la requête, nommés par l'interface attendue afin d'avoir un simili getByType? – temsa

+1

Bonne idée, devrait fonctionner – skaffman

+0

(+1) Belle prise avec l'application-wrapper. toujours, '@ Autowired' ne sera pas utilisable de cette façon? – Bozho

7

Vous ne pouvez pas utiliser @Autowired directement parce que vos jsps et servlets sont instanciés par le Confiner de servlet. Donc, ils ne font pas partie du contexte du printemps et donc leurs dépendances ne sont pas injectés.

Vous pouvez:

  1. déplacer tout le code qui à servlets pur, plutôt que dans jsps - laisser la présentation que dans les pages JSP.
  2. utilisation @Configurable sur vos servlets (et ajouter un javaagent, tel que décrit dans les documents liés)

Une autre façon, est de faire la partie servlet du contexte actuel manuellement. Ceci est possible dans les deux jsps et servlets:

public void init() { 
    WebApplicationContext ctx = WebApplicationContextUtils 
     .getRequiredWebApplicationContext(getServletContext()); 

    AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory(); 

    bf.autowireBean(this); 
} 

Cela permettra de résoudre les @Autowired dépendances annotées.

Maintenant, je ne suis pas sûr que les conteneurs de servlet doivent utiliser une seule instance d'une classe de servlet. Sinon, il vaut mieux placer le code ci-dessus dans une méthode getter pour la dépendance (getDao()) et si la propriété @Autowired est null (c'est-à-dire qu'une autre instance de la classe servlet est utilisée par le conteneur) - effectuez l'opération ci-dessus.


Que tous dit, vraiment envisager d'utiliser un framework web (l'un de ceux que vous avez énumérés). Avoir une logique dans jsps est complètement faux, difficile à supporter, difficile à lire, etc.

+1

Je le sais, mais vous pouvez Ne pas réécrire un logiciel complet en 5 jours (y compris la division du front et de la logique métier), tout en ajoutant de nouvelles fonctionnalités. En fait, nous devrions éviter d'utiliser le DAO là-bas et écrire, puis compter uniquement sur l'objet métier, mais ce n'est que du code déjà écrit que je ne peux pas réécrire en si peu de temps. Convaincre les managers de convertir l'application en Spring/Hibernate/Jpa au lieu des singletons faits maison et des outils ORM de l'entreprise était déjà une grande source de souffrance. Ils ne voient que cela comme un coût ... – temsa

4

Je doute qu'il existe un moyen propre d'injecter des dépendances dans une JSP.

Je pense que la solution propre serait de commencer à refactoriser votre code pour obtenir la logique métier des JSP, en utilisant SpringMVC ou l'une des alternatives que vous avez citées. Commencez avec un ou plusieurs contrôleurs minimalistes qui transmettent simplement la requête aux JSP avec les beans injectés en tant qu'attributs; @ réponse de Skaffman donne une façon de le faire, ou vous pourriez le faire plus sélectivement. Ensuite, migrez progressivement le code des JSP vers les contrôleurs.

5

Qu'en est primordial méthode jspInit() et ajouter le support Autowiring:

<%@ page import="com.example.ExampleService"%> 
<%@ page import="org.springframework.beans.factory.annotation.Value"%> 
<%@ page import="org.springframework.beans.factory.annotation.Autowired"%> 
<%@ page import="org.springframework.web.context.support.SpringBeanAutowiringSupport"%> 
<%! 
    public void jspInit() 
    { 
     SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, 
     getServletContext()); 
    } 

    @Value("${example.property}") 
    private String someField; 

    @Autowired 
    private ExampleService exampleService; 
%> 

<% final Object data = exampleService.getSomething(someField); %>