====== Spring MVC ====== Entramos por fin en la parte del desarrollo de una aplicación web. Spring MVC es parte de la funcionalidad de Spring framework pero dedicada a la parte de los Servlets y JSP. Hemos elegido Spring MVC para la parte web por dos motivos: * Mejora el uso del API de Servlets pero sin estar muy alejados de ellos. Usar Spring MVC es como usar los Servlets pero con mejoras que nos hacen la vida mas fácil. En Spring en vez de usar Servlets usaremos clases Java llamadas controladores. * Se integra perectamente con la parte de Inyección de Dependencias de Spring. No vamos a entrar en detalles sobre cómo funciona Spring MVC sino que vamos a explicar lo mínimo para que se pueda usar Spring MVC. ===== Ficheros de configuración ===== Veamos ahora los ficheros que es necesario modificar/crear para poder usar Spring MVC ==== web.xml ==== Añadir al fichero ''web.xml'' el siguiente fragmento xml: org.springframework.web.context.ContextLoaderListener contextConfigLocation classpath:applicationContext.xml dispatcher org.springframework.web.servlet.DispatcherServlet 1 dispatcher *.html Este código XML hay que copiarlo tal cual está en el ''web.xml'' pero hay 2 líneas que pueden modificarse para personalizar la aplicación. * Línea 6: Vemos como se especifica el nombre del fichero de configuración de Spring. En este caso es el mismo que usamos en el tema anterior ''classpath:applicationContext.xml''. * Línea 16: Es el patrón que tendrán las URL para que se redireccionen a nuestros controladores de Spring. En nuestro caso , cualquier petición que acabe con ".html" será redirigida hasta los controladores definidos en Spring, pero podemos especificar cualquier patrón para nuestros controladores. En muchos tutoriales se pone como valor a '''' el valor de ''*.jsp''. Nunca se debe usar ese valor ya que se producirá un error puesto que no sabrá correctamente redireccionar desde los controladores a las páginas JSP de la vista. ==== dispatcher-servlet.xml ==== Se deberá crear el fichero ''dispatcher-servlet.xml'' en la carpeta ''/WEB-INF''. El contenido del mismo será el siguiente: Este código XML hay que copiarlo tal cual está en el ''dispatcher-servlet.xml'' pero hay 2 líneas que deben modificarse para personalizar la aplicación: * Línea 13: Se debe indicar el paquete donde se encuentran los controladores web. * Línea 16: Se indica dónde deben estar las páginas JSP a las que se redirecciona desde los controladores. Se ha elegido ''/WEB-INF/jsp/''.Normalmente este valor no es necesario modificarlo ya que las páginas JSP deberían estar dentro de la carpeta ''WEB-INF'' para que desde el navegador no se pueda tener acceso directo a ellas. Debe hacerse a través de los controladores. Recuerda modificar el tag '''' para indicar dónde se encuentra el paquete con los controladores web. ==== context.xml ==== Este fichero no tiene nada que ver con Spring MVC. El fichero se utiliza para configurar el javax.sql.DataSource que usará el [[patrones:pool_conexiones|pool de conexiones]]. Si no recuerdas que es el pool de conexiones se recomienda ver el tutorial [[patrones:pool_conexiones|pool de conexiones]]. ==== hibernate.cfg.xml ==== El fichero ''hibernate.cfg.xml'' es necesario modificarlo para indicarle a Hibernate que obtenga la conexiones a través del ''DataSource'' en vez de crearlas él directamente. java:/comp/env/jdbc/hibernate1 org.hibernate.dialect.MySQL5Dialect true Vemos en la línea 6 como se ha incluido la propiedad ''connection.datasource'' y se ha eliminado toda referencia a la base de datos. ==== applicationContext.xml ==== No es necesario modificar el fichero ''applicationContext.xml'' de configuración de Spring ===== SessionFactory e Hibernate ===== En las aplicaciones de escritorio vimos como se debía llamar a distintos métodos de ''HibernateUtil'' para gestionar el objeto ''SessionFactory''. En las aplicaciones Web debemos hacer lo mismo para lo que simplemente crearemos la clase Java ''HibernateContextListenerAndFilter'' @WebListener() @WebFilter(urlPatterns = {"*.html"}) public class HibernateContextListenerAndFilter implements Filter,ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { HibernateUtil.buildSessionFactory(); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { try { HibernateUtil.openSessionAndBindToThread(); filterChain.doFilter(servletRequest, servletResponse); } finally { HibernateUtil.closeSessionAndUnbindFromThread(); } } @Override public void destroy() { } @Override public void contextDestroyed(ServletContextEvent sce) { HibernateUtil.closeSessionFactory(); } } Esta clase se ejecutará al inicio y final de la aplicación y en cada petición web cuya URL tenga el patrón "''*.html''".Para conseguirlo se han añadido anotaciones de Java EE 6 Web ''@WebListener'' y ''@WebFilter'' No se va a explicar nada de Java EE 6 ya que está fuera del ámbito de este curso pero os dejo el [[http://docs.oracle.com/javaee/6/tutorial/doc/|Tutorial Java EE 6]] y concretamente sobre la anotación ''@WebListener'' en [[http://docs.oracle.com/javaee/6/tutorial/doc/bnafi.html|Servlet Lifecycle]] y sobre la anotación ''@WebFilter'' en [[http://docs.oracle.com/javaee/6/tutorial/doc/bnagb.html|Filtering Requests and Responses]] Lo que sí vamos a comentar son la líneas referidas a ''HibernateUtil'' que tiene ésta clase. * Línea 7: Al inicio de la aplicación web se inicializa Hibernate con la llamada a ''HibernateUtil.buildSessionFactory()'' * Línea 33: Al finalizar la aplicación web se cierra Hibernate con la llamada a ''HibernateUtil.closeSessionFactory()''. * Línea 18: Al inicio de la petición web se crea la sesión de Hibernate con la llamada a ''HibernateUtil.openSessionAndAttachToThread()'' * Línea 22: Al finalizar la petición web se destruye la sesión de hibernate con la llamada a ''HibernateUtil.closeSessionAndDeattachFromThread()'' Como vemos, el patrón utilizado con ''HibernateUtil'' es exactamente igual al usado en las aplicaciones de escritorio con lo que ha sido muy sencillo utilizar ''HibernateUtil'' en una aplicación web. Para que funcione la clase ''HibernateContextListenerAndFilter'' es necesario usar Tomcat 7 con la versión de Java EE 6 Web. Si se quisiera usar con con Java EE 5 se podría hacer eliminado las anotaciones y modificando el fichero ''web.xml'' {{:unidades:08_spring:tomcat7_javaee6.png?nolink|tomcat7_javaee6.png}} ==== web.xml ==== En vez de usar la anotaciones: @WebListener() @WebFilter(urlPatterns = {"*.html"}) Se puede modificar el web.xml añadiendo las siguientes líneas: com.fpmislata.persistencia.hibernate.HibernateContextListenerAndFilter HibernateContextListenerAndFilter com.fpmislata.persistencia.hibernate.HibernateContextListenerAndFilter HibernateContextListenerAndFilter *.html ====== Controllers ====== Ahora veamos las clases Java que usaremos como controladores en nuestra aplicación web. Estas clases son muy parecidas a los Servlets de Java EE pero más sencillas de usar. Recuerda que usamos estas clases gracias a que estamos usando el framework Spring MVC. Siguiendo la //moda// actual, no es necesario que los controladores en Spring MVC extiendan de ninguna otra clase ni que implementen ningún interfaz. Únicamente deben incluir la anotación ''@Controller'' la principio de la clase. @Controller public class ProfesorController { @Autowired private ProfesorDAO profesorDAO; @RequestMapping({"/index.html"}) public ModelAndView read(HttpServletRequest request, HttpServletResponse response) { Map model = new HashMap<>(); String viewName; try { Profesor profesor = profesorDAO.get(1001); model.put("texto", profesor.toString()); viewName = "profesor"; } catch (BussinessException ex) { model.put("msgError", "No es posible obtener los datos"); viewName = "error"; } return new ModelAndView(viewName, model); } } Pasemos ahora a explicar el código de controlador. Como ya hemos dicho lo principal que debe tener un controller de Spring MVC es la anotación ''@Controller'' al principio de la clase (Línea 1). Con ésto sabrá Spring MVC que es un controlador. ===== Manejo de peticiones ===== El manejo de peticiones web se realiza a través de los métodos del controlador. Cada método gestionará las peticiones de una o más URLs y puede haber tantos métodos como se desee. Ésto es una gran ventaja respecto a un Servlet ya que hace mucho más sencillo procesar una serie de URL relacionadas en un único controlador. Recuerda que en un Servlet había un único método para todas las peticiones. Cada método que controla peticiones Web tendrá la anotación ''@RequestMapping'' (Línea 7). Esta anotación tendrá como argumento un Array de Strings con todas las URLs que va a manejar. Por ello nótese que hay una llaves "''{ }''" antes y después del String de la URL que maneja ya que se permite más de una. Los argumentos de entrada del método son los objetos javax.servlet.http.HttpServletRequest|HttpServletRequest y javax.servlet.http.HttpServletResponse|HttpServletResponse al igual que en un Servlet. Spring MVC tiene muchas funcionalidades relativas las URL que controla, parametros de entrada y de salida.Aquí se han utilizado únicamente javax.servlet.http.HttpServletRequest|HttpServletRequest y javax.servlet.http.HttpServletResponse|HttpServletResponse para asemejarlos mas a los Servlets y no complicar el uso de Spring MVC pero se recomienda al programador ver todas las opciones que dispone Spring MVC. Mas información en [[http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-controller|16.3 Implementing Controllers]] El método retorna una clase de Spring MVC llamada org.springframework.web.servlet.ModelAndView|ModelAndView. Esta clase contendrá un String con la página jsp a mostrar ( es decir la Vista ) y un java.util.Map|Map con los datos que necesita la vista para mostrarse (es decir el Modelo). Podemos ver en la línea 22: return new ModelAndView(viewName, model); como se crea un nuevo objeto org.springframework.web.servlet.ModelAndView|ModelAndView que tiene como argumentos un String con el nombre de la página JSP a mostrar y el java.util.Map|Map con los datos para la vista. Recuerda que en el String con el nombre de la vista que se retorna en org.springframework.web.servlet.ModelAndView|ModelAndView no se debe incluir el sufijo ".jsp" ya que en el fichero ''dispatcher-servlet.xml'' , la línea 17 , ya se indica que se añadirá como sufijo el texto ".jsp". ====== La página JSP ====== Las páginas JSP se deben colocar en la carpeta ''WEB-INF/jsp'' tal y como se ha definido en el fichero ''dispatcher-servlet.xml'' , en la línea 16. La vista tiene acceso a los elementos del java.util.Map|Map del modelo que se creó en la clase org.springframework.web.servlet.ModelAndView|ModelAndView mediante el siguiente código: Object texto=request.getAttribute("texto"); Siendo el String ''"texto"'' la clave del java.util.Map|Map con la que se guardó el valor. Un ejemplo de página JSP es la siguiente: <%@page contentType="text/html" pageEncoding="UTF-8"%> <% Object texto=request.getAttribute("texto"); %> Profesor

<%=texto %>

Vemos en la línea 3 cómo se accede a los datos del modelo.