Post on 05-Jul-2015
mayo de 2005
Control de flujo en base a “Actions”
Introducción (I)
Actions clases más flexibles Responsabilidades:
Acceder a capa de negocio Preparar los objetos de datos para capa de presentación Tratamiento de errores
¿Dónde encaja un Action ? ActionForward proporciona un enlace a página de entrada ActionForm captura la entrada ActionMapping configura el Action Action envía la entrada a la base de datos
Introducción (II)
¿Qué son? Son miniservlets. El servlet ActionServlet “reparte el juego” entre los
actions Se fija en los ActionMapping para enviar a uno u otro
Todo Action devuelve un ActionForward El ActionServlet hace la redirección a la página adecuada
Multihilo Sólo se instancia una clase Action de cada tipo por aplicación
Punto de entrada de ejecución Método perform() (Struts 1.0) ó método execute()
(desde 1.1)
Introducción (III)
¿Qué parámetros aceptan? mapping ActionMapping utilizado para
invocar este Action form ActionForm especificado (si lo hay) en
el ActionMapping request El contexto del request (mismo que
en Servlet) Response Contexto del response (mismo que
en Servlet)
Introducción (IV)
¿Qué funciones tienen? Validar precondiciones
Validaciones no realizadas en ActionForm. P.e.: ¿Está usuario logeado?
Llamar a los métodos de lógica de negocio Buena práctica separar de Action lógica de negocio
Tratamiento de errores Registrar errores. Objetos ActionErrors, ActionError y
método saveErrors Mostrar mensaje de error “localizado”
Rutar el control a la vista adecuada return mapping.findForward("continue");
Flujo de control (I)
JSP
ActionServlet
JSP
Form HTML
ActionHazAlgo
ActionForm
Request form
ulario.jsp
Envía form a hazAlgo.doElige
Action
execute() EligeJSP
devuelve resultado
Struts-config.xml
Flujo de control (II) Usuario solicita un formulario HTML Formulario le envía a hazAlgo.do
Struts-config.xml mapea /hazAlgo.do a HazAlgoAction (derivada de Action)
Se invoca método execute() de HazAlgoAction Como argumento va ActionForm con datos del formulario El objeto Action HazAlgoAction invoca lógica de negocio y/o accede
al modelo (BBDD) Action utiliza método mapping.findForward para buscar recurso
(definido en struts-config.xml) a dónde redireccionar (JSP, otro Action, página HTML, etc.)
Struts redirecciona a salida adecuada Si es JSP se pueden usar tags de struts <bean:message> para
internacionalizar salida y <bean:write> para escribir variables
Escribiendo una aplicación (I)
Modificar struts-config.xml: Relacionar paths XXXX.do a clases Action Especificar condiciones de retorno a
páginas JSP Declarar todos los form beans utilizados
(ActionForm) Definir un ActionForm
Clase derivada de ActionForm que contiene datos de un formulario HTML
Escribiendo una aplicación (II)
Crear JavaBeans de resultados: Contendrán los resultados de la capa de negocio
y/o del modelo
Definir una clase Action que reciba las peticiones:
struts-config.xml determina: Entrada: puede haber varias URIs mapeadas a un mismo
Action Salida: a qué JSP se devolverá el control dependiendo de
estado: éxito, error en BBDD, error autenticación, etc.
Escribiendo una aplicación (III)
Crear el formulario que invoca a hazAlgo.do: El atributo action de formulario HTML apunta a hazAlgo.do Pueden usarse Tags de Struts para facitar tarea <html:form>
Mostrar resultados en JSP Se utilizan tags de Struts <bean:write> para copiar valores de
JavaBean de resultados en página Alternativamente puede usarse JSLT
Si la página JSP sólo es accesible desde Action pueden ir dentro de WEB-INF
Si JSP tiene sentido como página accesible directamente puede hacerse redirect (petición pasa por cliente) en vez de forward (petición no pasa por cliente):
<forward ... redirect="true"/> (en struts-config.xml)
Ejemplo 1: Mapear resultados
Aplicación básica de registro Familiarización con Actions No se comprobará entrada Mapeo de datos
Localización http://localhost:8080/struts-actions
Clase Action RegisterAction1
Dentro de paquete app Siempre devuelve página de éxito.
Creamos proyecto en NetBeans “struts-actions” partiendo de fuentes de directorio “struts-actions”
Ejemplo 1:struts-config.xml (I)
Creamos entrada para register1.do Creamos entrada <action> dentro de <action-mappings> Notas sobre atributos de action:
Path: Es el path que se quiere maper al action Es relativo al contexto de la aplicación. NO incluye el .do Path=“/register1” http://localhost:8080/struts-actions/register1.do
Type: Es la clase Action a la que se mapea URI
<action-mappings><action path="/register1"
type=“app.RegisterAction1“</action>
</action-mappings>
Ejemplo 1:struts-config.xml (II)
Especificamos página de retorno Creamos entrada <forward> con nombre “success” Dos alternativas
Página “privada” para un action concreto Se define anidado dentro de la etiqueta <action> correspondiente
Página accesible desde más de un action o recurso. Se define dentro de <global-forwards> fuera de <action-mappings>
Definimos la página de retorno como “global”: Dentro de directorio WEB-INF No será accesible desde el navegador
directamente
<global-forwards><forward name=“success“
path=“/WEB-INF/results/confirm.jsp"></forward>
</global-forwards>
Ejemplo 1:Creamos Action Todas deben derivar de Action Deben ir todas en el mismo paquete El método principal a redefinir es execute().
Está relacionado con nuestra lógica de negocio No requiere declaraciones en struts-config.xml
Siempre debería acabar con mapping.findForward Puede haber diferentes retornos dependiendo del éxito de la acción La elección del JSP específico de acuerdo con el estado de salida se definía en struts-config.xml (podemos cambiar JSPs sin
tener que recompilar) Por ahora no usaremos SuggestionBean
package app;
import javax.servlet.http.*;import org.apache.struts.action.*;
public class RegisterAction1 extends Action {public ActionForward execute(ActionMapping mapping,
ActionForm form,HttpServletRequest request,HttpServletResponse response)
throws Exception {return(mapping.findForward("success"));
}}
Ejemplo 1:Presentación
Tenemos lógica básica Falta parte de presentación Formulario que apunte a register1.do Página de entrada: register1.jsp:
<HTML><HEAD><TITLE></TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Registro de nueva cuenta</H1><FORM ACTION="register1.do" METHOD="POST"> Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR> Password: <INPUT TYPE="PASSWORD" NAME="password"><BR> <INPUT TYPE="SUBMIT" VALUE="Registrar"></FORM></CENTER></BODY></HTML>
Ejemplo 1:Presentación (II) Página de resultado Se realiza forward dentro del servidor No interesa que sea accesible directamente
La creamos dentro de WEB-INF Página WEB-INF/results/confirm.jsp que sólo muestra mensaje de éxito
<HTML><HEAD><TITLE></TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Ha registrado la cuenta con éxito</H1>Felicidades.</CENTER></BODY></HTML>
Ejemplo 1:Resultados
Página de inicio: http://localhost:8080/struts-actions/register1.jsp
Ejemplo 1:Resultados (II)
Página de resultados: Tras introducir cualquier cosa
Ejemplo 2: Múltiples resultados
Extensión de aplicación de ejemplo 1 Mapear más de un resultado según condición de
error
Nueva clase Action: RegisterAction2
Devolverá “success”, “bad-address” o “bad-password”
Nuevas páginas de resultados WEB-INF/result/bad-address.jsp WEB-INF/result/bad-password.jsp
Ejemplo 2: Entrada
Reaprovechamos register1.jsp para register2.jsp
Cambiamos ACTION del formulario que apunte a: register2.do
<HTML><HEAD><TITLE>New Account Registration</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Registro de nueva cuenta (2ª forma)</H1><FORM ACTION="register2.do" METHOD="POST"> Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR> Password: <INPUT TYPE="PASSWORD" NAME="password"><BR> <INPUT TYPE="SUBMIT" VALUE="Registrar"></FORM></CENTER></BODY></HTML>
Ejemplo 2: struts-config.xml
Añadimos nuevo action (register2.do) Tiene varias salidas dependiendo del
resultado de la operación
<action-mappings><action path="/register2"
type="coreservlets.RegisterAction2">
<forward name="bad-address"path="/WEB-INF/results/bad-address.jsp"/>
<forward name="bad-password"path="/WEB-INF/results/bad-password.jsp"/>
<forward name="success"path="/WEB-INF/results/confirm.jsp"/>
</action></action-mappings>
Ejemplo 2:Creamos Action
Ahora nuestro Action tiene algo de lógica Chequea formato de dirección email Chequea longitud mínima del passwordpublic class RegisterAction2 extends Action {
public ActionForwardexecute(ActionMapping mapping,
ActionForm form,HttpServletRequest request,HttpServletResponse response)
throws Exception {String email = request.getParameter("email");String password = request.getParameter("password");if ((email == null) || (email.trim().length() < 3) || (email.indexOf("@") == -1)) {
return(mapping.findForward("bad-address"));} else if ((password == null) || (password.trim().length() < 6)) {
return(mapping.findForward("bad-password"));} else {
return(mapping.findForward("success"));}
}}
Ejemplo 2:Presentación Páginas de salida de error que muestren mensajes adecuados:
WEB-INF/result/bad-address.jsp WEB-INF/result/bad-password.jsp
<HTML><HEAD><TITLE></TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Dirección de email incorrecta</H1>Debe tener formato username@host.Por favor <A HREF="register2.jsp">Intentelo de nuevo</A>.</CENTER></BODY></HTML>
<HTML><HEAD><TITLE></TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Password incorrecto</H1>El password debe tener al menos 6 caracteres.Por favor inténtelo <A HREF="register2.jsp">de nuevo</A>.</CENTER></BODY></HTML>
Bad-address.jsp Bad-password.jsp
Ejemplo 2:Resultados Accedemos a: http://localhost:8080/struts-actions/register2.jsp Páginas de error en caso de introducir mal email o password menor de 6
caracteres
Ejemplo 3: Con form beans
Partimos de Ejemplo2 Añadimos sugerencias para el usuario en caso de que no complete
algún campo Utilizaremos un form bean
Contiene los datos que recibimos del formulario Familiarización de uso de ActionForms
Utilizaremos un bean de resultados Representa resultados del modelo o lógica de negocio
Haremos uso de tags para JSP de struts <bean:write> nos facilitará el manejo de campos de los beans Para poder utilizar los tags <bean:xxxxx> ha de incluirs en el JSP:
<%@ taglib uri=http://struts.apache.org/tags-bean prefix="bean" %>
Ejemplo 3:struts-config.xml (I)
Definimos el form bean a utilizar: Creamos entrada <form-bean> con nombre
“userFormBean” Parámetros
Name: nombre simbólico que se referenciará en actions Type: clase que implementa el ActionForm
<form-beans><form-bean name=“userFormBean“
type=“app.UserFormBean"></form-bean>
</form-beans>
Ejemplo 3:struts-config.xml (II)
Definimos un nuevo action (register3.do) con dos nuevos argumentos
Name: nombre simbólico que hace referencia al form-bean definido (ActionForm)
Scope: Ámbito donde es válido el form-bean. Por defecto es session. Ponemos request (se inicialicen los datos con cada envío).
<action path="/register3"type=“app.RegisterAction3"name="userFormBean"scope="request“><forward name="bad-address"
path="/WEB-INF/results/bad-address-tags.jsp"/><forward name="bad-password"
path="/WEB-INF/results/bad-password-tags.jsp"/><forward name="success"
path="/WEB-INF/results/confirm.jsp"/></action>
Ejemplo 3:Creamos form bean
Definimos un form bean básico Clase derivada de ActionForm Debe tener parámetros mutables que se correspondan con campos
del formulario HTML Debe tener parámetros leibles para cada uno que quiera mostrarse
en el JSP de salida
package app;import org.apache.struts.action.*;public class UserFormBean extends ActionForm {
private String email = "";private String password = "";public String getEmail() { return(email); }public void setEmail(String email) {
this.email = email;}public String getPassword() { return(password); }public void setPassword(String password) {
this.password = password;}
}
Ejemplo 3:Creamos bean de resultados
Definimos el bean de resultados Está relacionado con nuestra lógica de negocio No requiere declaraciones en struts-config.xml
package app;import org.apache.struts.action.*;public class SuggestionBean {
private String email = "";private String password = "";
public SuggestionBean(String email, String password){this.email = email;this.password = password;
}public String getEmail() { return this.email; }public String getPassword() { return this.password; }
}
Ejemplo 3:Creamos “lógica de negocio”
Definimos una clase que implemente nuestra lógica de negocio
Podría hacer cualquier cosa Clase de ayuda que nos sugiera combinaciones
usuario/password
package app;public class SuggestionUtils {
private static String[] suggestedAddresses ={ “emiliobotin@bsch.es",
"gates@microsoft.com",“ortega@inditex.com","ellison@oracle.com" };
private static String chars ="abcdefghijklmnopqrstuvwxyz0123456789#@$%^&*?!";
public static SuggestionBean getSuggestionBean() {String address = randomString(suggestedAddresses);String password = randomString(chars, 8);return(new SuggestionBean(address, password));
}/* … Mirar código ejemplo para randomString() … */
}
Ejemplo 3:Creamos action Partimos del Action del ejemplo anterior
Ahora recuperamos los datos de entrada del ActionForm (en vez del request) Metemos bean SuggestionBean como atributo del objeto request como
resultado en las páginas de error.
public class RegisterAction2 extends Action {public ActionForward
execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)
throws Exception {UserFormBean userBean = (UserFormBean) form;String email = userBean.getEmail();String password = userBean.getPassword();if ((email == null) || (email.trim().length() < 3) || (email.indexOf("@") == -1)) {
request.setAttribute("suggestionBean",SuggestionUtils.getSuggestionBean());
return(mapping.findForward("bad-address"));} else if ((password == null) || (password.trim().length() < 6)) {
request.setAttribute("suggestionBean",SuggestionUtils.getSuggestionBean());
return(mapping.findForward("bad-password"));} else {
return(mapping.findForward("success"));}
}}
Ejemplo 3:Presentación
El punto de entrada: register3.jsp Igual sólo que apunta a register3.do
<HTML><HEAD><TITLE>New Account Registration</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Registro de nueva cuenta (con sugerencias)</H1><FORM ACTION="register3.do" METHOD="POST"> Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR> Password: <INPUT TYPE="PASSWORD" NAME="password"><BR> <INPUT TYPE="SUBMIT" VALUE="Registrar"></FORM></CENTER></BODY></HTML>
Ejemplo 3:Presentación (II) Salida
Hacemos uso de tag <bean:write>. Por defecto filtra caracteres malignos y los convierte a código HTML. Podemos evitar el filtrado con argumento: filter=“false”
“>” “> Para hacer uso de los tags <bean:XXXX> hay que importar:
<%@ taglib uri="http://struts.apache.org/tags-bean"prefix="bean" %>
Podemos referencias los beans (tanto los normales como ActionForms) por su nombre (especificado en sruts-config.xml)
Creamos WEB-INF/results/bad-address-tags.jsp
<HTML><HEAD><TITLE>New Account Registration</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Registro de nueva cuenta (con sugerencias)</H1><FORM ACTION="register3.do" METHOD="POST"> Dirección Email: <INPUT TYPE="TEXT" NAME="email"><BR> Password: <INPUT TYPE="PASSWORD" NAME="password"><BR> <INPUT TYPE="SUBMIT" VALUE="Registrar"></FORM></CENTER></BODY></HTML>
Ejemplo 3:Presentación (III) Salida
Hacemos uso de tag <bean:write>. Por defecto filtra caracteres malignos y los convierte a código HTML. Podemos evitar el filtrado con argumento: filter=“false”
“>” “> Para hacer uso de los tags <bean:XXXX> hay que importar:
<%@ taglib uri="http://struts.apache.org/tags-bean"prefix="bean" %>
Podemos referencias los beans (tanto los normales como ActionForms) por su nombre (especificado en sruts-config.xml)
Creamos WEB-INF/results/bad-address-tags.jsp
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE>Illegal Email Address</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Email incorrecto</H1>La dirección "<bean:write name="userFormBean" property="email"/>"debe tener el formato usuario@host (p.e. "<bean:write name="suggestionBean" property="email"/>")<p>Inténtelo <A HREF="register3.jsp">de nuevo</A>.</p></CENTER></BODY></HTML>
Ejemplo 3:Presentación (IV)
Salida Y lo mismo para WEB-INF/results/bad-
address-tags.jsp
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE>Illegal Password</TITLE></HEAD><BODY BGCOLOR="#FDF5E6"><CENTER><H1>Password Incorrecto</H1>El password "<bean:write name="userFormBean" property="password"/>" es muy corto.Debe tener al menos 6 caracteres. P.e.: "<bean:write name="suggestionBean" property="password"/>"Por favor inténtelo <A HREF="register3.jsp">de nuevo</A>.</CENTER></BODY></HTML>
Ejemplo 3:Resultados
Si introducimos mal dirección o password nos recordará lo introducido y nos dará sugerencias