|
Manual Básico de Struts |
Controller
Intro
El Controller comprende la funcionalidad involucrada desde que un usuario genera un estímulo (click en un link, envío de un formulario, etc.) hasta que se genera la interfaz de respuesta. Entre medio, llamará a los objetos de negocio del Model para que resuelvan funcionalidad propia de la lógica de negocio y según el resultado de la misma ejecutará la JSP que deba generar la interfaz resultante.
Struts incluye un servlet que a partir de la configuración de struts-config.xml recibe las solicitudes del usuario, llama al Action Bean que corresponda y, según lo que éste retorne, ejecuta una JSP. Por consiguiente, las tareas que se deben realizar son:
- Escribir una clase Action que extienda de org.apache.action.Action. Ver sección "Controller Action Bean".
- Configurar el struts-config.xml para que incluya el nuevo action mapping y sus posibles forwards de salida. Por ejemplo:
- Incluir los links (preferentemente utilizando <html:link>) o forms (necesariamente utilizando <html:form>) necesarios en las JSPs correspondientes.
<struts-config>
...
<action-mappings>
...
<action path="/logoff" type="com.empresa.aplicacion.LogoffAction">
<forward name="success" path="/index.jsp"/>
</action>
...
</action-mappings>
...
</struts-config>
En este caso, cuando la solicitud sea "/logoff" el Controller llamará a LogoffAction y si esta retorna un ActionForward con valor success entonces ejecutará /index.jsp. Pero... ¿qué pasa si es una acción asociada a un formulario? La respuesta es un poco más compleja: se debe definir un Form Bean, un Action Mapping con el Form Bean asociado y el o los forwards necesarios. Por ejemplo:
<struts-config>
...
<form-beans>
...
<form-bean name="logonForm" type="com.empresa.aplicacion.LogonForm"/>
...
</form-beans>
...
<global-forwards>
...
<forward name="success" path="/mainMenu.do"/>
...
</global-forwards>
...
<action-mappings>
...
<action path="/logon" type="com.empresa.aplicacion.LogonAction"
name="logonForm" scope="request" input="/logon.jsp"> </action>
...
</action-mappings>
...
</struts-config>
En este caso se ha definido un global-forward que, como su nombre lo indica, viene a ser un forward que se aplica a todos los action-mappings (excepto que se re-defina para alguno en particular).
ActionForm Beans
Los ActionForm Beans son clases que extienden ActionForm y que implementan métodos get y set para cada una de los inputs de un form de una página, y los métodos validate y reset.

Cuando un usuario completa un formulario y lo envía, el Controller busca en el scope especificado el ActionForm Bean correspondiente (todo esto configurado en el struts-config.xml) y si no lo encuentra lo crea. Luego realiza un set por cada input del form y finalmente llama al método validate. Si éste retornara uno o más errores, el Controller llamaría a la JSP del formulario para que ésta lo volviera a generar (con los valores establecidos por el usuario) e incluyera el o los mensajes de error correspondientes. Si todo estuviese bien, llamaría al método perform del Action (también configurado en el struts-config.xml) pasándole el ActionForm Bean como parámetro para que sea utilizado para obtener los valores de los datos.
Si bien el ActionForm tienen características que corresponden al Model, los ActionForm pertenecen a la View. Justamente uno de estos puntos comunes es la validación de datos y a fines de evitar la duplicación de funcionalidad, si un desde un ActionForm debe realizar controles de validación que se hubiesen implementado en un objeto de negocio entonces se debería utilizar una instancia de éste para efectuarlos. Ejemplo:
public final class ClienteForm extends ActionForm {
private String nombre = null;
ActionErrors errors = null;
Cliente cliente = null;
...
public ClienteForm() {
...
// Crear u obtener el objeto como sea...
cliente = new Cliente();
errors = new ActionErrors;
...
}
public String getNombre() {
return (this.nombre);
}
public void setNombre(String nombre) {
try {
cliente.setNombre(nombre);
} catch (Exception e) {
errors.add("nombre", new ActionError("error.nombre"));
}
this.nombre = nombre;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
this.nombre = null;
}
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
...
return errors;
}
}
Al momento de escribir un ActionForm debemos tener en mente los siguientes principios:
- No debe tener nada que corresponda a la lógica de negocio
- No debería tener más que implementaciones de getters y setters (obligatoriamente un par por cada input del form; si el input se llama nombre entonces tendremos getNombre() y setNombre(String nombre)), y de los métodos reset y validate
- Debe ser un Firewall entre el usuario y el Action que detenga todo tipo de errores de incompletitud o inconsistencia
- Si el formulario se desarrolla en varias páginas (por ejemplo, en las interfaces de tipo "Wizard"/"Asistentes") el ActionForm y el Action deberán ser los mismos, lo que permitirá, entre otras cosas, que los input se puedan reorganizar en distintas páginas sin cambiar los ActionForm ni los Action
















































