2010-01-26 15 views
8

Actualmente estamos agregando algunas características nuevas a una aplicación web antigua que estaba utilizando solo JSP sin ningún marco para el frente. Recientemente hemos agregado Spring y nos gustaría conectar automáticamente nuestros beans en nuestro JSP modificado, sin reescribir todo para usar SpringMVC, Struts2 o Tapestry5.¿Cuál es la forma más limpia de conectar automáticamente Spring Beans en un JSP?

Estamos utilizando autowiring por tipo, por lo que lleva a conseguir un poco de código como este en el JSP, al obtener previamente el contexto de aplicaciones web (como "wap"):

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

no Quisiéramos para usar dicho código, sino que automáticamente inyecte nuestros beans directamente en nuestros JSP como lo haríamos en un enterprise bean usando @Autowired annotation.

De hecho, estamos buscando las formas más limpias de inyectar nuestros granos en nuestros JSP. Que usas ?

+0

lo bueno de SpringMVC es que usted no tiene que tragar la pastilla entera. Puedes elegir las partes de la primavera que quieras usar. Probablemente sería más limpio hacer lo que Stephen C indicó y comenzar a refactorizar. – SWD

Respuesta

9

Puede utilizar ContextExposingHttpServletRequest de primavera:

HttpServletRequest decorador que hace que todos los granos de primavera en un determinado WebApplicationContext accesible como atributos solicitud, a través de perezoso comprobar una vez un atributo se acceder.

esto requeriría el código de controlador para envolver el original HttpServletRequest en un ContextExposingHttpServletRequest, y luego hacia adelante que al JSP. Puede exponer beans con nombre específico, o cada bean en el contexto.

Por supuesto, esto simplemente cambia el problema de sus JSP a su código de controlador, pero ese es quizás un problema más manejable.

+1

¿Qué piensas acerca de cambiar esto a un filtro (en lugar de un servlet) sobre JSP que obtienen todos los beans del contexto Spring y ponerlos en el ámbito de solicitud, nombrado por la interfaz esperada para tener un getByType similar? – temsa

+1

Buena idea, debería funcionar – skaffman

+0

(+1) Buena captura con la solicitud de envoltura. todavía, '@ Autowired' no será utilizable de esa manera? – Bozho

7

No puede usar @Autowired directamente porque el servlet conainer crea una instancia de sus jsps y servlets. Por lo tanto, no son parte del contexto de primavera y, por lo tanto, sus dependencias no se inyectan.

Puede:

  1. movimiento todo el código que a los servlets puros, en lugar de en las páginas JSP - dejar única presentación en las páginas JSP.
  2. uso @Configurable en sus servlets (y añadir un javaagent, como se describe en los documentos vinculados)

Otra forma, es hacer que la parte servlet del contexto actual manualmente. Esto es posible en tanto JSP y servlets:

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

    AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory(); 

    bf.autowireBean(this); 
} 

Esto resolverá las dependencias @Autowired anotados.

Ahora, no estoy seguro de si se requieren contenedores servlet para usar una sola instancia de de una clase servlet. Si no, será mejor que coloque el código anterior en un método getter para la dependencia (getDao()) y si la propiedad @Autowired es null (es decir, el contenedor usa otra instancia de la clase servlet) - realice la operación anterior.


Dicho todo esto, realmente considerar el uso de un framework de desarrollo web (cualquiera de los que en la lista). Tener lógica en jsps es completamente incorrecta, difícil de admitir, difícil de leer, etc.

+1

Lo sé definitivamente, pero usted puede Reescribe un software completo en 5 días (incluida la división de la lógica frontal y comercial), al tiempo que agrega nuevas funciones. De hecho, deberíamos evitar usar el DAO allí y escribir y luego confiar solo en el objeto comercial también, pero esto es solo un código ya escrito que no puedo reescribir en tan poco tiempo. Convencer a los gerentes para que conviertan la aplicación a Spring/Hibernate/Jpa en lugar de los singleton caseros y las herramientas ORM creadas por la empresa ya era un gran problema. Solo ven eso como un costo ... – temsa

4

Dudo que haya una manera limpia de inyectar dependencias en un JSP.

Creo que la solución limpia sería comenzar a refactorizar su código para obtener la lógica comercial de los JSP, utilizando SpringMVC o una de las alternativas que citó.

Comience con uno o más controladores minimalistas que simplemente pasan la solicitud a los JSP con los beans inyectados como atributos; La respuesta de @ skaffman le da una forma de hacerlo, o puede hacerlo de manera más selectiva. A continuación, migre progresivamente el código de los JSP a los controladores.

5

¿Qué pasa con anulando método jspInit() y la adición de soporte 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); %> 
Cuestiones relacionadas