Apartado 4.3: Problemas con Servlets y páginas JSP. Patrones

Anuncio
4.3 Problemas con servlets y páginas
JSP. Patrones
Situación a la que queremos llegar
n
n
n
Poder usar directamente herramientas de diseño de
páginas web para implementar la vista
Las actualizaciones al aspecto gráfico no deben
provocar un re-arranque del servidor
Separación de roles
n
Informáticos
n
n
Diseñadores gráficos o similares
n
n
Modelo, controlador y partes de la vista no relacionados con el
aspecto gráfico
Implementación del aspecto gráfico de la aplicación
Esta separación en muchos puede ser sólo ideal (depende
de la cultura de la empresa), pero la idea es tender hacia
ella
¿ Son los Servlets la solución ?
n
¿ Podemos usar directamente herramientas de diseño
de páginas web ?
n
n
¿ Se pueden hacer actualizaciones al aspecto gráfico
sin re-arrancar el servidor ?
n
n
No
No
¿ Es posible una separación de roles ?
n
n
Las personas que desarrollan el modelo no tienen porque
ser las mismas que las que hacen los servlets
Sin embargo, las personas que desarrollan los servlets
necesitan conocimientos de programación
¿ Es JSP la solución ?
n
¿ Podemos usar directamente herramientas de diseño
de páginas web ?
n
n
¿ Se pueden hacer actualizaciones al aspecto gráfico
sin re-arrancar el servidor ?
n
n
Sí
Sí
¿ Es posible una separación de roles ?
n
n
Las personas que desarrollan el modelo no tienen porque
ser las mismas que las que hacen las páginas JSP
Sin embargo, las personas que desarrollan las páginas JSP
necesitan conocimientos de programación para incrustar el
código Java (scriptlets y expresiones)
¿ Cuál es la solución ?
n
n
Una que permita construir páginas JSP sin código
Java (o de otro lenguaje de programación)
¿ Cómo podemos conseguirlo ?
n
n
Con un buen diseño Model-View-Controller
Usando el mecanismo de extensión de tags de JSP
n
n
n
n
Permite implementar “acciones a medida” (custom actions)
Paquete javax.servlet.jsp.tagext
Podríamos implementar un buen número de acciones para
eliminar una parte importante de los scriptlets y expresiones de
las páginas JSP
Un diseñador gráfico podría aprender a usarlas
n
n
Al fin y al cabo, tienen el aspecto de los tags HTML (un nombre y
atributos)
Muchos editores de HTML permiten integrar librerías de
acciones para desarrollar páginas JSP
Problema 1: URL rewriting
n
Para que una aplicación que use sesiones sea
robusta, necesita aplicar URL rewriting a todas las
URLs que genera o hace un sendRedirect
n
Ej.: Extracto de Portal2/MainPage.jsp
<a href="<%= response.encodeURL("../Index.jsp") %>">
Servlet and JSP tutorial main page</a>
<br>
<a href="<%= response.encodeURL("ProcessLogout.jsp") %>">Logout</a>
n
Sería más sencillo disponer de una acción que lo
hiciese automáticamente
<html:link page="../Index.jsp">Servlet and JSP tutorial main page
</html:link>
<br>
<html:link page="ProcessLogout.jsp">Logout</html:link>
Problema 2: Mostrar formularios (1)
n
Repasar Portal2/ShowLogin.jsp
n
n
n
n
Necesidad de un scriptlet muy grande para recuperar
posibles errores
Necesidad de usar expresiones para insertar los posibles
mensajes de errores
Necesidad de aplicar URL rewriting en el atributo action
del formulario
Sería más sencillo disponer de acciones que
ocultasen todo este código
Problema 2: Mostrar formularios (2)
<html>
<head>
<title>Portal-2 login form</title>
</head>
<body text="#000000" bgcolor="#ffffff">
<html:form action="ProcessLogin.jsp">
<table width="100%" border="0" align="center" cellspacing="12">
<%-- Login name --%>
<tr>
<th align="right" width="50%">Login name</th>
<td align="left">
<html:text property="loginName" size="16" maxlength="16"/>
<html:errors property="loginName"/>
</td>
</tr>
Problema 2: Mostrar formularios (3)
<%-- Password --%>
<tr>
<th align="right" width="50%">Password</th>
<td align="left">
<html:password property="password" size="16" maxlength="16"/>
<html:errors property="password"/>
</td>
</tr>
<%-- Remember my password --%>
<tr>
<th align="right" width="50%">
Remember my password (cookies must be enabled)
</th>
<td align="left">
<html:checkbox property="rememberMyPassword"/>
</td>
</tr>
Problema 2: Mostrar formularios (y 4)
<tr>
<td width="50%"></td>
<td align="left" width="50%">
<input type="submit" value="Login">
</td>
</tr>
</table>
</html:form>
</body>
</html>
Patrón View Helper
n
n
n
Este tipo de acciones JSP a medida que estamos
viendo (problemas 1 y 2), y que nos ayudan a
generar la vista, corresponden a la aplicación del
patrón View Helper
Facilitan el acceso a objetos Java (en cualquiera de
los cuatro ámbitos)
Generan HTML, WML, etc. sin aspecto gráfico
n
n
Ej.: Campos de entrada en formularios, URLs (para hacer
más transparente el paso de parámetros, URL rewriting,
etc.)
Nunca deben generar HTML, WML, etc.
centrado en aspecto gráfico
n
n
Ejemplo de mala idea: tener un acción que imprime un
objeto Java en una tabla
Precisamente lo que queremos evitar es código Java
mezclado con HTML, WML, etc.
Problema 3: Procesar peticiones (1)
n
Las páginas JSP de procesamiento suelen tener el
siguiente esquema
n
(1.1) Recuperar los valores de los parámetros
n
n
n
(1.2) Validar los parámetros
n
n
n
Directamente de la request
Usando JavaBeans
En caso de tratarse del procesamiento de un formulario, si hay
errores, se hace un forward al formulario con los errores
insertados en la request
En caso de que ocurra algún error “inesperado” =>
sendRedirect a una página que indique “error interno”
(1.3) Invocar una operación sobre un Business Delegate del
modelo o una fachada del controlador
n
Si se produce una excepción, mismo tratamiento que en la
validación de parámetros
Problema 3: Procesar peticiones (2)
n
(1.4) Hacer un sendRedirect a otra página o
generar una respuesta
n
(1.4.1) sendRedirect
n
n
(1.4.2) Generar una respuesta
n
n
Ej.: En el procesamiento de un formulario de login
Ej.: En el procesamiento de una búsqueda
Variantes
n
En muchas situaciones reales el paso 1.3 se implementa sin
hacer uso de Business Delegates y lanzado queries
directamente contra la BD vía JDBC
n
¡ Modelo mezclado con la vista !
n
n
Quizás sería mejor decir: ¡ modelo inexistente !
Difícil de mantener en aplicaciones de tamaño medio y grande
Problema 3: Procesar peticiones (3)
n
Análisis
n
Páginas de procesamiento que son del tipo 1.4.1
n
n
n
No generan aspecto gráfico
Sólo contienen un scriptlet grande
Páginas de procesamiento que son del tipo 1.4.2
n
n
Contiene un scriptlet grande al principio
La última parte de la página genera la respuesta HTML, WML,
etc.
n
n
Suelen hacer uso de scriptlets para iterar sobre los resultados
devueltos por la operación del modelo y darles formato HTML,
WML, etc.
Ej.: Imprimir los resultados de una búsqueda en una tabla
Problema 3: Procesar peticiones (4)
n
¿ Cómo podemos eliminar el código Java en las
páginas de tipo 1.4.1 ?
n
n
Implementándolas como servlets (controlador) y no como
páginas JSP
¿ Cómo podemos eliminar el código Java en las
páginas de tipo 1.4.2 ?
n
n
Implementándolas como un servlet (controlador) y una
página JSP (vista)
Servlet
n
n
n
Ejecuta el código que antes iba en el scriptlet
En caso de errores => forward a la página JSP que muestra
el formulario (con errores insertados en la request) o
sendRedirect a una página de error interno
En otro caso, deja el valor de retorno de la operación del
Business Delegate en la request como atributo y hace un
forward a la página JSP de visualización de resultados
Problema 3: Procesar peticiones (5)
n
¿ Cómo podemos eliminar el código Java en las
páginas de tipo 1.4.2 ? (cont)
n
Página JSP de visualización de resultados
n
n
Recupera los resultados de la request con acciones JSP
Hace uso de acciones JSP para iterar sobre los resultados de
tipo Collection o similar
Problema 3: Procesar peticiones (6)
n
El enfoque anterior requiere un servlet por cada
petición que haya que procesar
n
Si deseamos saber cuál es la siguiente URL a la que se salta
tras invocar una petición de procesamiento, hay que
examinar el servlet en cuestión
n
n
Flujo de control difícil de seguir
Si se necesita aplicar políticas globales a todos los servlets,
es necesario programarlas en cada uno
n
Ej.: Hacer log de cada petición que se recibe, imprimiendo la
URL invocada, los nombres de los parámetros y sus valores
Problema 3: Procesar peticiones (7)
n
Patrón Front Controller
n
Emplea un solo servlet
javax.servlet.http.HttpServlet
Action
FrontController
0..n
+ process
# doGet
# doPost
doGet llama a
doPost (o alrevés)
Action1
ActionN
...
Problema 3: Procesar peticiones (8)
n
Patrón Front Controller (cont)
n
n
Configuramos el servidor de aplicaciones para que las
peticiones a URLs que terminen en .do se redirijan al
servlet FrontController
En WEB-INF/web.xml
<servlet>
<servlet-name>FrontController</servlet-name>
<servlet-class>FrontController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FrontController</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Problema 3: Procesar peticiones (9)
n
Patrón Front Controller (cont)
n
n
Ej.: Portal-2
Acciones: ProcessLoginAction y ProcessLogoutAction
n
n
n
Funcionalmente equivalentes a Portal2/ProcessLogin.jsp
y Portal2/ProcessLogout.jsp
Las peticiones a las URLs Portal2/ProcessLogin.do y
Portal2/ProcessLogout.do llegan al FrontController
Cuando el FrontController arranca (init)
n
Lee un fichero de configuración que especifica
n
n
n
n
Portal2/ProcessLogin.do => Action =
ProcessLoginAction, Success = /Portal2/MainPage.jsp,
Input = /Portal2/ShowLogin.jsp
Portal2/ProcessLogout.do => Action =
ProcessLogoutAction, Success = /Index.jsp
InternalError = /Portal2/InternalError.jsp
Crea una instancia por cada acción existente
Problema 3: Procesar peticiones (10)
n
Patrón Front Controller (cont)
n
n
Cuando al FrontController le llega una petición, la pasa
a la acción correspondiente
El método process de la acción (1) recupera los valores de
los parámetros, (2) invoca una operación sobre un Business
Delegate o una fachada del controlador, (3) deja los
resultados en la request, y (4) hace un forward o
sendRedirect a Success, Input o InternalError
n
La clase base Action (u otra en un framework más complejo)
le facilita el hacer el forward/sendRedirect
n
n
n
Usa nombre lógicos (Success, Input o InternalError) y no
los nombres de las URLs reales
El sendRedirect aplica URL rewriting automáticamente
El fichero de configuración deja claro el flujo de control
Problema 3: Procesar peticiones (y 11)
n
Si quisiésemos aplicar una política global (ej.: trazar
peticiones en un log para depuración) a todas las
acciones o un subconjunto de ellas
n
n
n
doGet/doPost (FrontController) pueden hacerlo antes
de llamar a la acción
También puede hacerlo la clase base Action
O aún mejor, podemos aplicar Chain Of Responsability en
doGet / doGet (o en la clase base Action) antes y/o
después de ejecutar la acción
n
n
n
Cadena del filtros de pre-procesamiento
Cadena de filtros de post-procesamiento
Sun Java Center llama Decorating Filter a este patrón
Otros problemas
n
Hay que tener cuidado cuando se escribe el valor de
un atributo de un objeto Java en el HTML generado
n
n
n
Podría contener caracteres especiales para HTML: <, >, ', "
y&
Es preciso convertirlos a referencias internas: &lt, &gt,
&#39, &#34 y &
En los ejemplos del tutorial de servlet no se trata este caso
n
n
¿ Y si queremos internacionalizar la aplicación ?
n
n
n
Ej.: Elegir <hola> como nombre de login y observar el valor
que imprime MainPage.jsp
Ej.: que el usuario pueda elegir el idioma: español, gallego,
inglés, etc.
Problema: en los ejemplos que hemos visto los mensajes
están dentro de las páginas JSP
Y más problemas, y más problemas, y más
problemas ...
Conclusión (1)
n
Necesitamos un framework que nos proporcione
n
n
Un servlet FrontController y clases relacionadas
Un buen número de acciones JSP a medida (custom tags)
que actúen como View Helpers para
n
n
n
n
n
n
n
Facilitar la construcción de las páginas que muestran
formularios (campos de entrada y errores)
Imprimir URLs (con URL rewriting automático)
Acceso a objetos Java en cualquiera de los posibles ámbitos
(request, session, page y application)
Imprimir el valor de atributos de objetos Java
Iterar sobre objetos de tipo Collection o similar
Soporte para internacionalización
Etc.
Conclusión (y 2)
n
Con este framework una aplicación web tendrá el
siguiente aspecto
n
Modelo
n
n
n
n
Controlador
n
Servlet FrontController y clases acción
n
Desacopla la vista del modelo
Vista
n
n
n
Conjunto de clases que implementan la lógica de negocio
Independiente de la vista
Páginas JSP sin código Java
Usan muchas acciones JSP a medida (la mayor parte
proporcionados por el framework)
Jakarta Struts
n
n
¡ Es el framework que queremos !
La versión 1.0 (estable) vio la luz en Julio del 2001
Descargar