Download Proyecto GestiónStockWeb
Document related concepts
no text concepts found
Transcript
ARQUITECTURA DE TRES CAPAS Una aplicación Web es un programa informático que puede dar servicio simultáneamente a múltiples usuarios que lo ejecutan a través de Internet. Normalmente se estructura en base a una arquitectura de tres capas Cliente Capa Intermedia Capa de Datos Red Capa Cliente interactúa con el usuario de la aplicación, o normalmente usa el navegador Web de la máquina cliente. Captura datos, los envía a la capa intermedia. Presenta al usuario los resultados generados por la aplicación. Capa Intermedia Esta constituida por la aplicación en sí. Instalada en una máquina independiente, (servidor) Los clientes acceden a ella a través de la red, vía protocolo HTTP. En la máquina servidor: o La aplicación es ejecutada por un motor de aplicación (p.e. Tomcat) permite que una instancia de la aplicación atienda múltiples clientes. o La aplicación requiere de un servidor Web (p.e. Apache) interfaz entre ella y el cliente ,realizando el diálogo http. Capa de datos almacenamiento permanente de la información o manejada por la aplicación y la gestión de la seguridad de los mismos. o Esta tarea es soportada, generalmente, por las bases de datos (Oracle, MySQL, SQL Server, etc.). 1 Patrón de Diseño Modelo-Vista-Controlador – (MVC. Model-View- Controller) Fundamental implementar correctamente la capa intermedia de la aplicación. definimos un modelo formado por una serie de bloques o componentes, de modo que cada uno pueda desarrollarse de manera independiente con responsabilidades claramente definidas: patrón Modelo-Vista-Controlador (MVC). Cliente Capa Intermedia Capa de Datos Red Browser Datos Controlador (Servlet) Vista (Jsp) Modelo (Clases) El controlador Es el cerebro de la aplicación. Todas las peticiones desde el cliente son dirigidas al controlador, o Por cada peticion invoca al resto de los componentes de la aplicación .jsp .class Por ejemplo: petición del cliente requiriendo datos de una base el controlador solicitará los datos necesario al modelo recibe los datos del modelo se los proporcionará a la vista. En una aplicación JEE, el controlador es implementado a través de un servlet un JavaBean una etiqueta personalizada. o Pueden existir mas de uno de estos componentes La vista La vista será la encargada de generar las respuestas (generalmente HTML o XML) Si esta respuesta tiene que incluir datos proporcionados por el controlador, o el código HTML de la página no será fijo o sino que deberá ser generado de forma dinámica, o su implementación correrá a cargo de una página JSP. 2 El modelo En la arquitectura MVC la lógica de negocio de la aplicación, el acceso a datos y su manipulación, esta encapsulada dentro del modelo. En una aplicación JEE el modelo puede ser implementado mediante clases estándar Java o mediante Enterprise JavaBeans. APLICACIÓN DE MVC. GestionStockWeb. Veamos el uso del modelo MVC en un caso práctico. Se propone una aplicación Web donde o se registran los movimientos de stock de determinados productos de un negocio. o Al momento de registrar un egreso de productos, o la aplicación deberá controlar que el stock actual sea suficiente o En caso de serlo, deberá informar si el stock resultante se equipara con el nivel mínimo de seguridad previsto para el artículo. o En caso de no serlo Si no existe disponibilidad o la cantidad ingresada no es correcta, deberá notificarse al usuario. El esquema de resolución es el siguiente: Controller Param: operacion= “login” 1. validarUsuario(usr, pwd) 2. registrarMovStock(nom, tipo, ctd) GestorStock Usuario: albert Contraseña: genio Modelo Producto Param: Sigue el proyecto completo operacion = “registrar” Ing. Martín Polliotto, 05 de agosto de 2009. 3 Ejemplo 6: Proyecto GestionStockWeb. Es un ejemplo de un nivel técnico superior. Implementa Servlets, y a diferencia de ejemplos anteriores: Todo organizado según el patrón MVC (Modelo Vista Controlador). o Capa Modelo las clases GestorStock y Producto contienen toda la lógica de negocio. o Capa Controlador viene implementado con un Servlet(clase Controller) o Capa Vista las páginas login.jsp y registrarMovStock.jsp. Lo más importante de este ejemplo Separación las capas de presentación de la de lógica de negocio Implementación de un Servlet que haga de vínculo entre ellas. ….. <web-app version="2.5" … <servlet> <servlet-name>Controller</servlet-name> <servlet-class>controlador.Controller</servlet-class> </servlet> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/controller</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <taglib> <taglib-uri>http://jakarta.apache.org/taglibs/ request-1.0</taglib-uri> <taglib-location>/WEB-INF/taglibs-request.tld </ taglib-location></taglib> </web-app> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Gestión de Stock Web</title> </head> <body> <jsp:forward page = "/vista/login.jsp"/> </body> </html> 4 login.jsp <%-Document : login Created on : 01/08/2009, 23:58:18 Author : fenix --%> Nota: La codificación de esta JSP se ha realizado usando GUI Builder <%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Gestión de Stock Web</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <style> </style> <%@ taglib uri="/WEB-INF/taglibs-request.tld" prefix="req" %> <link rel="stylesheet" href="estilos.css" type="text/css"> </head> <body> <form name="frmLogin" action="controller" method="POST"> <input type="hidden" value="login" name="operacion"> <!-El input 'operacion' permite enviar, sin mostrar al usuario, la acción que deberá procesar nuestro servlet Controller cuando reciba la petición desde este formulario... --> <br/> <div> <table> <h3>Gestión de Stock Web</h3> <br/> <h4 style="color:white;">Ingrese su nombre de usuario y contraseña</h4> <tbody style=""> <tr> <td>Usuario</td> <td><input type="text" name="usuario" value="" size="25" /></td> </tr> <tr> <td>Password</td> <td><input type="password" name="clave" value="" size="25" /></td> </tr> </tbody> </table> <input type="submit" value="Ingresar" name="btnLogin" style="fontfamily:arial;font-size:11px;"/> <br/> <h5 style="color:red;"><req:attribute name="error"/></h5> </div> </form> </body> </html> 5 Esto se ve: Al clickear sobre Ingresar el control es tomado por el indicado en la cláusula action de la sentencia form: Controller, usándose el método post. Controller.java package controlador; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import modelo.GestorStock; /** * * @author fenix */ public class Controller extends HttpServlet { private GestorStock gestor; @Override public void init() throws ServletException { super.init(); gestor = new GestorStock(); } protected void init(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {processRequest(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response);} 6 protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String operacion = request.getParameter("operacion"); RequestDispatcher despachador = null; /*El objeto 'despachador' permite encaminar (despachar) la respuesta a la solicitud * recibida en función del resultado de la operación solicitada. El input type = “hidden”, con */ nombre “operación”, tiene asociado el valor “login”. Entonif(operacion.equals("login")){ ces ejecutamos el cuerpo de esta String usuario = request.getParameter("usuario"); llave. Si gestor.validarUsuario String clave = request.getParameter("clave"); (usuario, clave), retorna “Ok”, String rtdo = gestor.validarUsuario(usuario, clave); vamos a movimentar stock: "/vista/registrarMovStock.jsp" if(rtdo.equals("Ok")){ request.setAttribute("lstProductos", gestor.getProductos()); despachador = request.getRequestDispatcher("/vista/registrarMovStock.jsp"); } else{ request.setAttribute("error", rtdo); despachador = request.getRequestDispatcher("/vista/login.jsp"); } seteamos, como atributo de la respuesta, el despachador.forward(request, response); mensaje de error y solicitamos nueva } identificación: /vista/login.jsp else if(operacion.equals("registrar")){ despachador = request.getRequestDispatcher("/vista/registrarMovStock.jsp"); String nombreProd = request.getParameter("producto"); String cantidad = request.getParameter("cantidad"); String tipoMov = request.getParameter("tipoMov"); request.setAttribute("mensaje", gestor.registrarMovStock(nombreProd,tipoMov, cantidad)); request.setAttribute("lstProductos", gestor.getProductos()); despachador.forward(request, response); } } public String getServletInfo() { return "Servlet Controller. Su objetivo es recibir la peticiones desde" + "las páginas, delegar según el trabajo solicitado mediante el " + "el parámetro 'operacion' al modelo (clases GestorStock y Producto) " + "y con la respuesta del modelo redirigir a la página que corresponda."; }// </editor-fold> } /vista/registrarMovStock.jsp La codificación de esta página, pg 8 7 Nota: La codificación de esta JSP se ha <%-realizado usando el GUI Builder Document : registrarMovStock Created on : 02/08/2009, 01:13:18 Author : fenix --%> …. <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Gestión de Stock Web</title> <%@ taglib uri="/WEB-INF/taglibs-request.tld" prefix="req"%> <link rel="stylesheet" href="estilos.css" type="text/css"> </head> <body> <form name="frmRegistarMovStock" action="controller" method="POST"> <input type="hidden" value="registrar" name="operacion"> <div style="background-color:blue;width:270px;height:250px;"> <h3 align="center" style="color:yellow;">Movimientos de Stock</h3> <table align="center"> <tbody> <tr> <td>Producto</td> <td> <select name="producto"> <%java.util.ArrayList prods = (java.util.ArrayList) request.getAttribute("lstProductos"); for (int i = 0; i < prods.size(); i++) { modelo.Producto p = (modelo.Producto) prods.get(i);%> <option><%=p.getNombre()%></option> <%}%> </select> </td> </tr> <tr> <td>Cantidad</td> <td><input type="text" name="cantidad" size="10" /></td> </tr> <tr> <td>Ingreso</td> <td><input type="radio" name="tipoMov" value="I" checked="checked" /></td> </tr> <tr> <td>Egreso</td> <td><input type="radio" name="tipoMov" value="E" /></td> </tr> </tbody> </table><br/> <input type="submit" value="Registrar" name="btnRegistrar" style="fontfamily:arial;font-size:11px;"/> <br/> <h5 style="color:white;"><req:attribute name="mensaje"/></h5> </div> </form> </body> </html> 8 package modelo; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class GestorStock { private List productos; private final String user = "Frodo"; private final String pwd = "Bolson"; public GestorStock() { productos = new ArrayList(); productos.add(new Producto("Gaseosa Cola 2.5 lts")); productos.add(new Producto("Galletitas Surtidas x 250 grs.")); productos.add(new Producto("Alfajor chico")); productos.add(new Producto("Cigarrillo Acme")); productos.add(new Producto("Yogurt x 500 cm3")); } public List getProductos() { return productos;} public String validarUsuario(String user, String pwd) { String r = "Usuario o clave incorrectos."; if (this.user.equals(user) && this.pwd.equals(pwd)) { r = "Ok"; } return r; } public String registrarMovStock(String prod, String tipo, String ctd) { String r = "Operación registrada exitosamente."; try { int cant = Integer.parseInt(ctd); Producto p = buscarProducto(prod); if (tipo.equals("E")) { if (p.getStock() >= cant) { p.setStock((p.getStock() - cant)); if (p.getStock() <= p.getPtoReorden()) r = "Producto a reponer."; }else r = "Stock insuficiente."; } else p.setStock((p.getStock() + cant)); r+=("<br>" + p.getNombre()+". Stock actual: " + p.getStock()); } catch (NumberFormatException e) { r = "Cantidad incorrecta."; } return r; } private Producto buscarProducto(String nombre) { for (Iterator it = productos.iterator(); it.hasNext();) { Producto x = (Producto) it.next(); if (x.getNombre().equals(nombre)) {return x;} } return null; } } 9 package modelo; public class Producto { private String nombre; private int stock; private int ptoReorden; public Producto(String n){ nombre = n; stock = (int)(Math.random()*100); //como máximo 100 articulos en stock ptoReorden = (int) (Math.random()*6 + 10); // punto de reorden: [10;15] } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public int getStock() { return stock; } public void setStock(int stock) { this.stock = stock; } public int getPtoReorden() { return ptoReorden; } public void setPtoReorden(int ptoReorden) { this.ptoReorden = ptoReorden; } public String toString(){ return "Producto: " + nombre + "\nStock: " + stock + "\nPunto Reorden: " + ptoReorden; } } 10