----------------------------------------------------------

Pedro del Gallego's Weblog

Main | Next day (ago 13, 2003) »

20030812 martes agosto 12, 2003

El patron Front Controller 1ª parte
Como comente en mi ultimo post he estado dando un pequeño curso sobre J2EE (Bueno mas bien sobre Servlet y JSP, pero eso es otra historia). En la aplicacion del ultimo dia presentaron un Servlet que implantaba el patron Front Controller de la forma

public class MiServlet extends HttpServlet{

public void doPost(HttpServletRequest request, HttpServletResponse response) { String action = request.getParameter("action"); if(action.equals("alta")){ // codigo del alta }else if(action.equals("baja")){ // codigo para dar de baja else if (....){ }.... }
}



No hace falta discutir lo malo de esta forma de implentarlo. Como soy bastante quisquilloso decidi implementar uno por mi parte. Para empezar me marque una serie de objetivos:

Empece por definir la interfaz Accion de la forma mas simple posible. La idea de crear una interfaz comun a todas las acciones es que obliga a que todas inserten el codigo que se ejecutara dentro de un metodo.

public interface Accion {

public String accion(); }



Para obtener una clase pense en un patron factory, creo que es una buena eleccion y que la tarea se ajusta a la definicion de este patron. Posiblemente seria necesario declarar el metodo como syncrhonized, pero no estoy del todo seguro. El objetivo de esta clase es que dado el nombre de otra clase nos devuelva una instancia de esta.

public class AccionFactory {

public static Accion getAccion(String accion){ Accion action = null; try { action = (Accion)Class.forName(accion).newInstance(); } catch (InstantiationException e) { System.out.println("Error al instanciar la clase"); e.printStackTrace(); } catch (IllegalAccessException e) { System.out.println("Acceso Ilegal a no se que ¿?"); e.printStackTrace(); } catch (ClassNotFoundException e) { System.out.println("Tas tonto esa clase no existe"); e.printStackTrace(); } return action; } }



Ahora tocaba buscar una forma de almacenar el mapeo, como ya explique me decidi por un fichero de propiedades por su simplicidad, el nombre del fichero esta directamente implementado en el codigo, aunque seria muy sencillo pasarselo como parametro de inicializacion al servlet y despues recuperarlo alli.

public class MapeoAccionesDAO {

private Properties mapa; public MapeoAccionesDAO(String configuracion){ mapa = new Properties(); try { InputStream iStream = new FileInputStream(configuracion);
mapa.load(iStream);
} catch (FileNotFoundException e) { System.out.println("Error fichero no encontrado");
e.printStackTrace();
} catch (IOException e) { System.out.println("Error IOException no se porque da este error");
e.printStackTrace();
}
} public String getNombreAccion(String requesURI){ return mapa.getProperty(requesURI); }
}



Ya por ultimo (para alivio de los que habeis leido tantas lineas de codigo) solo faltaba implementar el servlet que actua como controlador. Tambien opte por hacerlo de la forma mas sencilla posible, eliminando por ejemplo la posibilidad de decidir si lo que quiero es ralizar un forward o un sendRedirect (esto lo hare un poco mas adelante).

public class Controlador extends HttpServlet {

/*
* Usaremos un objeto que nos mapee las URI con las
* clases accion asociadas a esa URI
*/
private MapeoAccionesDAO acciones;
public void init(ServletConfig config) throws ServletException {
super.init(config);
/*
* Inicializamos el mapeo usando un patron DAO
*/
ServletContext sc = config.getServletContext();
String configuracion = sc.getRealPath("configuracion.properties");
acciones = new MapeoAccionesDAO(configuracion);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.procesar(request,response); }
protected void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.procesar(request,response); }
private void procesar( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ Accion action = null;
/*
* Extraemos la URI de la solicitud
* y se la pasamos al properties como clave
*/
String accion = acciones.getNombreAccion(request.getRequestURI());
System.out.println("Voy a realizar la accion : " + accion);
/*
* Instanciamos la clase que nos devuelve el properties
* y usamos este como zona de mapeo
* y todo esto usando un patron Factory
*/
action = AccionFactory.getAccion(accion);
String nuevaURL = action.accion();
response.sendRedirect(nuevaURL);
}
}


un ejemplo del mapeo seria el siguiente fichero :

comprar.do=comprarAccion
/mittienda/elegir.do=org.mitienda.elegirAccion
/mittienda/devolver.do=org.mitienda.devolveAccion
/mittienda/buscar.do=org.mitienda.buscarAccion
/mittienda/inicio.do=inicioAccion

Pues esto es lo que he hecho, no se si sigue a rajatabla el patron front controller o si he metido la pata, asi que espero opiniones, sugerencias y sobre todo críticas (que es de donde + se aprende). Quedan muchos aspectos por hacer, pero solo queria tener una idea de como funcionaba.

PD: es mi primer post con lineas de codigo :-) ( ago 12 2003, 11:48:41 PM CEST ) Permalink Comentarios [5]