Herramientas de usuario

Herramientas del sitio


unidades:08_spring:03_spring_mvc
no way to compare when less than two revisions

Diferencias

Muestra las diferencias entre dos versiones de la página.


unidades:08_spring:03_spring_mvc [2023/04/07 21:26] (actual) – creado - editor externo 127.0.0.1
Línea 1: Línea 1:
 +====== 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:
 +<code xml 1 | Fragmento del web.xml>
 +<listener>
 +    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 +</listener> 
 +<context-param>
 +    <param-name>contextConfigLocation</param-name>
 +    <param-value>classpath:applicationContext.xml</param-value>
 +</context-param>    
 +
 +<servlet>
 +    <servlet-name>dispatcher</servlet-name> 
 +    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 +    <load-on-startup>1</load-on-startup> 
 +</servlet>
 +<servlet-mapping>
 +    <servlet-name>dispatcher</servlet-name> 
 +    <url-pattern>*.html</url-pattern>
 +</servlet-mapping>
 +</code>
 +
 +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.
 +
 +<note warning>
 +En muchos tutoriales se pone como valor a ''<url-pattern>'' 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.
 +</note>
 +
 +==== dispatcher-servlet.xml ====
 +Se deberá crear el fichero ''dispatcher-servlet.xml'' en la carpeta ''/WEB-INF''. El contenido del mismo será el siguiente:
 +
 +<code xml 1 | dispatcher-servlet.xml>
 +<?xml version="1.0" encoding="UTF-8"?> 
 +<beans xmlns="http://www.springframework.org/schema/beans"
 +       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 +       xmlns:context="http://www.springframework.org/schema/context" 
 +       xmlns:mvc="http://www.springframework.org/schema/mvc" 
 +       xsi:schemaLocation="
 +       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
 +       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
 +       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
 +">
 +
 +    <mvc:annotation-driven/> 
 +    <context:component-scan base-package="ejemplo02.presentacion" />
 +    
 +    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
 +        <property name="prefix" value="/WEB-INF/jsp/"/> 
 +        <property name="suffix" value=".jsp"/> 
 +    </bean> 
 +</beans>
 +</code>
 +
 +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.
 +
 +<note important>
 +Recuerda modificar el tag ''<context:component-scan>'' para indicar dónde se encuentra el paquete con los controladores web.
 +</note>
 +==== context.xml ====
 +Este fichero no tiene nada que ver con Spring MVC. El fichero se utiliza para configurar el <javadoc jdk7>javax.sql.DataSource</javadoc> que usará el [[patrones:pool_conexiones|pool de conexiones]].
 +
 +<note important>
 +Si no recuerdas que es el pool de conexiones se recomienda ver el tutorial [[patrones:pool_conexiones|pool de conexiones]].
 +</note>
 +
 +<code xml 1 | context.xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<Context antiJARLocking="true" path="/Ejemplo02">
 +    <Resource
 +        name="jdbc/hibernate1" 
 +        driverClassName="com.mysql.jdbc.Driver"
 +        url="jdbc:mysql://localhost:3306/hibernate1"
 +        username="hibernate1" 
 +        password="hibernate1"
 +        maxActive="100" 
 +        maxIdle="30" 
 +        maxWait="10000"
 +        auth="Container" 
 +        type="javax.sql.DataSource"
 +        validationQuery="SELECT 1 FROM dual"
 +     /> 
 +</Context>      
 +</code>
 +
 +
 +==== 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.
 +
 +
 +<code xml 1| hibernate.cfg.xml>
 +<?xml version="1.0" encoding="UTF-8"?>
 +<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 +<hibernate-configuration>
 +  <session-factory>
 +    <property name="connection.datasource">java:/comp/env/jdbc/hibernate1</property>
 +    <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
 +    <property name="hibernate.show_sql">true</property>
 +    <mapping resource="ejemplo02/persistencia/dao/impl/Profesor.hbm.xml"/>
 +    <mapping resource="ejemplo02/persistencia/dao/impl/Usuario.hbm.xml"/>
 +  </session-factory>
 +</hibernate-configuration>
 +</code>
 +
 +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''
 +
 +<code java 1 | HibernateContextListenerAndFilter.java>
 +@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();
 +    }
 +}
 +</code>
 +
 +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''
 +
 +<note tip>
 +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]]
 +</note>
 +
 +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. 
 +
 +<note warning>
 +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}}
 +
 +</note>
 +
 +==== web.xml ====
 +En vez de usar la anotaciones:
 +
 +<code java>
 +@WebListener()
 +@WebFilter(urlPatterns = {"*.html"})
 +</code>
 +
 +Se puede modificar el web.xml añadiendo las siguientes líneas:
 +<code xml> 
 +<listener>
 +    <listener-class>com.fpmislata.persistencia.hibernate.HibernateContextListenerAndFilter</listener-class>
 +</listener>
 +<filter>
 +    <filter-name>HibernateContextListenerAndFilter</filter-name>
 +    <filter-class>com.fpmislata.persistencia.hibernate.HibernateContextListenerAndFilter</filter-class>
 +</filter>
 +<filter-mapping>
 +    <filter-name>HibernateContextListenerAndFilter</filter-name>
 +    <url-pattern>*.html</url-pattern>
 +</filter-mapping>    
 +    
 +</code>
 +====== 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.
 +
 +<code java 1 | ProfesorController.java >
 +@Controller
 +public class ProfesorController {
 +
 +    @Autowired
 +    private ProfesorDAO profesorDAO;
 +
 +    @RequestMapping({"/index.html"})
 +    public ModelAndView read(HttpServletRequest request, HttpServletResponse response) {
 +        Map<String, Object> 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);
 +    } 
 +    
 +}
 +</code>
 +
 +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 <javadoc jee6>javax.servlet.http.HttpServletRequest|HttpServletRequest</javadoc> y <javadoc jee6>javax.servlet.http.HttpServletResponse|HttpServletResponse</javadoc> al igual que en un Servlet.
 +
 +<note tip>
 +Spring MVC tiene muchas funcionalidades relativas las URL que controla, parametros de entrada y de salida.Aquí se han utilizado únicamente <javadoc jee6>javax.servlet.http.HttpServletRequest|HttpServletRequest</javadoc> y <javadoc jee6>javax.servlet.http.HttpServletResponse|HttpServletResponse</javadoc> 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]]
 +</note>
 +
 +El método retorna una clase de Spring MVC llamada <javadoc s31>org.springframework.web.servlet.ModelAndView|ModelAndView</javadoc>. Esta clase contendrá un String con la página jsp a mostrar ( es decir la Vista ) y un <javadoc jdk7>java.util.Map|Map</javadoc> con los datos que necesita la vista para mostrarse (es decir el Modelo).
 +
 +Podemos ver en la línea 22:
 +<code java>
 +return new ModelAndView(viewName, model);
 +</code>
 +como se crea un nuevo objeto <javadoc s31>org.springframework.web.servlet.ModelAndView|ModelAndView</javadoc> que tiene como argumentos un String con el nombre de la página JSP a mostrar y el <javadoc jdk7>java.util.Map|Map</javadoc> con los datos para la vista.
 +
 +<note tip>
 +Recuerda que en el String con el nombre de la vista que se retorna en <javadoc s31>org.springframework.web.servlet.ModelAndView|ModelAndView</javadoc> 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".
 +</note>
 +
 +====== 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 <javadoc jdk7>java.util.Map|Map</javadoc> del modelo que se creó en la clase <javadoc s31>org.springframework.web.servlet.ModelAndView|ModelAndView</javadoc> mediante el siguiente código:
 +<code java>
 +Object texto=request.getAttribute("texto");
 +</code>
 +Siendo el String ''"texto"'' la clave del <javadoc jdk7>java.util.Map|Map</javadoc> con la que se guardó el valor.
 +
 +Un ejemplo de página JSP es la siguiente:
 +<code html 1 | profesor.jsp>
 +<%@page contentType="text/html" pageEncoding="UTF-8"%>
 +<%
 +Object texto=request.getAttribute("texto");
 +%>
 +<!DOCTYPE html>
 +<html>
 +    <head>
 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 +        <title>Profesor</title>
 +    </head>
 +    <body>
 +        <h1><%=texto %></h1>
 +    </body>
 +</html>
 +</code>
 +Vemos en la línea 3 cómo se accede a los datos del modelo.
  
unidades/08_spring/03_spring_mvc.txt · Última modificación: 2023/04/07 21:26 por 127.0.0.1