Lenguaje de Programación II
LENGUAJE DE PROGRAMACIÓN II
CARRERA DE COMPUTACIÓN E INFORMÁTICA
2
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
3
Índice Presentación Red de contenidos
4 5
Unidad de Aprendizaje 1
HTML, JQuery, Servlet, JSP y JDBC. 1.1 Tema 1 : HTML, JSP y elementos de script 1.1.1 : Etiquetas HTML 5. 1.1.2 : JSP y elementos de script 1.2 Tema 2 1.2.1 1.2.2 1.2.3
: : : :
JQuery, Servlet y JSP JQuery Validaciones con JQuery Arquitectura del Servlet
7 7 15 20 20 23
1.3 Tema 3 : JDBC, Aplicaciones Parte I 1.3.1 : Aplicación de Logueo 1.3.2 : Aplicación de Listado
35 36 43
1.4 Tema 4 : JDBC, Aplicaciones Parte II 1.4.1 : Aplicación de Mantenimiento
46 46
Unidad de Aprendizaje 2
CRUD con patrón DAO, sesiones y Lenguaje de Expresiones 2.1 Tema 5 : Patrón DAO Parte I 2.1.1 : Patrones de diseño de software 2.1.2 : Patrón DAO 2.1.3 : Aplicación Listado 2.2 Tema 6 2.2.1 2.2.2 2.2.3 2.2.4
: : : : :
Patrón DAO Parte II, Sesiones Web y EL
Lenguaje de expresiones Aplicación Mantenimiento Sesiones web Aplicación de Logueo
55 55 60 65 74 74 74 83 85
Unidad de Aprendizaje 3
Etiquetas JSTL, Transacciones, Ajax y Listeners 3.1 Tema 7 : Custom Tag y JSTL 3.1.1 : Custom Tag 3.1.2 : Creación de etiquetas personalizadas (Custom TAG) 3.1.3 : JSTL y Librerías 3.1.4 : Aplicación Listado con JSTL 3.2 Tema 8 3.2.1 3.2.2 3.2.3
: : : :
Ajax y Transacciones en Web
AJAX Transacciones Aplicación Ajax y Transacción
3.3 Tema 9 : Listeners 3.3.1 : Tipos 3.3.2 : Aplicaciones
CIBERTEC
93 93 93 103 116 118 118 121 125 146 146 149
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
4
Presentación Lenguaje de Programación II pertenece a la línea de cursos de programación y se dicta en la carrera de Computación e Informática. El curso brinda un conjunto de herramientas del lenguaje Java que permite a los estudiantes utilizarlas en la implementación de aplicaciones web en Java. El manual para el curso ha sido diseñado bajo la modalidad de unidades de aprendizaje, las que se desarrollan durante semanas determinadas. En cada una de ellas, hallará los logros que debe alcanzar al final de la unidad; el tema tratado, el cual será ampliamente desarrollado; y los contenidos, que debe desarrollar, es decir, los subtemas. Asimismo, encontrará las actividades que deberá desarrollar en cada sesión, que le permitirán reforzar lo aprendido en la clase. El curso es eminentemente práctico: consiste en desarrollar una aplicación web. En primer lugar, se inicia con crear programas utilizando la tecnología de Servlet y JSP. Continúa con la presentación de nuevas tecnologías como el patrón Data Access Object, sesiones en la web. Luego, se desarrollan los componentes reutilizables mediante CustomTag. Finalmente, se concluye con el uso de transacciones, Ajax, JQuery y Listeners.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
5
Red de contenidos
Lenguaje de Programación II
Servlet y JSP
Sesiones y EL
Customg Tag
JSTL
Sesiones
Tag Dinámicos
JSTL
EL
Generación de Librerías
Servlet
JSP
AJAX
Patrón DAO
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
AJAX
LENGUAJE DE PROGRAMACIÓN II
6
UNIDAD
1 HTML, JQuery, JSP Y JDBC LOGRO DE LA UNIDAD DE APRENDIZAJE Al término de la unidad, el alumno implementa una aplicación Java Web que utilice las tecnologías JQuery, JSP y Servlet con base de datos.
TEMARIO 1.1 Tema 1 1.1.1 1.1.2 1.2 Tema 2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 Tema 3 1.3.1 1.3.2 1.4 Tema 4 1.4.1
: : : : : : : : : : : : :
HTML, JSP y elementos de script Etiquetas HTML 5 JSP y elementos de script JQuery, Servlet y JSP JQuery Validaciones con JQuery Arquitectura del Servlet Servlet y JSP JDBC, Aplicaciones Parte I Aplicación de Logueo Aplicación de Listado JDBC, Aplicaciones Parte II Aplicación de Mantenimiento
ACTIVIDADES PROPUESTAS Los alumnos resuelven ejercicios que involucran el uso de etiquetas HTML 5 y validación de datos. Los alumnos implementan una aplicación con base de datos para realizar mantenimiento y logueo a un portal web.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
7
1.1 HTML, JSP Y ELEMENTOS DE SCRIPT HTML, siglas de HyperText Markup Language (lenguaje de marcas de hipertexto), hace referencia al lenguaje de marcado para la elaboración de páginas web. Es un estándar que sirve de referencia para la elaboración de páginas web en sus diferentes versiones, define una estructura básica y un código (denominado código HTML) para la definición de contenido de una página web, como texto, imágenes, videos, entre otros. Es un estándar a cargo de la W3C, organización dedicada a la estandarización de casi todas las tecnologías ligadas a la web, sobre todo en lo referente a su escritura e interpretación. JSP, es un lenguaje para la creación de sitios web dinámicos, acrónimo de Java Server Pages. Está orientado a desarrollar páginas web en Java. JSP es un lenguaje multiplataforma. Creado para ejecutarse del lado del servidor. JSP fue desarrollado por Sun Microsystems. La tecnología de JSP permite a los desarrolladores y a los diseñadores de web desarrollar rápidamente y mantener fácilmente páginas dinámicas, también permite introducir código para la generación dinámica de HTML dentro de una página web.
1.1.1 Etiquetas HTML5 HTML es el lenguaje usado para escribir las páginas web, describe la estructura y el contenido usando solo texto y lo complementa con objetos tales como imágenes, flash y otros. Los archivos así creados son guardados con la extensión de archivo HTM o HTML. Su estructura se compone de etiquetas o tags entre las cuales van insertados los diferentes elementos que componen la página como son los bloques de texto, scripts y la ruta a la ubicación de archivos externos como imágenes y otros archivos multimedia. Es más ligero al ser más sencillo y simple el código, lo que permite que las páginas escritas en este lenguaje carguen más rápido en el navegador. Si aún no fuera suficiente, introduce infinidad de opciones que hasta ahora estaban vedadas a las páginas web, como insertar directamente video (no flash), música, y casi cualquier elemento. Formulario Es el contenedor principal donde se encuentran los controles que utilizaremos para ingresar información referente a una entidad de un sistema.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
8
Parámetros de la etiqueta FORM
action: sirve para indicar a donde enviaremos los datos introducidos en los campos del formulario, un destino determinado como: servlet, jsp, etc. method: este atributo indica el modo de transmisión de los datos. El modo GET utiliza la dirección URL para pasar los valores introducidos en los campos del formulario, da como resultado una url como: (www.plataforma.com/enviar.jsp?Apellido=Lara&Nombre=Luis). El modo POST envía los datos como parte de la entrada estándar (no visible en la url). name: Identifica el nombre del formulario, este nombre facilita identificar el formulario desde el script. target: Indica la ventana de destino diferente a la del envió de los datos. accept-charset: Especifica el juego de caracteres que el servidor utiliza para gestionar los datos del formulario. auto-complete: puede ser ON u OFF. Para activar el autocompletado de datos del formulario.
Etiqueta INPUT Esta es la etiqueta más utilizada y también la que presenta más opciones. El atributo TYPE le permite indicar la clase de entrada de datos. El valor predeterminado es TEXT y representa una línea de entrada de datos. Se lista los diferentes tipos de datos que trabaja la etiqueta INPUT:
TEXT CHECKBOX RESET RADIO PASSWORD BUTTON FILE HIDDEN IMAGE SUBMIT
Atributos de la etiqueta input El principal atributo de la etiqueta INPUT es TYPE, ya que es el que le indica el tipo de datos que debe recibir. A continuación mostraremos una lista de atributos que se le pueden agregar a la etiqueta INPUT.
TYPE: Mencionado anteriormente, es el que indica el tipo de control de datos que se ha elegido. SRC: Indica el origen de los datos. STEP: Permite establecer la cantidad de valores posibles dentro de un rango. VALUE: Indica el valor que devuelve el control. REQUIRED: Valor booleano que nos indica que es una información obligatoria. PLACEHOLDER: Texto que sirve de información o guía al usuario y desaparece al pulsar dentro del campo, anteriormente este efecto se creaba con JavaScript
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
9
AUTOCOMPLETE: Indica se se activa (on) o se desactiva (off) el auto completado de la entrada de datos. ALT: Se utiliza cuando el tipo es una imagen y no se puede cargar en la interfaz del usuario, se muestra este texto alternativo. AUTOFOCUS: Permite especificar que una parte del formulario debe tener foco para ingresar información cuando se carga la página. CHECKED: Para indicar si el elemento está seleccionado por defecto, solo se utiliza en algunos tipos. DISABLED: Es un valor booleano que indica que el elemento está desactivado, con lo cual no admite entrada de datos. READONLY: Valor booleano que indica que el campo no se puede modificar, solo lectura. FORM ENCTYPE: Indica el modo de envío de los datos. FORM ACTION: Es la dirección Url que se utiliza al activar el elemento. FORM NOVALIDATE: Es un valor booleano que indica que el formulario no se valida antes de enviarse. FORM TARGET: Ventana del destino del formulario. HEIGHT: Altura del campo en cuestión. WIDTH: Anchura del campo en cuestión. SIZE: Indica la cantidad de caracteres que se pueden introducir en el campo. MAX: Valor máximo que se puede entrar en el elemento de datos. MIN: Valor Mínimo que se puede entrar en el elemento de datos. MAXLENGTH: Longitud máxima de la entrada de datos. LIST: Es un identificador de una lista que se define con DATALIST MULTIPLE: Valor booleano que indica que se permite la selección de valores múltiples. NAME: Nombre que identifica al campo de datos. PATTERN: Expresión regular que se utiliza para validar entradas de datos. Este atributo permite hacer validaciones muy complejas y utilizado correctamente puede ahorrarse muchas líneas de código.
Tipos de campos de formulario (Etiqueta - input)
Input Type:Text El tipo texto representa una línea de texto, como en casi todos los campos de formulario su valor se puede inicializar utilizando el atributo value.
Input Type:Password Representa una entrada de datos de texto que se visualizan asteriscos pero al enviarse se envían los datos reales, el datos introducido en el campo se asigna al atributo value.
Input Type:Hidden Es un control que se mantiene oculto a la vista pero que se pasa al servidor junto con el resto de los campos del formulario. Es un campo adecuado para pasar información de una página a otra y que se puede utilizar en los script como un dato más. Al ser un control oculto, el usuario no puede ni ver ni modificar. El dato se le asigna al atributo value.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
10
Input Type:Checkbox Es un control que es presentado al usuario por una casilla de verificación; por lo tanto, sólo puede tener dos valores: seleccionado o no seleccionado. Si se utiliza el atributo checked, el campo se muestra seleccionado por defecto.
Input Type:Radio Es un control que es presentado al usuario con botones de opción; una variable asignada a un grupo de botones en el que solo uno puede estar seleccionado. Si se utiliza el atributo checked, el campo aparece seleccionado por defecto, para informarle a HTML que todos los botones forman parte de un grupo de opciones, estos comparten el atributo name.
Input Type:SUBMIT Es un control que se representa por un botón que al ser pulsado envía los datos recogidos por el formulario al destino escrito en el parámetro action, en este caso el atributo value se utiliza para poner el texto dentro del botón.
Input Type:RESET Es un control que se representa por un botón que al ser pulsado reinicia los campos del formulario con los valores predeterminados. El atributo value se utiliza como texto del botón.
Input type:File Este control permite enviar archivos al servidor mediante el método POST. En el navegador se muestra un botón examinar o seleccionar para que podamos elegir el archivo que se requiere enviar.
Etiqueta TEXTAREA Se puede crear áreas de texto (en columnas y filas) dónde el usuario pueda insertar contenido donde requiere gran cantidad de información. A diferencia de los input de tipo text, en los textarea el usuario puede incluir saltos de línea. Rn parámetro rows y cols indica la cantidad de filas y columnas que tendrá el control. Etiqueta FIELDSET Sirve para agrupar los elementos. Se utiliza con su respectiva etiqueta de cierre y crea un recuadro que rodea a los elementos de formulario colocados dentro de ella. Etiqueta LEGEND Sirve para nombrar o etiquetar un grupo creado con FIELDSET. Añade simplemente una nota aclaratoria sobre qué tipo de información se está agrupando en el recuadro.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
11
Ejercicio 01: pagina01.html Diseñar la siguiente página para ingresar y seleccionar datos
Código: <meta charset="utf-8">
Insert title here
Nuevos Tipos de input En HTML5 se han incluido nuevos tipos de entradas de datos para los formularios, algunos de estos nuevos tipo de entrada tienen la capacidad de comprobar si el valor introducido coincide con su tipo de dato lo que nos ayuda bastante a la hora de solucionar la validación de los datos que el usuario introduce. Input type:url Esta entrada de datos se utiliza para especificar una dirección web. Se muestra como un simple campo de texto normal. Input type:search El tipo de entrada de datos Search(type="search") proporciona un campo de búsqueda, es muy parecido a un campo de texto normal. Input type: email Se utiliza para especificar una o más direcciones de correo electrónico. Soporta el atributo booleano múltiple, para permitir varias direcciones separadas por coma. Input type: number El tipo number (input=”number”) proporciona una entrada de dato para agregar un número. Normalmente se trata de un cuadro donde se puede escribir un número o hacer clic en las flechas arriba o abajo para seleccionarlo. Esta entrada de datos cuenta con los atributos max y min para especificar los valores mínimo y máximos permitidos, también puede utilizar el atributo step, este determina la cantidad a disminuir o aumentar cuando hace clic en las flechas.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
13
Input type: range Este tipo de entrada de datos nos proporciona un deslizador en aquellos navegadores que lo soportan. Al igual que number, permite los atributos min, max y step. Input Type=Date Esto engloba la fecha (año, mes, día) pero no la hora; Ejemplo, 2008-06-22, Podemos seleccionar el año, mes y día. Ejercicio 02: pagina02.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Insert title here Registrar Empleado
1.1.2 JSP y elementos de script JSP permite la creación de sitios web dinámicos donde se puede combinar contenido HTML y bloques de programación en java que permitan la programación de sentencias. JSP scripting incluye los siguientes elementos de código Java que pueden aparecer dentro de una página JSP: Scriptlets Expresiones Scriptlets Son porciones de código Java mezclados con el lenguaje de marcas de la página. Un scriptlet, o fragmento de código, puede consistir de una o más líneas de código Java y se puede usar con el código HTML o JSP para configurar saltos condicionales o bucles por ejemplo. Un scriptlet JSP está contenido dentro de los símbolos <%...%> y se escribe usando la sintaxis Java. Expresiones Se evalúan y convierten a valores de String y luego son mostradas en la ubicación respectiva dentro de la página. Una expresión JSP no termina en “;”. Está contenida dentro de los símbolos: <%=...%>. Objeto request
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
16
El objeto request está disponible de forma automática por lo que no es necesario instanciarlo. getParameter(String), permite recuperar una variable enviada por url. setAttribute(String, Object), para cargar (setear) el objeto en el request. getAttribute(String), para recuperar el objeto Ejercicio 03: Acceso.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Insert title here
AccesoAction.jsp
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
17
<% String mensaje="",codigo; codigo=request.getParameter("txt_codigo"); int digito=Integer.parseInt(""+codigo.charAt(0)); if(digito>=1 && digito<=4) mensaje="Grupo Sistemas"; else if(digito==5) mensaje="Gerencia General"; else if(digito>=6 && digito<=8) mensaje="Portal Web"; else mensaje="No existe Area"; request.setAttribute("msj", mensaje); pageContext.forward("Respuesta.jsp"); %>
Respuesta.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Insert title here <% String msj=(String)request.getAttribute("msj"); %>
Acceso a : <%=msj%>
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
18
Ejercicio 04: Registro.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Insert title here
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
19
RegistroAction.jsp <% String mensaje[]=new String[3]; String datos,destino; datos=request.getParameter("txt_ape_nom"); destino=request.getParameter("cbo_destino"); mensaje[0]=datos; mensaje[1]=destino; if(destino.equals("Cajamarca")) mensaje[2]="150.00"; else if(destino.equals("Trujillo")) mensaje[2]="180.00"; else if(destino.equals("Arequipa")) mensaje[2]="210.00"; else mensaje[2]="170.00"; request.setAttribute("msj", mensaje); pageContext.forward("Ayuda.jsp"); %>
Ayuda.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Insert title here <% String msj[]=(String[])request.getAttribute("msj"); %>
Cliente : <%=msj[0]%> El precio del destino <%=msj[1]%> es de S/. <%=msj[2] %> nuevos soles.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
1.2
20
JQuery, Servlet y JSP
1.2.1. JQuery JQuery es una librería gratuita y open source que simplifica la creación de páginas web altamente interactivas. Funciona en todos los exploradores de internet modernos y abstrae características específicas de cada uno de estos, permitiéndonos enforcarnos en el diseño y resultado final, en lugar de tratar de desarrollar funciones complejas en exploradores individuales. Específicamente jQuery facilita:
La búsqueda y manipulación de contenido en una página HTML; Trabajar con el modelo de eventos de los exploradores modernos; Y añadir efectos y transiciones sofisticadas que vemos en páginas modernas, como animaciones disparadas por eventos.
1.2.2. Validación Una de las tareas más comunes en los sistemas, sea web o escritorio, es la validación de campos, ya que a partir de la información que se genere en formularios, ésta será enviada para ser procesada. Para realizar la validación usamos los siguientes archivos:
jquery-1.11.3.js, es la librería principaldel JQuery. jquery.validate.js, continene los métodos para realizar la validación en los formularios. jquery.metadata.js, Su funcionamiento permite incluir datos adicionales dentro de nuestro código HTML, estos datos utilizan el formato JSON
Ejercicio 01: registrarPelicula.jsp
Validar lo siguiente:
Ingresar en forma obligatoria: Nombre, Duración, Director, Actores, Sinopsis. Duración solo número de 1 a 3 cifras
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
21
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8">
Registro de Pelicula <script type="text/javascript" src="js/jquery-1.11.3.js"> <script type="text/javascript" src="js/jquery.validate.js"> <script type="text/javascript" src="js/jquery.metadata.js"> <script type="text/javascript"> $(document).ready(function() { $("#dataPelicula").validate(); });
Nota: Si trabajamos con jquery.validation hay que tener claros que son los métodos de validación y las reglas de validación. Los métodos de validación implementan el código necesario para validar un elemento. Tenemos disponibles un número considerable de métodos de validación para las comprobaciones más habituales, pero siempre es posible agregar a jquery.validation nuestras propias validaciones personalizadas. Por otro lado, las reglas de validación permiten asociar un elemento de nuestro formulario a uno o más métodos de validación. Para asociar una regla de validación a un elemento, podemos hacerlo de las siguientes formas y pueden combinarse según nuestras necesidades:
A través de nombres de clases css en atributo class. Por ejemplo class=”required number” especifica que nuestro elemento será requerido y sólo aceptará números. Estos nombres de clases no tienen por qué existir en la hoja de estilos, son clases que utilizará sólo jquery.validation.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
23
A través de código javascript y añadiendo las reglas a través del objeto rules.
En el formulario de la página registrarPelicula.jsp se observa lo siguiente:
Se ha especificado las reglas de validación a través de nombres de clases. Se ha llamado al método validate() para el elemento dataPelicula, que configura el formulario para que sea validado. A partir de este momento, el formulario no podrá ser enviado al servlet: ServletMantenimientoPelicula si no cumple con las reglas impuestas. Para mostrar los mensajes se tiene que abrir el archivo jquery.validate.js y proceder a realizar los siguientes cambios:
1.2.3. Arquitectura del Servlet Un servlet es un componente JEE que extiende la capacidad de proceso de un servidor que emplea el paradigma request – response. Por lo tanto, “Un servlet es una clase Java que recibe requerimientos de un cliente para cumplir con un servicio; luego de cumplir con el servicio, envía la respuesta hacia el cliente.”
Petición (Request)
Servidor web
Respuesta (Response) Cliente ejecutando un Browser
CIBERTEC
Aplicación web Servlets
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
24
La API Servlet se constituye de dos paquetes básicos:
javax.servlet javax.servlet.http
Ciclo de Vida de un SERVLET
El ciclo de vida del servlet está compuesto de tres fases: a) El método init. Este método es llamado por el servidor de aplicaciones cuando el servlet se está cargando en memoria. b) El método service. Este método es llamado por cada petición de cliente. Para las peticiones HTTP, este método se ha especializado para enviar la petición al método doGet o doPost. c) El método destroy. Este método es llamado por el servidor de aplicaciones cuando el servlet es descargado de memoria. Los Servlets son cargados en memoria en la primera petición de un cliente o cuando el servidor de aplicaciones arranca. Cada petición de cliente es servida sobre un diferente hilo (thread); por lo tanto, muchos clientes pueden acceder al mismo código en paralelo. Es responsabilidad del desarrollador sincronizar los accesos a los recursos compartidos. Se pueden crear Servlets de un solo hilo (SingleThread) implementando la interfaz: javax.servlet.SingleThreadModel
La clase HTTPSERVLET Los clientes web (browsers) interactúan con los Servlets usando el protocolo HTTP (Request-Response); por lo tanto, para crear Servlets que soporten este protocolo, se debe heredar de la clase javax.servlet.http.HttpServlet. La clase HttpServlet provee una estructura de trabajo adecuada para manipular el protocolo HTTP junto con los métodos GET y POST. Métodos de la clase HttpServlet
protected doDelete(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to void
handle a DELETE request. protected doGet(HttpServletRequest req, HttpServletResponse resp) void Called by the server (via the service method) to allow a servlet to
handle a GET request. protected doHead(HttpServletRequest req, HttpServletResponse resp) Receives an HTTP HEAD request from the protected service void
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
25
method and handles the request. protected doOptions(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to void
handle a OPTIONS request. protected doPost(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to void
handle a POST request. protected doPut(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to void
handle a PUT request. protected doTrace(HttpServletRequest req, HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to void
handle a TRACE request. protected getLastModified(HttpServletRequest req) Returns the time the HttpServletRequest object was last modified, long
in milliseconds since midnight January 1, 1970 GMT. protected service(HttpServletRequest req, HttpServletResponse resp) Receives standard HTTP requests from the public service method void
and dispatches them to the doXXX methods defined in this class. void
service(ServletRequest req, ServletResponse res)
Dispatches client requests to the protected service method.
Métodos de la clase HttpServletRequest String
getAuthType()
Returns the name of the authentication scheme used to protect
the servlet String
getContextPath()
Returns an array containing all of the Cookie objects the client sent with this request. Cookie[]
getCookies()
Returns an array containing all of the Cookie objects the client sent with this request. long
getDateHeader(String name)
Returns the value of the specified request header as a long value that represents a Date object. String
getHeader(String name)
Returns the value of the specified request header as a String. Enumeration getHeaderNames()
Returns an enumeration of all the header names this request contains. int
getIntHeader(String name)
Returns the value of the specified request header as an int. String
getMethod()
Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
String
26
getPathInfo()
Returns any extra path information associated with the URL the client sent when it made this request. String
getPathTranslated()
Returns any extra path information after the servlet name but before the query string, and translates it to a real path. String
getQueryString()
Returns the query string that is contained in the request URL after the path. String
getRemoteUser()
Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated. String
getRequestedSessionId()
Returns the session ID specified by the client. String
getRequestURI()
Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. StringBuffe getRequestURL() r Reconstructs the URL the client used to make the request. getServletPath() String
Returns the part of this request's URL that calls the servlet. HttpSession getSession()
Returns the current session associated with this request, or if the request does not have a session, creates one. HttpSession getSession(boolean create)
Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session. boolean
getUserPrincipal()
Returns a java.security.Principal object containing the name of the current authenticated user. boolean
isRequestedSessionIdFromCookie()
boolean
isRequestedSessionIdFromURL()
Checks whether the requested session ID came in as a cookie.
Checks whether the requested session ID came in as part of the request URL. boolean
isRequestedSessionIdValid()
Checks whether the requested session ID is still valid. boolean
isUserInRole(String role)
Returns a boolean indicating whether the authenticated user is included in the specified logical "role".
DESPACHADOR DE LA PETICIÓN (Request Dispatcher) El despachador de la petición (RequestDispatcher) permite remitir una petición (request) a otro servlet o a otro componente JEE. Un objeto RequestDispatcher es obtenido de la siguiente manera: RequestDispatcher rd=getServletContext ().getRequestDispatcher (“ruta”); Una vez obtenido el objeto RequestDispatcher, invocamos al otro recurso (servlet) enviándole el objeto request.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
27
rd.forward (request, response) Hay que registrar el servlet MyForwardServlet para lo cual debemos modificar el archivo web.xml. COMPARTIENDO OBJETOS Existen dos formas de compartir objetos entre Servlets:
El objeto ServletContext y
El objeto HttpServletRequest
El ServletContext es usado cuando un grupo de Servlets necesitan trabajar con un mismo objeto. El servlet que desea compartir el objeto usa el método setAttribute del objeto ServletContext y otro servlet dentro del contexto de Servlets que desea tomar el objeto usa el método getAttribute. Ejemplo: Servlet 1 (compartiendo objeto) : MiClase elObjeto = new MiClase (); getServletContext ().setAttribute(“objeto”, elObjeto); Servlet 2 (tomando objeto): MiClase elObjeto; ElObjeto =(MiClase)getServletContext().getAttribute(“objeto”);
HttpServletRequest es usado cuando al hacer uso de una remisión (forward) se necesita compartir un objeto entre Servlets. El servlet que desea compartir el objeto usa el método setAttribute del objeto HttpServletRequest y el otro servlet usa el método getAttribute. Ejemplo: MiClase elObjeto = new MiClase(); request.setAttribute(“objeto”,elObjeto); El Objeto =(MiClase)request.getAttribute(“objeto”); Java Server Pages JSP Un JSP es un servlet; por lo tanto, es un componente web que se encuentra en el lado del servidor. Un JSP tiene código Java dentro del código en HTML (embedded); a diferencia de los Servlets que pueden generar HTML desde código Java. “Los JSPs son utilizados para generar páginas web dinámicas. “ No es muy frecuente encontrar programadores Java buenos en diseño html o diseñadores de html buenos programando en Java; por ello, JSP es la solución para separar roles: “Un jsp tiene poco código Java que puede ser fácilmente entendido por un diseñador html.”
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
28
Ejemplo:
Saludo <% String miAlias=request.getParameter(“miAlias”); %>
Hola <%=miAlias%>
CICLO DE VIDA DEL JSP Antes de poder ser ejecutado, un jsp debe ser convertido en un servlet de Java. Esto es hecho en dos etapas:
El texto jsp es traducido en código Java. El código java es compilado en servlet. El servlet resultante procesa las peticiones http. El proceso de traducido y compilado es realizado una sola vez antes de procesar la primera petición http; luego, el servlet resultante tiene el mismo ciclo de vida que cualquier servlet. Los equivalentes a los métodos init, service y destroy son los siguientes:
jspInit, _jspService jspDestroy
DIRECTIVAS JSP Las directivas JSP son usadas para definir información al traductor java acerca de la página. La sintaxis es la siguiente:
<%@ directiva[ atributo=valor ] %>
Directiva include. Se usa para definir el contenido de otro archivo en elJSP. Ejemplo:
Prueba <%@ include file=”loguito.html”%>
Directiva page. Se usa para definir las características de las cuales va a depender la página. La directiva aplica a todo el JSP incluso los archivos incluidos con la directiva include.
Directiva page info. Define una cadena de texto que es ubicada en el método Servlet.getServletInfo() del código traducido. Ejemplo:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
29
<%@ page info=”En el mar, la vida es más sabrosa” %>
Directiva page import. Se usa para importar una lista de nombres de paquetes separados por comas. Ejemplo: <%@ page import=”java.math.*,java.util.*” %>
Directiva page errorPage. Se usa para redireccionar un cliente a un URL específico cuando ocurre una excepción que no ha sido capturada en la página. Ejemplo: <%@ page errorPage=”/jsps/error.jsp” %>
Directiva page isErrorPage. Se usa para indicar si la página es un “target” válido (destino) de una directiva page errorPage. El valor por defecto es false. Ejemplo: <%@ page isErrorPage=”true” %> <%@ page isErrorPage=”false” %>
JSP SCRIPTING
El scripting es utilizado para codificar el JSP. El scripting está conformado de:
Declarations
Scriplets
Expressions
a) Declarations. Son utilizadas para declarar métodos y variables de instancia en el servlet JSP. Sintaxis: <%! Declaración %> Ejemplo: <%! private int contador = 0; %>
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
30
b) Scriplets. Se utilizan para escribir código Java en el JSP. Sintaxis: <% código_java %> Ejemplo: <%String sexo = request.getParameter(“ sexo”); If(sexo.equals(“M”)) { %>
Sr. <% }else{ %>
Sra. <% } %> c)
Expressions. Las expresiones son para incluir directamente dentro de la salida de la página cadenas (Strings), que son el resultado de evaluar una expresión de código Java y luego convertirla en una cadena. Sintaxis: <%= expression %> Ejemplo: La fecha actual es <%=new java.util.Date() %>
INTERACCIÓN CON UN JSP Existen tres formas básicas de interactuar con un JSP: a)
Un JSP puede ser invocado por su URL. Ejemplo: http://nombreservidor/aplicacionweb/nombrejsp.jsp
b)
Un JSP puede ser invocado desde un servlet usando el método forward del objeto RequestDispatcher. Ejemplo: String miRuta = “/jsps/consultas.jsp”; RequestDispatcher rd = getServletContext().getRequestDispatcher(miRuta); Rd.forward(request,response);
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
31
c) Un Servlet o un JSP pueden ser invocados desde un JSP usando la etiqueta
o la etiqueta . Ejemplo:
texto texto OBJETOS IMPLÍCITOS EN EL JSP El código JSP puede acceder a información del servlet usando objetos implícitos definidos por cada página. Los objetos implícitos son variables predefinidas (no necesitamos declararlas) que se pueden referenciar en el código Java del JSP.
Objeto request. Contiene la información de petición del actual HTTP request.
Objeto session. Contiene la información de la sesión del cliente. Es una instancia de la clase javax.servlet.http.HttpSession.
Objeto out. Es usado para las salidas de texto que se quieran incluir en la página.
Objeto Application. Contiene información del contexto de todos los componentes web de la misma aplicación web. Es una instancia de la clase javax.servlet.ServletContext
ATRIBUTOS DEL SCOPE (ÁMBITO) Un JSP puede acceder a objetos en tiempo de ejecución vía uno de los siguientes scopes o ámbitos:
request (Es el objeto HttpServletRequest Actual)
session (Es el objeto HttpSession actual)
application (Es el objeto ServletContext actual)
a) Request Scope. Este ámbito se constituye en la vía más adecuada para que un servlet pase referencias de objetos al JSP. Las referencias a objetos con ámbito Request son almacenadas en el objeto request. Se usa lo siguiente:
setAttribute(String,Object) para cargar (setear) el objeto en el request.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
32
getAttribute(String) para recuperar el objeto.
b) Session Scope. Se puede acceder a este ámbito desde Servlets y páginas JSP que están procesando peticiones que se encuentran en la misma sesión. Las referencias a los objetos son perdidas después que la sesión asociada es finalizada. Las referencias a los objetos con ámbito Session son almacenadas en el objeto session. Se usa lo siguiente:
setAttribute(String,Object) para cargar(setear) el objeto en la sesión getAttribute(String) para recuperar el objeto
c) Application Scope. Se puede acceder a este ámbito desde Servlets y páginas JSP que están procesando peticiones que se encuentran en la misma aplicación web. (El mismo contexto) Las referencias a los objetos con ámbito Application son almacenadas en el objeto application. Se usa lo siguiente:
setAttribute(String,Object) para cargar(setear) el objeto en el contexto getAttribute(String) para recuperar el objeto
OBJETOS IMPLÍCITOS EN UN JSP OBJETO request response out
SIGNIFICADO El objeto HttpServletRequest asociado con la petición El objeto HttpServletResponse asociado con la respuesta El Writer empleado para enviar la salida al cliente. La salida de los JSP emplea un buffer que permite que se envíen cabeceras HTTP o códigos de estado aunque ya se haya empezado a escribir en la salida (out no es un PrintWriter, sino un objeto de la clase especial JspWriter). El objeto HttpSession asociado con la petición actual. En JSP, las session sesiones se crean automáticamente, de modo que este objeto está instanciado aunque no se cree explícitamente una sesión. application El objeto ServletContext, común a todos los Servlets de la aplicación web config El objeto ServletConfig, empleado para leer parámetros de inicialización pageContext Permite acceder desde un único objeto a todos los demás objetos implícitos page Referencia al propio servlet generado (tiene el mismo valor que this).Como tal, en Java no tiene demasiado sentido utilizarla, pero está pensada para el caso en que se utilizara un lenguaje de programación distinto. exception Representa un error producido en la aplicación. Solo es accesible si la página se ha designado como página de error (mediante la directiva page isErrorPage)
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
33
Ejercicio 01: registrarNota.jsp
Realizar las siguientes operaciones: Todas las cajas deben aceptar datos de forma obligatoria DNI, solo números de 8 cifras Parcial y final solo números entre 1 y 20
Código |<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8"> Registro de Notas <script type="text/javascript" src="js/jquery-1.11.3.js"> <script type="text/javascript" src="js/jquery.validate.js"> <script type="text/javascript" src="js/jquery.metadata.js"> <script type="text/javascript"> $(document).ready(function() { $("#frmRegistro").validate(); }); Registro de Notas DNI Apellidos y Nombres: CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
34
Curso: Algebra Lenguaje Historia Ingles Parcial: Final:
ServletNota Captura los valores enviados por el formulario que se encuentra en la página registrarNota.jsp, realiza el cálculo del promedio y adiciona 4 o 2 puntos según la condición establecida. Luego envía un arreglo de tipo String algunos datos del Servlet a la página respuesta.jsp. Package controlador; @WebServlet("/ServletNota") public class ServletNota extends HttpServlet { private static final long serialVersionUID = 1L; public ServletNota() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dni,ape_nom,curso; int parcial,fin,adicional,promedio; String valores[]=new String[4]; dni=request.getParameter("txt_dni"); ape_nom=request.getParameter("txt_ape_nom"); curso=request.getParameter("cbo_curso"); parcial=Integer.parseInt(request.getParameter("txt_parcial")); fin=Integer.parseInt(request.getParameter("txt_final")); if(curso.equals("Algebra")|| curso.equals("Historia")) adicional=4; else adicional=2; promedio=((parcial+2*fin)+adicional)/3; request.setAttribute("info", valores); valores[0]=dni;valores[1]=ape_nom; valores[2]=curso;valores[3]=""+promedio; request.getRequestDispatcher("respuesta.jsp").forward(request, response); } } CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
35
respuesta.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta charset="utf-8"> Insert title here <% String msj[]=(String[])request.getAttribute("info"); %> DNI : <%=msj[0]%> Alumno : <%=msj[1]%> Curso : <%=msj[2]%> Promedio : <%=msj[3]%>
1.3
JDBC – Aplicaciones parte I
Connection, Class.forName Java Database Connectivity, más conocida por sus siglas JDBC es una API que permite la ejecución de operaciones sobre bases de datos desde el lenguaje de programación Java, independientemente del sistema operativo donde se ejecute o de la base de datos a la cual se accede, utilizando el dialecto SQL del modelo de base de datos que se utilice. El API JDBC se presenta como una colección de interfaces Java y métodos de gestión de manejadores de conexión hacia cada modelo específico de base de datos. Un manejador de conexiones hacia un modelo de base de datos en particular es un conjunto de clases que implementan las interfaces Java y que utilizan los métodos de registro para declarar los tipos de localizadores a base de datos (URL) que pueden manejar. Para utilizar una base de datos particular, el usuario ejecuta su programa junto con la biblioteca de conexión apropiada al modelo de su base de datos, y accede a ella estableciendo una conexión; para ello provee el localizador a la base de datos y los parámetros de conexión específicos. A partir de allí puede realizar cualquier tipo de tarea con la base de datos a la que tenga permiso: consulta, actualización, creación, modificación y borrado de tablas, ejecución de procedimientos almacenados en la base de datos, etc.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
36
Pasos de la Conexión
1.3.1 Aplicación de Logueo Modelo de base de datos: instituto
Script base de datos
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
37
Pasos a seguir: 1. Crear un proyecto web y construya la siguiente estructura:
Dónde: entidad: misServlets: utils: img: js:
2.
Almacena la clase Alumno(Definir atributos) Almacena los Servlets del proyecto(ServletListado, ServletLogueo, ServletMantenimiento) Almacena la clase para conexión con la base de datos (MysqlDBConexion) Almacena las imágenes (delete.gif,edit.gif ) Almacena los archivos de JQuery para realizar validaciones
Crear la clase MysqlDBConexion y guardarlo en el paquete utils.
package utils; import java.sql.Connection; import java.sql.DriverManager; public class MysqlDBConexion { public static Connection getConexion(){ Connection cn=null; try { Class.forName("com.mysql.jdbc.Driver"); cn=DriverManager.getConnection("jdbc:mysql://localhost/instituto", "root","mysql"); } catch (Exception e) { e.printStackTrace(); } return cn; } }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
38
3. Crear la clase Alumno y guardarlo en el paquete entidad. package entidad; public class Alumno { private int codigo; private String nombre,paterno,materno; private int edad; public int getCodigo() { return codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getPaterno() { return paterno; } public void setPaterno(String paterno) { this.paterno = paterno; } public String getMaterno() { return materno; } public void setMaterno(String materno) { this.materno = materno; } public int getEdad() { return edad; } public void setEdad(int edad) { this.edad = edad; } }
4. Crear la clase Empleado y guardarlo en el paquete entidad. package entidad; public class Empleado { private int codigo; private String nombre,apelliedos; private String login,clave; public int getCodigo() { return codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApelliedos() { return apelliedos; } CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
39
public void setApelliedos(String apelliedos) { this.apelliedos = apelliedos; } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getClave() { return clave; } public void setClave(String clave) { this.clave = clave; } }
5. Crear la clase ModelEmpleado y guardarlo en el paquete modelo. package modelo; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import entidad.Empleado; import utils.MysqlDBConexion; public class ModelEmpleado { public Empleado iniciarSesion(String log,String pas){ Empleado obj=null; Connection cn=null; ResultSet rs=null; PreparedStatement pstm=null; try { String sql="select *from tbempleado where login_emp=? and clave_emp=?"; cn=MysqlDBConexion.getConexion(); pstm=cn.prepareStatement(sql); pstm.setString(1, log); pstm.setString(2, pas); rs=pstm.executeQuery(); if(rs.next()){ obj=new Empleado(); obj.setCodigo(rs.getInt(1)); obj.setNombre(rs.getString(2)); obj.setApellidos(rs.getString(3)); obj.setLogin(rs.getString(4)); obj.setLogin(rs.getString(4)); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(rs!=null)rs.close(); if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return obj;y guardarlo en el paquete controlador. 6. Crear el ServletEmpleado } } CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
40
package controlador; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.annotation.WebServlet; import modelo.ModelEmpleado; import entidad.Empleado; @WebServlet("/ServletEmpleado") public class ServletEmpleado extends HttpServlet { ModelEmpleado m=new ModelEmpleado(); private static final long serialVersionUID = 1L; public ServletEmpleado() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String login,clave; login=request.getParameter("txtlogin"); clave=request.getParameter("txtpass"); Empleado e=m.iniciarSesion(login, clave); if(e==null){ request.setAttribute("msj", "Error usuario y/o clave"); request.getRequestDispatcher("index.jsp").forward( request,response); } else{ response.sendRedirect("menu.jsp"); } } }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
41
7. Crear la página index.jsp y guardarlo dentro de WebContent
Código: <% String x=(String) request.getAttribute("msj"); String a=""; if(x!=null) a=x; %> <%=a %>
En el ServletEmpleado se recupera los valores de las cajas: package controlador; @WebServlet("/ServletEmpleado") public class ServletEmpleado extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String login,clave; login=request.getParameter("txtlogin"); clave=request.getParameter("txtpass"); Empleado e=m.iniciarSesion(login, clave); if(e==null){ request.setAttribute("msj", "Error usuario y/o clave"); request.getRequestDispatcher("index.jsp").forward( request,response); } else{ response.sendRedirect("menu.jsp"); } }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
42
Si ingresamos un usuario y/o clave en forma incorrecta se mostrara lo siguiente
Si los datos ingresados son corretos se mostrara la página menú.jsp
8. Crear la página menu.jsp y guardarlo dentro de WebContent <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here Listar Alumnos Registrar Alumno
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
43
1.3.2 Aplicación de Listado Pasos a seguir Usando el proyecto anterior (LPII_Clase02), realizar lo siguiente: 1. Crear la clase ModelAlumno y guardarlo dentro del paquete modelo. package modelo; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import utils.MysqlDBConexion; import entidad.Alumno; public class ModelAlumno { public List listar(){ Alumno alu=null; List data=new ArrayList(); Connection cn=null; ResultSet rs=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="select *from tb_alumno"; pstm=cn.prepareStatement(sql); rs=pstm.executeQuery(); while(rs.next()){ alu=new Alumno(); alu.setCodigo(rs.getInt(1)); alu.setNombre(rs.getString(2)); alu.setPaterno(rs.getString(3)); alu.setMaterno(rs.getString(4)); alu.setEdad(rs.getInt(5)); data.add(alu); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(rs!=null)rs.close(); if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return data; } }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
44
2. Crear el ServletAlumno y guardarlo dentro del paquete controlador. package controlador; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import entidad.Alumno; import modelo.ModelAlumno; public class ServletAlumno extends HttpServlet { ModelAlumno m=new ModelAlumno(); private static final long serialVersionUID = 1L; public ServletAlumno() { super(); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String tipo=request.getParameter("tipo"); if(tipo.equals("listar")) listar(request,response); } private void listar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List info=new ModelAlumno().listar(); request.setAttribute("data", info); request.getRequestDispatcher("listarAlumno.jsp").forward( request, response); } }
3. Crear la página listarAlumno.jsp y guardarlo dentro de WebContent. <%@page import="entidad.Alumno"%> <%@page import="java.util.List"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here <% List da= (List)request.getAttribute("data"); %> LISTADO DE ALUMNOS + Nuevo Registro
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
45
CODIGO NOMBRES PARTENO MATERNO EDAD ACCIONES <% if(da!=null){ for(Alumno a:da){ %> <%=a.getCodigo()%> <%=a.getNombre()%> <%=a.getPaterno()%> <%=a.getMaterno()%> <%=a.getEdad()%> <% } } %>
Se mostrara el siguiente resultado:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
46
1.4 JDBC – Aplicaciones parte II 1.4.1 Aplicación de Mantenimiento Pasos a seguir Usando el proyecto anterior (LPII_Clase02), realizar lo siguiente: 1. Agregar los siguientes métodos dentro de la clase ModelAlumno. public Alumno buscarAlumno(int cod){ Alumno alu=null; Connection cn=null; PreparedStatement pstm=null; ResultSet rs=null; try { cn=MysqlDBConexion.getConexion(); String sql="select *from tb_alumno where cod_alu=?"; pstm=cn.prepareStatement(sql); pstm.setInt(1, cod); rs=pstm.executeQuery(); if(rs.next()){ alu=new Alumno(); alu.setCodigo(rs.getInt(1)); alu.setNombre(rs.getString(2)); alu.setPaterno(rs.getString(3)); alu.setMaterno(rs.getString(4)); alu.setEdad(rs.getInt(5)); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(rs!=null) rs.close(); if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return alu; } public int registrarAlumno(Alumno obj){ int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="insert into tb_alumno values(null,?,?,?,?)"; pstm=cn.prepareStatement(sql); pstm.setString(1, obj.getNombre()); pstm.setString(2, obj.getPaterno()); pstm.setString(3, obj.getMaterno()); pstm.setInt(4, obj.getEdad()); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
47
finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; } public int actualizarAlumno(Alumno obj){ int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="update tb_alumno set nom_alu=?,pat_alu=?, mat_alu=?,edad_alu=? where cod_alu=?"; pstm=cn.prepareStatement(sql); pstm.setString(1, obj.getNombre()); pstm.setString(2, obj.getPaterno()); pstm.setString(3, obj.getMaterno()); pstm.setInt(4, obj.getEdad()); pstm.setInt(5, obj.getCodigo()); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; } public int eliminarAlumno(int cod){ int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="delete from tb_alumno where cod_alu=?"; pstm=cn.prepareStatement(sql); pstm.setInt(1, cod); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
2.
48
Modificar el ServletAlumno según la siguiente imagen:
protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { String tipo=request.getParameter("tipo"); if(tipo.equals("listar")) listar(request,response); else if(tipo.equals("registrar")) registrar(request,response); else if(tipo.equals("buscar")) buscar(request,response); else if(tipo.equals("actualizar")) actualizar(request,response); else if(tipo.equals("eliminar")) eliminar(request,response); } private void actualizar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Alumno obj=new Alumno(); String cod=request.getParameter("txt_cod"); String nom=request.getParameter("txt_nom"); String pat=request.getParameter("txt_pat"); String mat=request.getParameter("txt_mat"); String edad=request.getParameter("txt_edad"); obj.setCodigo(Integer.parseInt(cod)); obj.setNombre(nom); obj.setPaterno(pat); obj.setMaterno(mat); obj.setEdad(Integer.parseInt(edad)); int estado=m.registrarAlumno(obj); if(estado!=-1) listar(request, response); else response.sendRedirect("error.html"); } private void registrar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Alumno obj=new Alumno(); String nom=request.getParameter("txt_nom"); String pat=request.getParameter("txt_pat"); String mat=request.getParameter("txt_mat"); String edad=request.getParameter("txt_edad"); obj.setNombre(nom); obj.setPaterno(pat); obj.setMaterno(mat); obj.setEdad(Integer.parseInt(edad)); int estado=m.registrarAlumno(obj); if(estado!=-1) listar(request, response); else response.sendRedirect("error.html"); }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
49
private void buscar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dato=request.getParameter("cod"); int codigo=Integer.parseInt(dato); Alumno x=m.buscarAlumno(codigo); request.setAttribute("registro", x); request.getRequestDispatcher("actualizarAlumno.jsp"). forward(request, response); } private void eliminar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dato=request.getParameter("cod"); int codigo=Integer.parseInt(dato); m.eliminarAlumno(codigo); request.getRequestDispatcher("ServletListado"). forward(request, response); }
3.
Modificar la página listarAlumno,jsp según la siguiente imagen:
if(da!=null){ for(Alumno a:da){ %> <%=a.getCodigo()%> <%=a.getNombre()%> <%=a.getPaterno()%> <%=a.getMaterno()%> <%=a.getEdad()%> "> "> <% } } %>
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
4.
50
Crear la página actualizarAlumno.jsp
Código: <%@page import="entidad.Alumno"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here <% Alumno a=(Alumno)request.getAttribute("registro"); %> CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
5.
51
Crear la página registrarAlumno.jsp
Código: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here <script type="text/javascript" src="js/jquery.js"> <script type="text/javascript" src="js/jquery.metadata.js"> <script type="text/javascript" src="js/jquery.validate.js"> <script type="text/javascript"> $(document).ready( function(){ $("#frmregistro").validate({ rules:{ txtnom:{ required:true, letras:true }, txtapepat:{ required:true, minlength:3 }, txtapemat:{ required:true, minlength:3 } }, messages:{ txtnom:{ required:"Ingrese Nombre", letras:"solo letras" }, txtapepat:{ required:"Ingrese Apellido Paterno", minlength:"Mínimo 3 letras" }, txtapemat:{ required:"Ingrese Apellido Materno", minlength:"Mínimo 3 letras" } } }); }); CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
52
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
53
Resumen 1. Las etiquetas HTML 5 permiten mejorar el aspecto de las páginas y usar Responsive Design. 2. El uso de la librería JQuery permite realizar validaciones en los formularios y a la vez poder crear nuestras propias validaciones con sus mensajes personalizados. 3. Para la creación de validaciones tenemos que usar expresiones regulares o trabajar directamente con JavaScript. 4. El uso de un servlet dentro de una sistema web permite la comunicación entre vista con el modelo usando el paradigma request y response. 5. El uso de métodos dentro del servlet permitirá ordenar las sentencias que se han implementado en el modelo debido a que estos últimos son invocados según el requerimiento del usuario
6. Si desea saber más acerca de estos temas, puede consultar las siguientes páginas. http://today.java.net/pub/a/today/2003/12/04/exceptions.html Aquí hallará importantes reglas básicas para la gestión de excepciones en java. http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Exception.html En esta página, hallará documentación detallada de la clase base de todas las excepciones controladas: Exception
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
54
UNIDAD
2 CRUD con patrón DAO, sesiones y EL LOGRO DE LA UNIDAD DE APRENDIZAJE Al término de la unidad, el alumno implementa una aplicación Java Web usando el patrón DAO, sesiones y Lenguaje de Expresiones (EL).
TEMARIO 2.1 Tema 5 2.1.1 2.1.2 2.1.3 2.2 Tema 6 2.2.1 2.2.2 2.23 2.2.4
: : : : : : : : :
Patrón DAO Parte I
Patrones de diseño de software Patrón DAO Aplicación Listado Patrón DAO Parte II, Sesiones web y EL Lenguaje de expresiones Aplicación Mantenimiento Sesiones web Aplicación de Logueo
Actividades propuestas
Implementar un aplicativo web usando el patrón DAO Crear aplicaciones con conexión a base de datos que resuelvan casos prácticos de la vida real. Trabajar con sesiones que permitan a cada usuario logueado poder trabajar con su propia sesión.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
55
2.1 Patrón DAO Parte I 2.1.1 Patrones de Diseño de Software El diseño es un modelo del sistema, realizado con una serie de principios y técnicas, que permite describir el sistema con el suficiente detalle como para ser implementado. Sin embargo, los principios y reglas no son suficientes. En el contexto de diseño, podemos observar que los buenos ingenieros tienen esquemas y estructuras de solución que usan numerosas veces en función del contexto del problema. Este es el sentido cabal de la expresión "tener una mente bien amueblada", y no el significado de tener una notable inteligencia. Estos esquemas y estructuras son conceptos reusables y nos permiten no reinventar la rueda. Un buen ingeniero reutiliza un esquema de solución ante problemas similares. Historia El concepto de "patrón de diseño" que tenemos en Ingeniería del Software se ha tomado prestado de la arquitectura. En 1977, se publica el libro "A Pattern Language: Towns/Building/Construction", de Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King y Shlomo Angel, Oxford University Press. Contiene numerosos patrones con una notación específica de Alexander. Alexander comenta que “cada patrón describe un problema que ocurre una y otra vez en nuestro entorno, para describir después el núcleo de la solución a ese problema, de tal manera que esa solución pueda ser usada más de un millón de veces sin hacerlo siquiera dos veces de la misma forma”. El patrón es un esquema de solución que se aplica a un tipo de problema. Esta aplicación del patrón no es mecánica, sino que requiere de adaptación y matices. Por ello, dice Alexander que los numerosos usos de un patrón no se repiten dos veces de la misma forma. La idea de patrones de diseño estaba "en el aire", la prueba es que numerosos diseñadores se dirigieron a aplicar las ideas de Alexander a su contexto. El catálogo más famoso de patrones se encuentra en “Design Patterns: Elements of Reusable Object-Oriented Software”, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, 1995, Addison-Wesley, también conocido como el libro GOF (Gang-OfFour). Siguiendo el libro de GOF, los patrones se clasifican según el propósito para el que han sido definidos: · · ·
Creacionales: solucionan problemas de creación de instancias. Nos ayudan a encapsular y abstraer dicha creación. Estructurales: solucionan problemas de composición (agregación) de clases y objetos. De Comportamiento: soluciones respecto a la interacción y responsabilidades entre clases y objetos, así como los algoritmos que encapsulan.
Según el ámbito, se clasifican en patrones de clase y de objeto:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
Clase
Creación Método de Fabricación
56
Estructural Adaptador (clases)
Objeto
Fábrica, Constructor, Prototipo, Singleton
CARRERA DE COMPUTACIÓN E INFORMÁTICA
Adaptador (objetos), Puente, Composición, Decorador, Fachada, Flyweight
De Conducta Interprete Plantilla Cadena de Responsabilidad, Comando (orden), Iterador, Intermediario, Observador, Estado, Estrategia, Visitante, Memoria
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
57
Catálogo de patrones J2EE
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
58
Capa de Presentación
Decorating Filter / Intercepting Filter
Front Controller/ Front Component
View Helper
Composite view
Service To Worker
Dispatcher View
CARRERA DE COMPUTACIÓN E INFORMÁTICA
Un objeto que está entre el cliente y los componentes web. Este procesa las peticiones y las respuestas. Un objeto que acepta todos los requerimientos de un cliente y los direcciona a manejadores apropiados. El patrón Front Controller podría dividir la funcionalidad en 2 diferentes objetos: el Front Controller y el Dispatcher. En ese caso, El Front Controller acepta todos los requerimientos de un cliente y realiza la autenticación, y el Dispatcher direcciona los requerimientos a manejadores apropiada Un objeto helper que encapsula la lógica de acceso a datos en beneficio de los componentes de la presentación. Por ejemplo, los JavaBeans pueden ser usados como patrón View Helper para las páginas JSP. Un objeto vista que está compuesto de otros objetos vista. Por ejemplo, una página JSP que incluye otras páginas JSP y HTML usando la directiva include o el action include es un patrón Composite View. Es como el patrón de diseño MVC con el Controlador actuando como Front Controller pero con una cosa importante: aquí el Dispatcher (el cual es parte del Front Controller) usa View Helpers a gran escala y ayuda en el manejo de la vista. Es como el patrón de diseño MVC con el controlador actuando como Front Controller pero con un asunto importante: aquí el Dispatcher (el cual es parte del Front Controller) no usa View Helpers y realiza muy poco trabajo en el manejo de la vista. El manejo de la vista es manejado por los mismos componentes de la Vista
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
59
Capa de Negocios
Business Delegate
Value Object/ Data Transfer Object/ Replicate Object
Session Façade/ Session Entity Façade/ Distributed Facade
Aggregate Entity Value Object Assembler
Value List Handler/ Page-by-Page Iterator/ Paged List
Service Locator
Un objeto que reside en la capa de presentación y en beneficio de los otros componentes de la capa de presentación llama a métodos remotos en los objetos de la capa de negocios. Un objeto serializable para la transferencia de datos sobre la red. El uso de un bean de sesión como una fachada (facade) para encapsular la complejidad de las interacciones entre los objetos de negocio y participantes en un flujo de trabajo. El Session Façade maneja los objetos de negocio y proporciona un servicio de acceso uniforme a los clientes. Un objeto que reside en la capa de negocios y crea Value Objets cuando es requerido Es un objeto que maneja la ejecución de consultas SQL, caché y procesamiento del resultado. Usualmente implementado como beans de sesión Es como el patrón de diseño MVC con el controlador actuando como Front Controller pero con un asunto importante: aquí el Dispatcher (el cual es parte del Front Controller) no usa View Helpers y realiza muy poco trabajo en el manejo de la vista. El manejo de la vista es manejado por los mismos componentes de la Vista Consiste en utilizar un objeto Service Locutor para abstraer toda la utilización JNDI y para ocultar las complejidades de la creación del contexto inicial, de búsqueda de objetos home EJB y recreación de objetos EJB. Varios clientes pueden reutilizar el objeto Service Locutor para reducir la complejidad del código, proporcionando un punto de control.
Capa de Integración
Data Access Object Service Activator
Service Activator
CIBERTEC
Consiste en utilizar un objeto de acceso a datos para abstraer y encapsular todos los accesos a la fuente de datos. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos. Se utiliza para recibir peticiones y mensajes asíncronos de los clientes. Cuando se recibe un mensaje, el Service Activator localiza e invoca a los métodos de los componentes de negocio necesarios para cumplir la petición de forma asíncrona.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
60
Concepto de patrón de diseño "Una arquitectura orientada a objetos bien estructurada está llena de patrones. La calidad de un sistema orientado a objetos se mide por la atención que los diseñadores han prestado a las colaboraciones entre sus objetos. Los patrones conducen a arquitecturas más pequeñas, más simples y más comprensibles". (Grady Booch) Los patrones de diseño son descripciones de clases cuyos objetos colaboran entre sí. Cada patrón es adecuado para ser adaptado a un cierto tipo de problema. Para describir un caso se debe especificar lo siguiente:
Nombre Propósito o finalidad Sinónimos (otros nombres por los que puede ser conocido) Problema al que es aplicable Estructura (diagrama de clases) Participantes (responsabilidad de cada clase) Colaboraciones (diagrama de interacciones) Implementación (consejos, notas y ejemplos) Otros patrones con los que está relacionado
Ventajas de los patrones: La clave para la reutilización es anticiparse a los nuevos requisitos y cambios, de modo que los sistemas evolucionen de forma adecuada. Cada patrón permite que algunos aspectos de la estructura del sistema puedan cambiar independientemente de otros aspectos. Facilitan la reusabilidad, extensibilidad y mantenimiento. Un patrón es un esquema o microarquitectura que supone una solución a problemas (dominios de aplicación) semejantes (aunque los dominios de problema pueden ser muy diferentes e ir desde una aplicación CAD a un cuadro de mando empresarial). Interesa constatar una vez más la vieja distinción entre dominio del problema (donde aparecen las clases propias del dominio, como cuenta, empleado, coche o beneficiario) y el dominio de la solución o aplicación (donde además aparecen clases como ventana, menú, contenedor o listener). Los patrones son patrones del dominio de la solución. También, conviene distinguir entre un patrón y una arquitectura global del sistema. Por decirlo en breve, es la misma distancia que hay entre el diseño de un componente (o módulo) y el análisis del sistema. Es la diferencia que hay entre el aspecto micro y el macro; por ello, en ocasiones, se denomina a los patrones como "microarquitecturas". En resumen, un patrón es el denominador común, una estructura común que tienen aplicaciones semejantes. Esto también ocurre en otros órdenes de la vida. Por ejemplo, en nuestra vida cotidiana, aplicamos a menudo el esquema saludopresentación- mensaje-despedida en ocasiones diversas.
2.1.2 Patrón DAO Contexto El acceso a los datos varía dependiendo de la fuente de los datos. El acceso al almacenamiento persistente, como una base de datos, varía en gran medida dependiendo del tipo de almacenamiento (bases de datos relacionales, bases de datos orientadas a objetos, archivos de texto, etc.) y de la implementación del vendedor.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
61
Problema Muchas aplicaciones de la plataforma JEE en el mundo real necesitan utilizar datos persistentes en algún momento. Para muchas de ellas, este almacenamiento persistente se implementa utilizando diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder a esos mecanismos de almacenamiento diferentes o datos residentes en sistemas diferentes. Típicamente, las aplicaciones utilizan componentes distribuidos compartidos persistentes como los entity bean para representar la data persistente. Una aplicación es considerada que empleará un bean managed persistence para sus entity beans cuando estas entity beans explícitamente accesen al almacén persistente, es decir, cuando el entity bean incluya código para acceder directamente al almacén persistente. Una aplicación con requerimientos simples no utilizaría entity beans y, en vez de ellos, utilizaría session beans o Servlets para acceder directamente al almacén persistente para recuperar y modificar datos. Las aplicaciones pueden usar la API-JDBC para acceder a los datos que residen en un RDBMS. Esta API permite el acceso estándar y la manipulación de datos en un almacén persistente como una base de datos relacional. JDBC permite a las aplicaciones JEE utilizar sentencias SQL estándar. Sin embargo, las sentencias SQL podrían v ariar dependiendo del DBMS. Solución Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la fuente de datos. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos. El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos. El Objeto de Acceso a Datos (DAO) es el objeto principal de este patrón. La fuente de datos podría ser un almacén persistente como un RDBMS, un servicio externo como B2B, un servicio de negocios accesado vía CORBA. Los componentes del negocio que cuentan con los objetos DAO utilizan una interfaz simple expuesta por el DAO para sus clientes. El DAO completamente oculta la implementación de la fuente de datos y lo aparta de los clientes, debido a que la interfaz expuesta por el DAO no cambia cuando la implementación de la fuente de datos cambia. Este patrón permite al DAO adaptarse a diferentes esquemas de almacenamiento sin afectar a sus clientes o componentes de negocio. DAO esencialmente actúa como un adaptador entre el componente de negocio y la fuente de datos (data source).
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
62
Diagrama de Clases
ESTRATEGIAS DE IMPLEMENTACIÓN DEL PATRÓN DAO Factory El patrón DAO se puede flexibilizar adoptando los patrones Factory y Abstract Factory. Cuando el almacenamiento asociado a la aplicación no está sujeto a cambios de una implementación a otra, esta estrategia se puede implementar utilizando el patrón Factory para producir el número de DAOs que necesita la aplicación. En la siguiente figura, podemos ver el diagrama de clases para este caso:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
63
Abstract Factory Cuando el almacenamiento asociado a la aplicación sí está sujeto a cambios de una implementación a otra, esta estrategia se podría implementar usando el patrón Abstract Factory. Este patrón a su vez puede construir y utilizar la implementación Factory. En este caso, esta estrategia proporciona un objeto factoría abstracta de DAOs (Abstract Factory) que puede construir varios tipos de factorías concretas de DAOs: cada factoría soporta un tipo diferente de implementación del almacenamiento persistente. Una vez que obtenemos la factoría concreta de DAOs para una implementación específica, la utilizamos para producir los DAOs soportados e implementados en esa implementación. En la siguiente figura, podemos ver el diagrama de clases para esta estrategia. En él vemos una fábrica base de DAOs, que es una clase abstracta que extienden e implementan las diferentes factorías concretas de DAOs para soportar el acceso específico a la implementación del almacenamiento. El cliente puede obtener una implementación de la factoría concreta del DAO como una RdbDAOFactory y utilizarla para obtener los DAOs concretos que funcionan en la implementación del almacenamiento. Por ejemplo, el cliente puede obtener una RdbDAOFactory y utilizarlas para obtener DAOs específcios como RdbCustomerDAO, RdbAccountDAO, etc. Los DAOs pueden extender e implementar una clase base genérica (mostradas como DAO1 y DAO2) que describa específicamente los requerimientos del DAO para el objeto de negocio que soporta. Cada DAO concreto es responsable de conectar con la fuente de datos y de obtener y manipular los datos para el objeto de negocio que soporta.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
64
En la siguiente figura, podemos ver el diagrama de secuencia para esta estrategia:
Contexto resultante DAO permite la transparencia de los detalles de la implementación de la fuente de datos. El acceso es transparente porque los detalles de la implementación se ocultan dentro del DAO. La capa de DAO’s permite una migración más fácil, hace más fácil que una aplicación pueda migrar a una implementación de base de datos diferente. Los objetos de negocio no conocen la implementación de datos subyacente; la migración implica cambios sólo en la capa DAO. Reduce la Complejidad del Código de los Objetos de Negocio. Centraliza todos los accesos a datos en una capa independiente.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
65
2.1.3 Aplicación Listado Estructura del Programa
Modelo de Datos
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
66
Pasos: 1.
Crear la clase ProductoDTO dentro del paquete beans, con los siguientes atributos privados, e implemente los métodos de acceso: set y get.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
67
package beans; public class ProductoDTO { private int codigo; private String descripcion; private double precio; private int stock; private int codMarca; private String nomMarca; public int getCodigo() { return codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getDescripcion() { return descripcion; } public void setDescripcion(String descripcion) { this.descripcion = descripcion; } public double getPrecio() { return precio; } public void setPrecio(double precio) { this.precio = precio; } public int getStock() { return stock; } public void setStock(int stock) { this.stock = stock; } public int getCodMarca() { return codMarca; } public void setCodMarca(int codMarca) { this.codMarca = codMarca; } public String getNomMarca() { return nomMarca; } public void setNomMarca(String nomMarca) { this.nomMarca = nomMarca; } }
2.
Crear una interface ProductoDAO dentro del paquete interfaces, con los siguientes métodos:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
68
3.
Registrar los DAOs(interface) dentro de la clase DAOFactory
4.
En la clase DAOFactory se mostrará
la siguiente imagen:
Esto sucede porque la clase MySqlDAOFactory no existe o se ha realizado cambios en el DAOFactory como registrar más DAOs (RECORDAR).
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
69
5.
Hacer clic en el foco y se mostrará la siguiente imagen:
6.
Hacer doble clic en Create class “MySqlDAOFactory” y se mostrará la siguiente ventana:
7.
Clic en botón Finish.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
70
8.
Se mostrará una clase nueva con el nombre: MySqlDAOFactory, como se muestra en la siguiente imagen:
9.
En la clase MySqlDAOFactory escribir lo siguiente:
10. Clic en el foco y se mostrará la siguiente imagen:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
71
11. Hacer doble clic en Create class “MySqlProductoDAO”, se mostrará la siguiente ventana:
12. Clic en el botón Finish y se mostrará la siguiente imagen:
Se puede observar que en esta clase se debe implementar los métodos creados en la interface ProductoDAO, es aquí donde se debe escribir los códigos para listar, insertar, modificar, eliminar y buscar.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
72
13. Implementar el código para listar los registros de la tabla tb_producto, escribir las siguientes líneas dentro del método listarProducto().
14. Crear una clase ProductoService dentro del paquete service y escribir los siguientes códigos:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
73
15. Crear un Servlet con el nombre: ServletProducto dentro del paquete misServlets y escriba lo siguiente:
16. En la página listarProducto.jsp escribir lo siguiente:
17. En la página encabezado.jsp escribir lo siguiente:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
74
18. Cuando se ejecuta la página encabezado.jsp se muestra la siguiente figura:
. 19. Clic en Listar y se muestra lo siguiente:
2.2 Patrón DAO Parte II y Sesiones Web y EL 2.2.1 Lenguaje de Expresiones EL es un lenguaje para acceder a datos de varias fuentes en tiempo de ejecución. Su sintaxis es considerablemente más amigable que la de Java, que es el único lenguaje soportado directamente por la especificación JSP 1.2. Todas las acciones JSTL reconocen expresiones EL en sus valores de atributos, y se podrían desarrollar acciones personalizadas para que hicieran lo mismo. Se espera que EL sea incorporado dentro de la próxima versión de la especificación JSP para mejorar su uso en el acceso a los datos sobre el lenguaje Java. Si es así, podremos usar expresiones EL en un valor de atributo de una acción, o incluso en una plantilla de texto. EL toma prestada de JavaScript la sintaxis para acceder a estructuras de datos tanto como propiedades de un objeto (con el operador.) como con elementos con nombres de un array (con el operador ["nombre"]). Como se ve aquí, una expresión EL siempre debe estar encerrada entre los caracteres $ { y } $. Las dos primeras expresiones acceden a una propiedad llamada myProperty en un objeto representado por una variable llamada myObj. La tercera expresión accede a una propiedad con un nombre contenido en una variable. Esta sintaxis se puede utilizar con cualquier expresión que evalúe el nombre de la propiedad. Estas etiquetas tratan de abstraer la complejidad de introducir código Java (scriptlet) dentro de JSP, del mismo modo que trata de evitar que cada equipo de desarrollo cree un juego de etiquetas no estándar para las mismas labores. sessionScope-------------------recupera una variable de sesión requestScope-------------------recupera variable que el servlet envía a un jsp
2.2.2 Aplicación Mantenimiento Trabajar con el proyecto anterior: Proyecto_DAO2. Pasos a seguir:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
1.
75
Implementar los métodos que se encuentra en la clase “MySqlProductoDAO”:
package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import utils.MysqlDBConexion; import beans.ProductoDTO; import interfaces.ProductoDAO; public class MySqlProductoDAO implements ProductoDAO{ @Override public ProductoDTO buscarProducto(int cod) { ProductoDTO obj=null; Connection cn=null; PreparedStatement pstm=null; ResultSet rs=null; try { cn=MysqlDBConexion.getConexion(); String sql="select *from tb_producto where cod_pro=?"; pstm=cn.prepareStatement(sql); pstm.setInt(1, cod); rs=pstm.executeQuery(); if(rs.next()){ obj=new ProductoDTO(); obj.setCodigo(rs.getInt(1)); obj.setDescripcion(rs.getString(2)); obj.setPrecio(rs.getDouble(3)); obj.setStock(rs.getInt(4)); obj.setNomMarca(rs.getString(5)); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(rs!=null)rs.close(); if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return obj; }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
76
@Override public int registrarProducto(ProductoDTO obj) { int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="insert into tb_producto values(null,?,?,?,?)"; pstm=cn.prepareStatement(sql); pstm.setString(1, obj.getDescripcion()); pstm.setDouble(2, obj.getPrecio()); pstm.setInt(3, obj.getStock()); pstm.setInt(4, obj.getCodMarca()); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; } @Override public int actualizarProducto(ProductoDTO obj) { int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="update tb_producto set des_pro=?,pre_pro=?,stock_act_pro=?,cod_mar= ? where cod_pro=?"; pstm=cn.prepareStatement(sql); pstm.setString(1, obj.getDescripcion()); pstm.setDouble(2, obj.getPrecio()); pstm.setInt(3, obj.getStock()); pstm.setInt(4, obj.getCodMarca()); pstm.setInt(5, obj.getCodigo()); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
77
@Override public int eliminarProducto(int cod) { int estado=-1; Connection cn=null; PreparedStatement pstm=null; try { cn=MysqlDBConexion.getConexion(); String sql="delete from tb_producto where cod_pro=?"; pstm=cn.prepareStatement(sql); pstm.setInt(1, cod); estado=pstm.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ try { if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } return estado; } @Override public List listarProducto() { List data=new ArrayList(); ProductoDTO obj=null; Connection cn=null; PreparedStatement pstm=null; ResultSet rs=null; try { cn=MysqlDBConexion.getConexion(); String sql="select p.cod_pro,p.des_pro,p.pre_pro,p.stock_act_pro," + "m.nom_mar from tb_producto p inner join tb_marca m " + "on p.cod_mar=m.cod_mar"; pstm=cn.prepareStatement(sql); rs=pstm.executeQuery(); while(rs.next()){ obj=new ProductoDTO(); obj.setCodigo(rs.getInt(1)); obj.setDescripcion(rs.getString(2)); obj.setPrecio(rs.getDouble(3)); obj.setStock(rs.getInt(4)); obj.setNomMarca(rs.getString(5)); data.add(obj); } } catch (Exception e) { e.printStackTrace(); } return data; }
}
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
78
2. Modificar la clase ProductoService: package service; import interfaces.ProductoDAO; import java.util.List; import utils.Constantes; import dao.DAOFactory; import beans.ProductoDTO; public class ProductoService { DAOFactory fabrica=DAOFactory.getDAOFactory(Constantes.ORIGEN_DATOS); ProductoDAO objPro=fabrica.getProducto(); public List listaProducto() { return objPro.listarProducto(); } public ProductoDTO buscaProducto(int cod) { return objPro.buscarProducto(cod); } public int registraProducto(ProductoDTO obj) { return objPro.registrarProducto(obj); } public int actualizaProducto(ProductoDTO obj) { return objPro.actualizarProducto(obj); } public int EliminaProducto(int cod) { return objPro.eliminarProducto(cod); } }
3.
Modificar el servlet ServletProducto:
package misServlets; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import beans.ProductoDTO; import service.ProductoService; public class ServletProducto extends HttpServlet { private static final long serialVersionUID = 1L; ProductoService serviProducto=new ProductoService(); protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String xtipo=request.getParameter("tipo"); if(xtipo.equals("listar")) listar(request,response); else if(xtipo.equals("buscar")) buscar(request,response); else if(xtipo.equals("registrar")) registrar(request,response); else if(xtipo.equals("actualizar")) actualizar(request,response); else if(xtipo.equals("eliminar")) eliminar(request,response); }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
79
private void eliminar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int cod=Integer.parseInt(request.getParameter("cod")); serviProducto.EliminaProducto(cod); listar(request, response); } private void buscar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int cod=Integer.parseInt(request.getParameter("cod")); request.setAttribute("Producto",serviProducto.buscaProducto(cod)); request.getRequestDispatcher("actualizarProducto.jsp"). forward(request, response); } private void actualizar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int marca,stock,cod; cod=Integer.parseInt(request.getParameter("txt_cod")); String des=request.getParameter("txt_des"); double pre=Double.parseDouble(request.getParameter("txt_pre")); stock=Integer.parseInt(request.getParameter("txt_stock")); marca=Integer.parseInt(request.getParameter("cbo_marca")); ProductoDTO obj=new ProductoDTO(); obj.setCodigo(cod); obj.setDescripcion(des); obj.setPrecio(pre); obj.setStock(stock); obj.setCodMarca(marca); serviProducto.actualizaProducto(obj); listar(request, response); } private void registrar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int marca,stock; String des=request.getParameter("txt_des"); double pre=Double.parseDouble(request.getParameter("txt_pre")); stock=Integer.parseInt(request.getParameter("txt_stock")); marca=Integer.parseInt(request.getParameter("cbo_marca")); ProductoDTO obj=new ProductoDTO(); obj.setDescripcion(des); obj.setPrecio(pre); obj.setStock(stock); obj.setCodMarca(marca); serviProducto.registraProducto(obj); listar(request, response); } private void listar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setAttribute("data", serviProducto.listaProducto()); request.getRequestDispatcher("listarProducto.jsp"). forward(request, response); } }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
80
4. Cuando se ejecuta la página encabezado.jsp se muestra la siguiente figura:
5. Clic en Nuevo, se mostrará la página: registrarProducto.jsp
Código: <%@page import="beans.MarcaDTO"%> <%@page import="java.util.ArrayList"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here <script type="text/javascript" src="js/jquery.js"> <script type="text/javascript" src="js/jquery.metadata.js"> <script type="text/javascript" src="js/jquery.validate.js"> <script type="text/javascript"> $(document).ready( function(){ $("#frmagregar").validate(); }); Descripcion Precio Stock
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
81
Marca SAMSUNG HP SONY
6.
Cuando se ejecuta la página encabezado.jsp se muestra la siguiente figura:
7. Clic en Listar, se mostrará la página: listarProducto.jsp
8. Cuando se selecciona un registro para buscar, se muestra la siguiente página: actualizarProducto.jsp:
Código: <%@page import="beans.ProductoDTO"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here <script type="text/javascript" src="js/jquery.js"> <script type="text/javascript" src="js/jquery.metadata.js"> <script type="text/javascript" src="js/jquery.validate.js">
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
82
<script type="text/javascript"> $(document).ready( function(){ $("#frmagregar").validate(); }); <% ProductoDTO obj=(ProductoDTO)request.getAttribute("Producto"); %>
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
83
2.2.3 Sesiones Web HTTPSESSION En una transacción http, cada conexión entre un cliente y un servidor es muy breve. Esta es una característica típica de cualquier protocolo sin estado (staless). El protocolo http no mantiene el estado, es decir, no tiene un mecanismo para saber que una serie de peticiones (request) provienen de un mismo cliente. Ante esta limitación, surge la sesión como el mecanismo adecuado para identificar un usuario que está interactuando con el sitio web. La sesión puede ser implementada a través de diferentes opciones:
HttpSession Campos ocultos HTML(hidden fields) Cookies URL Rewriting
La interfaz HttpSession es parte de la API de Servlets y proporciona una alternativa para manejar el estado de una aplicación en un servidor web. OBTENIENDO UNA SESIÓN Las sesiones son compartidas por todos los Servlets y jsps accesados por un cliente; por lo tanto, es común que se cree un objeto Sesión cuando nos “logueamos” a un sitio web. Por otro lado, si nos “deslogueamos” de un sitio web, la sesión debería ser destruida. En Java, el objeto HttpSession identifica una sesión y es obtenida utilizando el método getSession del objeto request. Ejemplo: HttpSession miSesion = req.getSession(true);
Sintaxis: request.getSession() o request.getSession(true). Retornan la sesión actual si existe; de lo contrario, crean una nueva. request.getSession(false). Retorna la sesión actual si existe; de lo contrario, retorna un objeto nulo. CONTENIDO DE LA SESIÓN El objeto HttpSession contiene información acerca de la sesión. Para acceder a esta información, existen una serie de métodos getters de los cuales mostraremos los más utilizados:
session.getLastAccessedTime(). La última vez que el cliente envió una petición asociada con la sesión. session.getCreationTime(). Cuando la sesión fue creada. session.getMaxInactiveInterval(). El intervalo de tiempo máximo (en segundos) que el Servlet Container mantiene abierta la sesión entre accesos del cliente
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
84
session.getAttribute(). Obtiene un objeto que fue almacenado en la sesión
ALMACENANDO Y RECUPERANDO OBJETOS DE LA SESIÓN La utilidad de una sesión radica en su capacidad de actuar como un repositorio donde se almacenan datos de la aplicación. Los datos son almacenados como un par <”nombre”, valor> siendo valor cualquier objeto que se desee almacenar en la sesión. Los métodos para acceder a los datos son los siguientes: session.setAttribute(String, Object). Sirve para almacenar objetos en la sesión. session.getAttribute(String). Sirve para recuperar objetos de la sesión. Ejemplo:
HttpSession session = req.getSession(true); String nombre=” Cesar Vallejo ”; session.setAttribute("miNombre",nombre);
La sesión puede ser finalizada de diferentes formas:
Programáticamente Por tiempo de expiración Cuando el usuario cierra el browser
Programáticamente: a) Usando el método invalidate() del objeto session b) Removiendo todos los objetos de la sesión con el método removeAttribute() Sintaxis: removeAttribute(String nombreAtributo) nombreAtributo es el nombre del atributo a ser removido. HttpSession session = req.getSession(true); session.removeAttribute(“nombre”); session.invalidate();
Por tiempo de expiración: La sesión es invalidada cuando se cumple un tiempo de inactividad de la sesión. Podemos definir el tiempo de inactividad máximo de dos formas: a) Utilizando el método setMaxInactiveInterval(int) Ejemplo: session.setMaxInactiveInterval(int) b) Utilizando la etiqueta dentro del archivo web.xml :
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
85
30
2.2.4 Aplicación de Logueo Trabajar con el proyecto anterior: Proyecto_DAO2. Pasos a seguir: 1. Crear una clase EmpleadoDTO y guardarlo en la carpeta beans. package beans; public class EmpleadoDTO { private int codigo; private String nombres; private String apellidos; private String login; private String password; public int getCodigo() { return codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getNombres() { return nombres; } public void setNombres(String nombres) { this.nombres = nombres; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
86
2. Crear una interface con el nombre EmpleadoDAO y guardarlo en el paquere interfaces.
3. Registrar el DAO en la clase DAOFactory
4. Actualizar la clase MySqlDAOFactory.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
87
5. En la clase MySqEmpleadolDAO, programar lo siguiente. package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import utils.MysqlDBConexion; import beans.EmpleadoDTO; import interfaces.EmpleadoDAO; public class MySqlEmpleadoDAO implements EmpleadoDAO{ @Override public EmpleadoDTO IniciarSesion(String xlogin) { EmpleadoDTO em=null; Connection cn=null; PreparedStatement pstm=null; ResultSet rs=null; try { cn=MysqlDBConexion.getConexion(); String sql="select *from tb_empleado where log_emp=?"; pstm=cn.prepareStatement(sql); pstm.setString(1, xlogin); rs=pstm.executeQuery(); if(rs.next()){ em=new EmpleadoDTO(); em.setCodigo(rs.getInt(1)); em.setNombres(rs.getString(2)); em.setApellidos(rs.getString(3)); em.setLogin(rs.getString(4)); em.setPassword(rs.getString(5)); } } catch (Exception e) { e.printStackTrace(); }finally{ try { if(rs!=null)rs.close(); if(pstm!=null)pstm.close(); if(cn!=null)cn.close(); } catch (Exception e2) { e2.printStackTrace(); } } 6. dd return em; } }
7. Crear la clase EmpleadoService, programar lo siguiente.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
88
8. Crear el servlet ServletEmpleado, programar lo siguiente. package misServlets; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import beans.EmpleadoDTO; import service.EmpleadoService; public class MantenimientoEmpleado extends HttpServlet { private static final long serialVersionUID = 1L; EmpleadoService servicio=new EmpleadoService(); protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String xtipo=request.getParameter("tipo"); if(xtipo.equals("sesion")) iniciarSesion(request,response); else if(xtipo.equals("cerrarSesion")) cerrarSesion(request,response); } private void cerrarSesion(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession sesion=request.getSession(); sesion.invalidate(); request.setAttribute("msg", "Iniciar sesión"); request.getRequestDispatcher("index.jsp"). forward(request, response); } private void iniciarSesion(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String xlogin=request.getParameter("txt_login"); String xpass=request.getParameter("txt_pass"); EmpleadoDTO obj=servicio.IniciaSesion(xlogin); if(obj!=null){ if(obj.getPassword().equals(xpass)){ HttpSession sesion=request.getSession(); sesion.setAttribute("datos",obj); request.getRequestDispatcher("encabezado.jsp"). forward(request, response); } else{ request.setAttribute("msg", "Contraseña incorrecta..."); request.getRequestDispatcher("index.jsp"). forward(request, response); } } else{ request.setAttribute("msg", "Usuario no existe..."); request.getRequestDispatcher("index.jsp"). forward(request, response); } } }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
89
9. Crear la página index.jsp, programar lo siguiente. <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here
10. Crear la página validar.jsp y escribir las siguientes instrucciones:
11. Modificar la página encabezado.jsp, para poder cerrar sesión:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
90
12. Llamar a validar.jsp y encabezado.jsp, en las páginas: listarProducto.jsp, registrarProducto.jsp y actualizarProducto.jsp, como se muestra en la siguiente imagen Página: listarProducto.jsp
Página: registrarProducto.jsp y actualizarProducto.jsp
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
91
Resumen 1. El catálogo más famoso de patrones se encuentra en “Design Patterns: Elements of Reusable Object-Oriented Software”, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides, 1995, Addison-Wesley, también conocido como el libro GOF (Gang-Of-Four). 2. Patrón Factory "Factoría" En realidad, son una familia de patrones:
Factoría simple: Una clase que crea objetos de otras clases. No delega en otras subclases y sus métodos pueden ser estáticos. Factory Method: Se define una interfaz para crear objetos, como en el Abstract Factory, pero se delega a las subclases implementar la creación en concreto. Abstract Factory: Da una interfaz para crear objetos de alguna familia, sin especificar la clase en concreto.
3. El uso de Lenguaje de Expresiones es obtener las propiedades de un objeto directamente a través de estas formas:
${myObj.myProperty}$ ${myObj["myProperty"]}$ ${myObj[varWithTheName]}$
4. Si desea saber más acerca de estos temas puede consultar las siguientes páginas.
http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html Aquí hallará definiciones y ejemplos sobre patrones. http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html Aquí hallará definiciones sobre los temas planteados.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
92
UNIDAD
3 Etiquetas, JSTL, Transacciones, Ajax y Listeners LOGRO DE LA UNIDAD DE APRENDIZAJE Al término de la unidad, el alumno implementa una aplicación Java Web que utilice Custom Tag, Java Standard Tag, Library (JSTL) y transacciones usando AJAX.
TEMARIO 3.1 Tema 7 3.1.1 3.1.2 3.1.3 3.1.4 3.2 Tema 8 3.2.1 3.2.2 3.2.3 3.3 Tema 3 3.3.1 3.3.2
: : : : : : : : : : : :
Custom Tag y JSTL Custom Tag Creación de etiquetas personalizadas (Custom TAG) JSTL y Librerías Aplicación Listado con JSTL Ajax y Transacciones en web Ajax Transacciones Aplicación Ajax y Transacción Listeners Tipos Aplicación Auditoria
Actividades propuestas Los alumnos resuelven ejercicios que involucran la creación de etiquetas personalizadas y el uso de JSTL para listar contenidos. Los alumnos implementan una aplicación con base de datos para realizar una transacción usando la Tecnología Ajax y aplicando auditoría.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
93
3.1 Custom Tag y JSTL 3.1.1 Custom Tag La tecnología JSP nos permite introducir código Java en páginas HTML. Este documento supone que está familiarizado con la creación de páginas JSP y que tiene instalado Apache-Tomcat (en realidad, valdría cualquier servidor de JSP que cumpla la especificación JSP 1.1, pero los ejemplos se han probado en Tomcat). Las JSP están compuestas por varios tags o, como las denominaremos en adelante, etiquetas. Ejemplos de etiquetas JSP son setProperty, include, forward, usebean. Todas ellas encapsulan comportamientos de una manera sencilla. Nos detendremos en la etiqueta . Esta etiqueta crea una instancia de una clase definida como un JavaBean. El uso de la etiqueta en conjunción con los JavaBeans hace que podamos separar la lógica de presentación de la de proceso y consigue unos archivos JSP más claros, y lo que es más importante, el que escribe la JSP no tiene por qué tener unos conocimientos avanzados de programación para crear páginas JSP de funcionalidades avanzadas. Pues bien, las JSP Custom Tags son un paso más allá. Con ellas se pueden añadir nuevas etiquetas a las ya existentes en JSP (eso sí a partir de la especificación JSP 1.1) que encapsulen comportamientos más o menos complicados. Antes de seguir, vamos a revisar algunos conceptos. Hay dos tipos principales de etiquetas: etiquetas que no tienen cuerpo y etiquetas que sí lo tienen. Ejemplos son la etiqueta que no tiene cuerpo y no tiene etiqueta de final; y manolo que tiene cuerpo y etiqueta de final. Estos son también los dos tipos de etiquetas JSP que nosotros podemos crear a medida. Entonces podemos decir que un Custom Tag permite la creación de etiquetas o librerías Tags personalizadas para separar la vista de la lógica de proceso logrando la reutilización de código. 3.1.2 Creación de etiquetas personalizadas (Custom TAG) Trabajar con el proyecto anterior y agregar el paquete tags dentro de src.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
94
Pasos: 1. 2.
Crear una clase con el nombre: TagMeses Realizar la herencia a la clase TagSupport, como se muestra en la siguiente imagen:
3.
Dentro de la clase “TagMeses” escribir doStartTag y pulsar CTRL + Barra Espaciadora y hacer doble clic en el método que se muestra para que se implemente.
Doble clic aquí
4.
Realizar el mismo procedimiento para doEndTag, la clase “TagMeses” quedara de la siguiente manera:
Nota: doStartTag: Se procesa la etiqueta de apertura. doEndTag: Se ejecuta despues de doStartTag.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
5.
95
Escribir el siguiente código:
Nota: JspWriter, es la clase que permite escribir un valor. SKIP_BODY, que se ejecute el cuerpo de la etiqueta creada. EVAL_PAGE, procesar el resto de JSP 6.
Crear una etiqueta personalizada(etiqueta select) que permita mostrar cualquier valor o valores que se ingresaran, crear una clase TagValores con el siguiente código:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
7.
96
Crear una etiqueta personalizada que muestre un mensaje según un valor que se ingresará. Crear una clase TagMensajes con el siguiente código:
Etiqueta personalizada (etiqueta select) que almacene los registros de una tabla (Marca). 8.
Crear una clase ComboDTO dentro del paquete beans con el siguiente código:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
9.
97
Crear una interface con el nombre ComboDAO dentro del paquete interfaces:
10. Proceda a registrar el DAO dentro de DAOFactory con el nombre getCombo().
11. Actualizar la clase MySqlDAOFactory
12. Programar en la clase MySqlComboDAO lo siguiente:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
98
13. Crear una clase dentro del paquete service con el nombre ComboService y escribir las siguientes instrucciones:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
99
14. Crear un archivo properties ”tags.properties” dentro de src, como se muestra a continuación:
15. Crear una clase TagComboDinamico dentro del paquete tags y escribir las siguientes instrucciones:
16. Crear un folder con el nombre: tag y un archivo con extensión tld dentro de WEBINF, para registrar las etiquetas personalizadas
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
100
17. El archivo tendrá la siguiente estructura:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
101
18. En la página registrarProducto.jsp, llamar al archivo tld creado.
19. Llamar la etiqueta personaliza “TagComboDinamico” para que almacene los registros de la tabla tb_marca
Cambiar por
20. Resultado al ejecutar la página:
21. En la página actualizarProducto.jsp, llamar al archivo tld creado.
22. Llamar la etiqueta personaliza “TagComboDinamico” para que almacene los registros de la tabla tb_marca y muestre seleccionado la marca según el producto escogido en el listado.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
102
Cambiar por
23. Ejecutar la página index.jsp, luego hacer clic en el menú listar y se mostrara la siguiente página:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
103
3.1.3 JSTL y Librerias JSTL responde a la demanda de los desarrolladores de un conjunto de acciones JSP personalizadas para manejar las tareas que necesitan casi todas las páginas JSP, incluyendo procesamiento condicional, internacionalización, acceso a bases de datos y procesamiento XML. Esto acelerará el desarrollo de JSPs más o menos eliminando la necesidad de elementos de scripting, y los inevitables y difíciles de encontrar errores de sintaxis; y liberando el tiempo anteriormente gastado en desarrollar y aprender trillones de acciones personalizadas específicas del proyecto para estas tareas comunes. JSTL 1.0 especifica un conjunto de librerías de etiquetas basadas en el API JSP 1.2. Hay cuatro librerías de etiquetas independientes, cada una contiene acciones personalizadas dirigidas a un área funcional específica. Esta tabla lista cada librería con su prefijo de etiqueta recomendado y la URI por defecto: Descripción Core XML Processing I18N & Formatting Database Access
Prefijo c x fmt sql
URI por Defecto http://java.sun.com/jstl/core http://java.sun.com/jstl/xml http://java.sun.com/jstl/fmt http://java.sun.com/jstl/sql
La Librería Core contiene acciones para las tareas rutinarias, como incluir o excluir una parte de una página dependiendo de una condición en tiempo de ejecución, hacer un bucle sobre una colección de ítems, manipular URLs para seguimiento de sesión, y la correcta interpretación del recurso objetivo. Asimismo, tiene acciones para importar contenido de otros recursos y redireccionar la respuesta a una URL diferente. La Librería XML contiene acciones para procesamiento XML, incluido validar un documento XML y transformarlo usando XSLT. También, proporciona acciones para extraer parte de un documento XML validado, hacer bucles sobre un conjunto de nodos y procesamiento condicional basado en valores de nodos. La Internacionalización (i18n) y el formateo general están soportados por las acciones de la Librería I18N & Formatting. Podemos leer y modificar información almacenada en una base de datos con las acciones proporcionadas por la Librería Database Access. Más adelante, podemos esperar que todos los contenedores web incluyan una implementación de las librerías JSTL, así no tendremos que instalar ningún código adicional. Hasta que esto suceda, podemos descargar e instalar la implementación de referencia (RI) de JSTL. Se ha desarrollado dentro del proyecto Apache Taglibs como una librería llamada Standard. Instalar RI es fácil, sólo hay que copiar los archivos JAR del directorio lib de la distribución al directorio WEB-INF/lib de nuestra aplicación. Obsérvese que JSTL 1.0 requiere un contenedor JSP 1.2; por ello, debemos asegurarnos de tener un contenedor compatible con JSP 1.2 antes de probar esto. Para usar una librería JSTL, tanto si la implementación está incluida con el contenedor o con el RI, debemos declarar la librería usando una directiva taglib, como lo haríamos con una librería de etiquetas personalizadas normal: <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
104
Obsérvese que siempre deberíamos usar la URI por defecto, incluso aunque la especificación JSP nos permita sobreescribirla. Un contenedor puede generar código optimizado para la acción JSTL en la clase correspondiente a una página JSP. Esto puede resultar en un mejor rendimiento que cuando el código generado llama a los manejadores de etiquetas a través del API estándar. Sin embargo, sólo cuando se usa la URI por defecto, es cuando el contenedor puede utilizar una implementación optimizada. El Lenguaje de Expresión JSTL Además de las librerías de etiquetas, JSTL 1.0 define un llamado Lenguaje de Expresiones (EL). EL es un lenguaje para acceder a datos de varias fuentes en tiempo de ejecución. Su sintaxis es considerablemente más amigable que la de Java, que es el único lenguaje soportado directamente por la especificación JSP 1.2. Todas las acciones JSTL reconocen expresiones EL en sus valores de atributos, y se podrían desarrollar acciones personalizadas para que hicieran lo mismo. Se espera que EL sea incorporado dentro de la próxima versión de la especificación JSP para mejorar su uso para acceder a datos sobre el lenguaje Java. Si es así, podremos usar expresiones EL en un valor de atributo de una acción, o incluso en una plantilla de texto. EL toma prestada de JavaScript la sintaxis para acceder a estructuras de datos tanto como propiedades de un objeto (con el operador.) como con elementos con nombres de un array (con el operador ["nombre"]). Las propiedades de los componentes JavaBeans y las entradas java.util.Map, que usan la clave como nombre de propiedad, pueden ser accedidas de esta forma. Aquí tenemos algunos ejemplos: ${myObj.myProperty}$ ${myObj["myProperty"]}$ ${myObj[varWithTheName]}$ Como se ve aquí, una expresión EL siempre debe estar encerrada entre los caracteres ${ y }$. Las dos primeras expresiones acceden a una propiedad llamada myProperty en un objeto representado por una variable llamada myObj. La tercera expresión accede a una propiedad con un nombre contenido en una variable. Esta sintaxis se puede utilizar con cualquier expresión que evalúe el nombre de la propiedad. El operador de acceso a array también se usa para datos representados como una colección de elementos indexados, como un array Java o una java.util.List: ${myList[2]}$ ${myList[aVar + 1]}$ Además de los operadores de propiedad y elemento array, y los operadores aritméticos, relacionales y lógicos, hay un operador especial para comprobar si un objeto está "vacío" o no puede ser usado en una expresión EL. La siguiente tabla lista todos los operadores: Operador . [] () + -
Descripción Accede a una propiedad. Accede a un elemento de un array/lista. Agrupa una subexpression. Suma Resta o negación de un número
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
/ o div % o mod == o eq != o ne < o lt > o gt <= o le >= o gt && o and || o or ! o not empty
105
División Módulo (resto) Comprueba Igualdad. Comprueba desigualdad. Comprueba menor que. Comprueba mayor que. Comprueba menor o igual que. Comprueba mayor o igual que. Comrpueba AND lógico. Comprueba OR lógico. Complemento binario booleano Comprueba un valor vacío (null, string vacío o una collección vacía)
Lo que no encontraremos en EL son sentencias como asignaciones, if/else o while. Para este tipo de funcionalidades, en JSP se usan los elementos Action. EL no está pensado para utilizarse como un lenguaje de programación de propósito general, sólo un lenguaje de acceso a datos. Cualquier objeto en uno de los ámbitos de JSP (página, solicitud, sesión o aplicación) se puede utilizar como una variable en una expresión EL. Por ejemplo, si tenemos un bean con una propiedad firstName en el ámbito de la solicitud bajo el nombre customer, esta expresión EL representa el valor de la propiedad firstName del bean. ${customer.firstName} Sin embargo, EL también hace que la información de la solicitud y la información general del contenedor esté disponible como un conjunto de variables implícitas: Variable Param paramValues Header headerValues Cookie initParams pageContext pageScope requestScope sessionScope applicationScope
Descripción Una collection de todos los valores de los parámetros de la solicitud como un sólo valor string para cada parámetro Una collection de todos los valores de los parámetros de la solicitud como un array de valores string por cada parámetro Una collection de todas las cabeceras de solicitud como un sólo valor string por cada cabecera Una collection de todos los valores de cabecera de la solicitud como un array de valores string por cada cabecera Una collection con todas las cookies de la solicitud en un sólo ejemplar de javax.servlet.http.Cookie por cada cokkie Una collection de todos los parámetros de inicialización de la aplicación en un sólo valor string por cada parámetro Un ejemplar de la clase javax.servlet.jspPageContext Una collection de todos los objetos en el ámbito de la página Una collection de todos los objetos en el ámbito de la solicitud Una collection de todos los objetos en el ámbito de la sesión Una collection de todos los objetos en el ámbito de la aplicación
Las cinco primeras variables implícitas de la tabla nos ofrecen acceso a los valores de parámetros, cabeceras y cookies de la solicitud actual. Aquí hay un ejemplo de cómo acceder a un parámetro de solicitud llamado listType y a la cabecera User-Agent:
${param.listType} ${header['User-Agent']}
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
106
Observe cómo se debe usar la sintaxis de array para la cabecera, porque el nombre incluye un guion; con la sintaxis de propiedad, sería interpretado como la expresión variable header.User menos el valor de una variable llamada Agent. La variable initParameter proporciona acceso a los parámetros de inicialización que se definen en el archivo web.xml de la aplicación. La variable pageContext tiene varias propiedades que proporcionan acceso al objeto servlet que representa la solicitud, la respuesta, la sesión y la aplicación, etc. Las cuatro últimas variables son colecciones que contienen todos los objetos de cada ámbito específico. Podemos usarlas para limitar la búsqueda de un objeto en sólo un ámbito en lugar de buscar en todos ellos, lo que está por defecto si no se especifica ningún ámbito. En otras palabras, si hay un objeto llamado customer en el ámbito de sesión, estas dos primeras expresiones encuentran el mismo objeto, pero la tercera vuelve vacía: ${customer} ${sessionScope.customer} ${requestScope.customer} Todas las acciones JSTL aceptan expresiones EL cómo valores de atributo, para todos los atributos excepto para var y scope, porque estos valores de atributo podrían usarse para chequear el tipo en el momento de la traducción en una futura versión. Hay un atributo de una acción JSTL adicional que no toma un valor de expresión EL, pero sólo se usa en la librería XML, por eso lo ignoraremos por ahora. Se pueden usar una o más expresiones EL en el mismo valor de atributo, y el texto fijo y las expresiones EL se pueden mezclar en el mismo valor de atributo: First name:
Antes de saltar a ver ejemplos de utilización de las acciones Core, se verá lo que dijimos anteriormente: todas las acciones JSTL de la librería EL aceptan expresiones EL. Realmente hay un conjunto paralelo de librerías JSTL, llamado conjunto de librería RT que sólo acepta expresiones Java del antiguo estilo: First name:
Procesamiento Condicional y Bucles Veamos algunos ejemplos de cómo podemos usar el JSTL condicional y las acciones de iteración: ; , , y un triple ; y . Por el camino, también usaremos acciones de salida básica y de selección de variables: y . nos permite incluir, o procesar, condicionalmente una parte de una página, dependiendo de la información durante la ejecución. Este ejemplo incluye un saludo personal si el usuario es un visitante repetitivo, según lo indica la presencia de una cookie con el nombre del usuario:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
107
Welcome back
El valor del atributo test es una expresión EL que chequea si la cookie existe. El operador empty combinado con el operador "not" (!) significa que evalúa a true si el cookie no existe, haciendo que el cuerpo del elemento sea procesado. Dentro del cuerpo, la acción añade el valor de la cookie a la respuesta. Así de sencillo. Pasar a través de una colección de datos es casi tan sencillo. Este fragmento itera sobre una colección de filas de una base de datos con información del tiempo de diferentes ciudades: City: Tomorrow's high: Tomorrow's low: La expresión EL para el valor items obtiene el valor de la propiedad rows desde un objeto representado por la variable forecasts. Como aprenderemos más adelante, las acciones de bases de datos de JSTL representan un resultado de consulta como un ejemplar de una clase llamada javax.servlet.jsp.jstl.sql.Result. Esta clase se puede utilizar como un bean con varias propiedades. La propiedad rows contiene un array de ejemplares java.util.SortedMap, donde cada uno representa una fila con valores de columnas. La acción procesa su cuerpo una vez por cada elemento de la colección especificado por el atributo ítems. Además de que con arrays, la acción funciona con cualquier otro tipo de dato que represente una colección, como ejemplares de las clases java.util.Collection o java.util.Map. Si se especifica el atributo var, el elemento actual de la colección se hace disponible para las acciones del cuerpo como una variable con el nombre especificado. Aquí se llamaba city y, como la colección es un array de maps, esta variable contiene un nuevo map con valores de columnas cada vez que se procesa el cuerpo. Los valores de las columnas se añaden a la respuesta por el mismo tipo de acciones que hemos visto en ejemplos anteriores. Para ilustrar el uso del resto de las acciones condicionales, extendamos el ejemplo de iteracción para procesar sólo un conjunto fijo de filas por cada página solicitada, añadamos enlaces "Previous" y "Next" a la misma página. El usuario puede entonces pasar sobre los resultados de la base de datos, mirando unas pocas filas cada vez, asumiendo que el objeto Result se ha grabado en el ámbito de la sesión. Aquí está cómo procesar sólo algunas filas:
City: Tomorrow's high: Tomorrow's low:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
108
La acción selecciona una variable con el valor especificado por el atributo value; que puede ser un valor estático, como en este ejemplo, o una expresión EL. También, podemos especificar el ámbito de la variable con el atributo scope (page, request, session o application). En este ejemplo, hemos seleccionado una variable llamada noOfRows a 10 en el ámbito de la página (por defecto). Este es el número de filas que mostraremos en cada solicitud. El , en este ejemplo, toma los mismos valores para los atributos ítems y var como antes, pero hemos añadido dos nuevos atributos: El atributo begin toma el índice (base 0) del primer elemento de la colección a procesar. Aquí se selecciona al valor de un parámetro de solicitud llamado first. Para la primera solicitud, este parámetro no está disponible, por eso la expresión se evalúa a 0; en otras palabras, la primea fila. El atributo end específica el índice del último elemento de la colección a procesar. Aquí lo hemos seleccionado al valor del parámetro first más noOfRows menos uno. Para la primera solicitud, cuando no existe el parámetro de la solicitud, este resultado es 9, por eso la acción itera sobre los índices del 0 al 9. Luego, añadimos los enlaces "Previous" y "Next":
"> Previous Page Previous Page "> Next Page Next Page
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
109
El agrupa una o más acciones , cada una especificando una condición booleana diferente. La acción chequea cada condición en orden y sólo permite la primera acción con una condición que se evalúe a true para procesar su cuerpo. El cuerpo también podría contener un . Su cuerpo sólo se procesa si ninguna de las condiciones de los es true. En este ejemplo, la primera acción comprueba si el parámetro first es mayor que cero, es decir, si la página muestra un subconjunto de filas distinto del primero. Si esto es cierto, el cuerpo de la acción añade un enlace a la misma página con un parámetro first seleccionado al índice del subconjunto anterior. Si no es true, se procesa el cuerpo de la acción , añadiendo sólo el texto "Previous Page". El segundo bloque proporciona lógica similar para añadir el enlace "Next Page".
Internacionalización y Formateo Las grandes sites normalmente necesitan complacer a los visitantes de todo el mundo, por lo que servir el contenido sólo en un idioma no es suficiente. Para desarrollar una site que proporcione una elección de idiomas, tenemos dos opciones: Escribir un conjunto de páginas para cada idioma Escribir un conjunto compartido de páginas que ponga el contenido en diferentes idiomas desde fuentes externas Frecuentemente, terminaremos con una mezcla de estas técnicas, usar páginas separadas para la mayoría de las grandes cantidades de contenido estático y páginas compartidas cuando la cantidad de contenido sea pequeña, pero dinámica (por ejemplo, una página con unas pocas etiquetas fijas mostradas en diferentes idiomas y todos los demás datos que vengan desde una base de datos). Preparar una aplicación para varios idiomas se llama internacionalización (comúnmente abreviado i18n); y hacer que el contenido esté disponible para un idioma específico se llama localización (o l10n). Para hacer esto, necesitamos considerar otras cosas además del idioma: cómo se formatean las fechas y números entre los diferentes países e, incluso, dentro de los países. También, podríamos necesitar adaptar los colores, las imágenes y otro contenido no textual. El término localidad se refiere a un conjunto de reglas y contenido aceptable para una región o cultura. Formateo de Fechas y Números Sensible a la Localidad JSTL incluye un conjunto de acciones para simplificar la internacionalización, principalmente cuando páginas compartidas se usan para varios idiomas. Primero, veamos cómo formatear apropiadamente fechas y números. Este ejemplo formatea la fecha actual y un número basándose en las reglas de la localidad por defecto: <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> Formatting with the default locale Date: Number: CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
110
La primera línea es la directiva taglib para la librería JSTL que contiene las acciones de formateo e internacionalización. El prefijo por defecto, usado aquí, es fmt. Para obtener un valor a formatear, entonces crea un objeto java.util.Date que representa la fecha y hora actuales, y lo graba como una variable llamada now. Ya estamos preparados para hacer algún formateo sensible a la localidad. La acción JSTL formatea el valor de la variable now asignado al valor del atributo value usando el tipo de expresión EL que aprendimos en la página anterior. El atributo dateStyle le dice a la acción cómo debe formatear la fecha. Podemos usar cualquiera de los valores default, short, medium, long, o full para el atributo dateStyle. El tipo de formateo que representa cada uno de estos tipos depende exactamente de la localidad. Para la localidad English, full resulta en un string como Thursday, August 29, 2002. En este ejemplo, sólo hemos formateado la parte de la fecha, pero también podemos incluir la parte de la hora (o formatear sólo la hora), y definir reglas de formateo personalizadas tanto para la fecha como para la hora en lugar de los estilos dependientes de la localidad: El atributo pattern toma un patrón de formateo personalizado del mismo tipo que la clase java.text.SimpleDateFormat. El patrón usado aquí resulta en Thursday, 29 August 2002, 17:29 con la localidad English. La acción soporta atributos similares para especificar cómo formatear un número usando estilos dependientes de la localidad para números normales, valores de moneda, o un porcentaje, así como usar patrones personalizados de diferentes tipos. Acceder a una Base de Datos Un sujeto de controversia es la inclusión en JSTL de acciones para acceder a bases de datos. Alguna gente ve esto como una mala práctica y argumenta que todos los accesos a bases de datos se deberían realizar desde componentes Java puros en una aplicación basada en MVC en lugar de desde página JSP. Este precepto es para aplicaciones que son extensas, ya que resulta bien práctico utilizar JSTL para aplicaciones sencillas. Sin el soporte de JSTL, estas aplicaciones normalmente terminan con el código para acceder a la base de datos dentro de scriptles, lo que es peor todavía para un mantenimiento y desarrollo correctos. Por lo tanto, veremos cómo acceder a bases de datos desde páginas JSP; sin embargo, esta aproximación no es la mejor para todos los tipos de aplicaciones. Si el equipo de desarrollo incluye programadores Java, se debería considerar seriamente encapsular el código de acceso a la base de datos en clases Java, y utilizar las JSP sólo para mostrar los resultados. Las acciones de bases de datos de JSTL están basadas en el API JDBC de Java y usan las abstracciones javax.sql.DataSource presentada en JDBC 2.0 para representar una base de datos. Un DataSource proporciona conexiones a una base de datos y puede implementar una característica llamada almacén de conexiones. Abrir una conexión física a una base de datos es una operación que consume mucho tiempo. Con el almacenamiento de conexiones, sólo necesitamos hacerlo una vez, y la misma conexión se puede reutilizar una y otra vez, sin los riesgos de problemas asociados con otras aproximaciones de compartición de conexiones.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
111
Poner un objeto DataSource a Disposición de JSTL JSTL soporta varias formas para hacer que un objeto DataSource esté disponible para las acciones de bases de datos. En un contenedor web con soporte JNDI (Java Naming and Directory Interface), se puede definir un DataSource por defecto como un recurso JNDI con un parámetro de contexto en el archivo web.xml: < context-param>
javax.servlet.jsp.jstl.sql.dataSource jdbc/Production Se deben utilizar las herramientas de configuración JNDI del contenedor WEB para configurar un recurso JNDI con el nombre especificado; por ejemplo, con un nombre de usuario y un password de una cuenta de usuario en una base de datos, las conexiones mínimas y máximas en el almacen, etc. La forma de realizar esto varía entre los contenedores y está fuera del ámbito de este artículo. Una alternativa para los contenedores que no soportan JNDI es que un oyente del ciclo de vida de la aplicación (contexto del servlet) cree y configure un DataSource y lo seleccione como el valor por defecto usando la clase Config de JSTL: import javax.servlet.*; import javax.servlet.http.*; import oracle.jdbc.pool.*; public class AppListener implements ServletContextListener { private OracleConnectionCacheImpl ds =null; public void contextInitialized(ServletContextEvent sce){ ServletContext application =sce.getServletContext(); try { ds = new OracleConnectionCacheImpl(); ds.setURL("jdbc:oracle:thin:@voyager2:1521:Oracle9i"); ds.setMaxLimit(20); ds.setUser("scott"); ds.setPassword("tiger"); } catch (Exception e){ application.log("Failed to create data source:"+ e.getMessage()); } Config.set(application, Config.SQL_DATASOURCE, ds); } ... }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
112
La clase oyente de este ejemplo crea un DataSource con capacidades de almacén de conexiones para una base de datos Oracle9i, y la hace disponible como por defecto para las acciones JSTL usando la clase Config para seleccionar la variable de configuración correspondiente. Otra forma, sólo disponible para prototipos o aplicaciones que no van a utilizarse tan duramente como para necesitar el almacén de conexiones, es usar la acción : Esta acción crea una sencilla fuente de datos, sin almacenamiento, para la URL JDBC especificada, con el usuario y la password, usando el driver JDBC especificado. Podríamos usar esta acción para empezar, pero recomendamos la utilización de una de las otras alternativas para una site del mundo real. Además de privarnos del almacén de conexiones para una fuente de datos creada de esta forma, no es una buena idea incluir información sensible como la URL de la base de datos, el nombre de usuario y la password en una página JSP, ya que sería posible para alguien acceder al código fuente de la página. Leer Datos de la Base de Datos Con una DataSource a nuestra disposición, podemos acceder a la base de datos. Aquí podemos leer datos desde una base de datos representada por el DataSource por defecto: <%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %> Reading database data ... Primero, necesitamos declarar la librería JSTL que contiene las acciones de bases de datos, usando la directiva taglib de la parte superior de este ejemplo. La acción ejecuta la sentencia SQL SELECT especificada por el atributo sql (o como el cuerpo del elemento acción) y graba los resultados en una variable nombrada por el atributo var. El resultado de la consulta a la base de datos se devuelve como un bean del tipo javax.servlet.jsp.jstl.sql.Result con varias propiedades de solo lectura:
Propiedad Rows
Tipo Java
Descripción Un array con un mapa insensible a las java.util.SortedMap[] mayúsculas por cada fila con las claves
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
rowsByIndex
Object[][]
columnNames rowCount
String[] Int
limitedByMaxRows
boolean
113
correspondiendo con los nombres de columna y valores correspondiendo con los valores de columna Un array con un array por fila con valores de columna Un array con nombres de columnas El número de filas en el resultado true si no se han incluido todas las filas debido a que se ha alcanzado el límite máximo de filas especificado
Ya vimos cómo utilizar la acción para mostrar todas o sólo algunas filas, por eso ahora veremos cómo podemos obtener sólo algunas filas para mostrarlas todas en esta parte. Los enlaces Next y Previous le permiten al usuario solicitar un conjunto diferente. Primero, aquí está cómo leer un subconjunto de filas y luego mostrar el subconjunto completo: SELECT * FROM Employee
El atributo startRow para la acción se envía a una expresión EL que lee el valor de un parámetro de solicitud llamado start. Luego veremos cómo cambia este valor cuando se pulsa sobre los enlaces Next y Previous. La primera vez que se accede a la página, el parámetro no existe, por eso la expresión se evalúa a 0. Esto significa que el resultado de la consulta contiene filas empezando con la primera que corresponda (índice 0). El atributo maxRows limita el número total de filas del valor de la variable noOfRows, lo seleccionamos a 10 en este ejemplo. La acción hace un bucle sobre todas las columnas del resultado y genera una lista de ítems con los valores de columna por cada fila. También, debemos generar los enlaces Next y Previous para permitir que el usuario seleccione un nuevo conjunto de filas: ">Previous Page Previous Page ">Next Page Next Page CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
114
El primer bloque es idéntico al de la página 1; si el parámetro de la solicitud start es mayor que cero, la página actual muestra un subconjunto de filas distinto del primero, por eso se añade un enlace Previous. El enlace apunta hacia la misma página, e incluye el parámetro start con un valor que es el valor actual menos el número de filas mostrado por cada página. El segundo bloque se aprovecha de la propiedad limitedByMaxRows del resultado de la consulta. Si esta propiedad es true, significa que se ha truncado el resultado al número de filas mostrado por cada página. De aquí, se genera el enlace Next con valor del parámetro start para el nuevo subconjunto de filas. Escribir Datos en la Base de Datos Además de leer datos desde una base de datos, también podemos usar JSTL para actualizar información. Este ejemplo muestra cómo insertar una nueva fila en una tabla: INSERT INTO Employee (FirstName, LastName, EmpDate) VALUES(?, ?, ?)
Antes de insertar la fila, este ejemplo ilustra cómo usar las acciones de validación JSTL. La página espera que todos los datos para la nueva fila se envíen como parámetros de solicitud (quizás introducidos en un formulario HTML), incluyendo una fecha de contratación. Antes de que la fecha se pueda insertar en la base de datos, debemos convertirla a su forma nativa Java. Esto es lo que hace la acción . El atributo value contiene una expresión EL que obtiene el valor del parámetro de solicitud empDate. La acción trata de interpretarlo como una fecha escrita en el formato especificado por el atributo pattern (un año de cuatro dígitos, seguido por dos dígitos del mes y dos dígitos del día, separados por barras inclinadas). Si tiene éxito, almacena la fecha en su forma nativa con el nombre especificado por el atributo var. La acción tiene en cuenta los strings inválidos. Si el valor del parámetro no puede ser interpretado como una fecha, el lanza una excepción, que la acción captura y graba en la variable especificada. Cuando esto sucede, la condición de comprobación de la acción se evalúa a true, por lo que la fecha de contratación es creada por la acción anidada. Para insertar la fila, usamos la acción . Como la acción de consulta, la sentencia SQL se puede especificar como el cuerpo del elemento o mediante un atributo sql. La acción se puede usar para ejecutar sentencias INSERT,
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
115
UPDATE, DELETE, así como sentencias para crear o eliminar objetos en la base de datos, como CREATE TABLE y DROP TABLE. El número de filas afectado por la sentencia puede capturarse de forma opcional en una variable nombrada por el atributo var. En este ejemplo (como en las mayoría de las aplicaciones del mundo real), no se conocen los nombres de las columnas en tiempo de ejecución; vienen de los parámetros de la solicitud. Por lo tanto, la sentencia INSERT de SQL incluye una marca de interrogación por cada valor como un contenedor y parámetros internos de la acción que seleccionan el valor dinámicamente. Las columnas FirstName y LastName son columnas de texto y las acciones seleccionan sus valores al valor del parámetro de solicitud correspondiente. Sin embargo, la columna EmpDate es una columna de fecha, demandando una atención especial. Primero de todo, debemos usar una variable que contenga la fecha en su forma nativa (un objeto java.util.Date) en lugar de usar el valor del parámetro de solicitud, usamos la variable creada por las acciones o . Segundo, debemos usar la acción para seleccionar el valor. En este ejemplo, hemos usado la parte de la fecha, por eso hemos seleccionado el atributo opcional type a date. Otros valores válidos son time y timestamp (por defecto), para las columnas que sólo toman la hora, o la fecha y la hora. Hay una acción JSTL más que no hemos descrito hasta ahora: . Podemos usarla para agrupar varias acciones update (o incluso query) donde todas ellas se deben ejecutar como parte de la misma transacción de la base de datos. El ejemplo estándar es transferir una cantidad de dinero de una cuenta a otra; implementada como una sentencia SQL que elimina el dinero de la primera cuenta y otra sentencia que lo añade a la segunda. Si encapsulamos todos los accesos a una base de datos en clases Java en lugar de usar las acciones de JSTL, todavía hay una parte de JSTL que nos puede ser útil. Es una clase llamada javax.servlet.jsp.jstl.sql.ResultSupport, con estos dos métodos: public static Result toResult(java.sql.ResultSet rs); public static Result toResult(java.sql.ResultSet rs, int maxRows); Podemos usar esta clase para convertir un objeto ResultSet estándar JDBC en un objeto Result JSTL antes de reenviarlo a la página JSP para mostrarlo. Las acciones JSTL pueden acceder fácilmente a los datos de un objeto Result, como vimos anteriormente. Otra aproximación, todavía mejor, es pasar el resultado de la consulta a la página JSP como una estructura de datos personalizada, como una List de beans que contienen los datos de cada fila, pero el objeto Result aún es un buen candidato para prototipos y pequeñas aplicaciones. Función fn:contains(string, substring) fn:containsIgnoreCase(string, substring) fn:endsWith(string, suffix) fn:escapeXml(string)
CIBERTEC
Descripción Devuelve true si el string contiene substring. Devuelve true si el string contiene a substring, ignorando capitalización. Devuelve true si el string termina con suffix. Devuelve el string con todos aquellos caracteres con especial significado en
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
fn:indexOf(string, substring) fn:join(array, separator)
fn:length(item)
fn:replace(string, before, after)
fn:split(string, separator)
fn:startsWith(string, prefix) fn:substring(string, begin, end)
fn:substringAfter(string, substring) fn:substringBefore(string, substring) fn:toLowerCase(string)
fn:toUpperCase(string)
fn:trim(string)
116
XML y HTML convertidos a sus códigos de escape pertinentes. Devuelve la primera ocurrencia de substring en el string. Devuelve un string compuesto por los elementos del array, separados por separator. Devuelve el número de elementos en ítem (si un array o colección), o el número de caracteres (es un string). Devuelve un string donde todas las ocurrencias del string before han sido reemplazadas por el string after. Devuelve un array donde los elementos son las partes del string separadas por separator. Devuelve true si el string comienza por prefix. Devuelve la parte del string que comienza por el índice begin y que acaba en el índice end. Devuelve la parte del string que sigue a substring. Devuelve la parte de string que precede a substring. Devuelve un string con todos los caracteres de la entrada convertidos a minúsculas. Devuelve un string con todos los caracteres de la entrada convertidos a mayúsculas. Devuelve un string sin espacios en sus laterales.
3.1.4 Aplicación Listado con JSTL Recuperar el proyecto anterior Pasos a seguir: 1. Proceda a copiar todos los jar que se entregó en clase dentro de la carpeta lib del proyecto web.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
117
2. Abrir la página listarProducto.jsp y escribir la directiva para trabajar con jstl.
3.
Modificar el listado de los productos como se muestra en la siguiente imagen:
Cambiar por
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
118
3.2 Ajax y Transacciones en Web 3.2.1 Ajax Ajax es una tecnología asíncrona, en el sentido de que los datos adicionales se solicitan al servidor y se cargan en segundo plano sin interferir con la visualización ni el comportamiento de la página.
Realizar peticiones al servidor y esperar respuesta puede consumir tiempo (el tiempo necesario para recargar una página completa). Para agilizar los desarrollos web surgió Ajax (inicialmente Asynchronous JavaScript And XML, aunque hoy día ya no es una tecnología ligada a XML con lo cual no pueden asociarse las siglas a estos términos), una tecnología que busca evitar las demoras propias de las peticiones y respuestas del servidor mediante la transmisión de datos en segundo plano usando un protocolo específicamente diseñado para la transmisión rápida de pequeños paquetes de datos. Con Ajax, se hace posible realizar peticiones al servidor y obtener respuesta de este en segundo plano (sin necesidad de recargar la página web completa) y usar esos
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
119
datos para, a través de JavaScript, modificar los contenidos de la página creando efectos dinámicos y rápidos. En el esquema anterior vemos las ideas en torno a Ajax de forma gráfica. En la parte superior hemos representado lo que sería un esquema de comunicación tradicional: el cliente solicita una página web completa al servidor. El servidor recibe la petición, se toma su tiempo para preparar la respuesta y la envía. El resultado, una pequeña demora debido al tiempo que tarda en llegar la petición al servidor, el tiempo que éste tarda en preparar la respuesta, y el tiempo que tarda en llegar la respuesta más recargarse en el navegador. En la parte inferior vemos lo que sería un esquema de comunicación usando Ajax: el cliente tiene una página web cargada (puede ser una página web completa, o sólo el esqueleto de una página web). El cliente sigue trabajando y en segundo plano (de ahí que hayamos dibujado con líneas punteadas las comunicaciones) le dice al servidor que le envíe un paquete de datos que le hacen falta. El servidor procesa la petición. Ahora la respuesta es mucho más rápida: no tiene que elaborar una página web completa, sino sólo preparar un paquete de datos. Por tanto el tiempo de respuesta es más rápido. El servidor envía el paquete de datos al cliente y el cliente los usa para cambiar los contenidos que se estaban mostrando en la página web. Funciones para Ajax Las funciones y utilidades relacionadas con AJAX son parte fundamental de jQuery. El método principal para realizar peticiones AJAX es $.ajax() (importante no olvidar el punto entre $ y ajax). A partir de esta función básica, se han definido otras funciones relacionadas, de más alto nivel y especializadas en tareas concretas: $.get(), $.post(), $.load(), etc. La sintaxis de $.ajax() es muy sencilla: $.ajax(opciones);
La URL que se solicita también se incluye dentro del array asociativo de opciones. A continuación se muestra un ejemplo básico realizado con $.ajax(): $.ajax({ url: 'pagina o servlet', type: 'POST', async: true, data: 'parametro1=valor1¶metro2=valor2', success: procesaRespuesta, error: muestraError });
La siguiente tabla muestra todas las opciones que se pueden definir para el método $.ajax():
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
Opción
120
Descripción
async
Indica si la petición es asíncrona. Su valor por defecto es true, el habitual para las peticiones AJAX
beforeSend
Permite indicar una función que modifique el objeto XMLHttpRequest antes de realizar la petición. El propio objeto XMLHttpRequest se pasa como único argumento de la función
complete
Permite establecer la función que se ejecuta cuando una petición se ha completado (y después de ejecutar, si se han establecido, las funciones de success o error). La función recibe el objetoXMLHttpRequest como primer parámetro y el resultado de la petición como segundo argumento
contentType
Indica el valor de la cabecera Content-Type utilizada para realizar la petición. Su valor por defecto esapplication/x-www-form-urlencoded
data
Información que se incluye en la petición. Se utiliza para enviar parámetros al servidor. Si es una cadena de texto, se envía tal cual, por lo que su formato debería ser parametro1=valor1¶metro2=valor2. También se puede indicar un array asociativo de pares clave/valor que se convierten automáticamente en una cadena tipo query string
dataType
El tipo de dato que se espera como respuesta. Si no se indica ningún valor, jQuery lo deduce a partir de las cabeceras de la respuesta. Los posibles valores son: xml (se devuelve un documento XML correspondiente al valor responseXML), html (devuelve directamente la respuesta del servidor mediante el valor responseText), script (se evalúa la respuesta como si fuera JavaScript y se devuelve el resultado) y json (se evalúa la respuesta como si fuera JSON y se devuelve el objeto JavaScript generado)
error
Indica la función que se ejecuta cuando se produce un error durante la petición. Esta función recibe el objeto XMLHttpRequest como primer parámetro, una cadena de texto indicando el error como segundo parámetro y un objeto con la excepción producida como tercer parámetro
ifModified
Permite considerar como correcta la petición solamente si la respuesta recibida es diferente de la anterior respuesta. Por defecto su valor es false
processData
Indica si se transforman los datos de la opción data para convertirlos en una cadena de texto. Si se indica un valor de false, no se realiza esta transformación automática
success
Permite establecer la función que se ejecuta cuando una petición se ha completado de forma correcta. La función recibe como primer parámetro los datos recibidos del servidor, previamente formateados según se especifique en la opción dataType
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
Opción timeout
type url
121
Descripción Indica el tiempo máximo, en milisegundos, que la petición espera la respuesta del servidor antes de anular la petición El tipo de petición que se realiza. Su valor por defecto es GET, aunque también se puede utilizar el método POST La URL del servidor a la que se realiza la petición
3.2.2 Transacciones Un sistema de procesamiento de transacciones (TPS por sus siglas en inglés) es un tipo de sistema de información que recolecta, almacena, modifica y recupera toda la información generada por las transacciones producidas en una organización. Una transacción es un evento que genera o modifica los datos que se encuentran eventualmente almacenados en un sistema de información. Para que un sistema informático pueda ser considerado como un TPS, este debe superar el test ACID. Desde un punto de vista técnico, un TPS monitoriza los programas transaccionales (un tipo especial de programas). La base de un programa transaccional está en que gestiona los datos de forma que estos deben ser siempre consistentes (por ejemplo, si se realiza un pago con una tarjeta electrónica, la cantidad de dinero de la cuenta sobre la que realiza el cargo debe disminuir en la misma cantidad que la cuenta que recibe el pago, de no ser así, ninguna de las dos cuentas se modificará), si durante el transcurso de una transacción ocurriese algún error, el TPS debe poder deshacer las operaciones realizadas hasta ese instante. Si bien este tipo de integridad es que debe presentar cualquier operación de procesamiento de transacciones por lotes, es particularmente importante para el procesamiento de transacciones on-line: si, por ejemplo, un sistema de reserva de billetes de una línea aérea es utilizado simultáneamente por varios operadores, tras encontrar un asiento vacío, los datos sobre la reserva de dicho asiento deben ser bloqueados hasta que la reserva se realice, de no ser así, otro operador podría tener la impresión de que dicho asiento está libre cuando en realidad está siendo reservado en ese mismo instante. Sin las debidas precauciones, en una transacción podría ocurrir una reserva doble. Otra función de los monitores de transacciones es la detección y resolución de interbloqueos (deadlock), y cortar transacciones para recuperar el sistema en caso de fallos masivos. Características Respuesta rápida En este tipo de sistemas resulta crítico que exista un rendimiento elevado con tiempos de respuesta cortos. Una empresa no puede permitirse tener clientes esperando por una respuesta del SPT; el tiempo total transcurrido desde que se inicia la transacción hasta que se produce la salida correspondiente debe ser del orden de unos pocos segundos o menos. Fiabilidad Muchas organizaciones basan su fiabilidad en los SPT; un fallo en un SPT afectará negativamente a las operaciones o incluso parará totalmente el negocio. Para que un SPT sea efectivo, su tasa de fallos debe ser muy baja. En caso de fallo de un SPT,
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
122
debe existir algún mecanismo que permita una recuperación rápida y precisa del sistema. Esto convierte en esencial la existencia procedimientos de copia de seguridad y de recuperación ante fallos correctamente diseñados. Inflexibilidad Un SPT requiere que todas las transacciones sean procesadas exactamente de la misma forma, independientemente del usuario, el cliente o la hora del día. Si los SPT fuesen flexibles, habría entonces demasiadas posibilidades de ejecutar operaciones no estándar. Por ejemplo, una aerolínea comercial necesita aceptar de forma consistente reservas de vuelos realizadas por un gran número de agencias de viaje distintas; aceptar distintos datos de transacción de cada agencia de viajes supondría un problema. Procesamiento controlado El procesamiento en un SPT debe apoyar las operaciones de la organización. Por ejemplo, si una organización establece roles y responsabilidades para determinados empleados, el SPT debe entonces mantener y reforzar este requisito. Propiedades Atomicidad Los cambios de estado provocados por una transacción son atómicos: o bien ocurren todos o bien no ocurre ninguno. Estos cambios incluyen tanto modificaciones de la base de datos, como envío de mensajes o acciones sobre los transductores. Consistencia Una transacción es una transformación de estado correcta. Las acciones consideradas en su conjunto no violan ninguna de las restricciones de integridad asociadas al estado. Esto implica que la transacción debe ser un programa correcto. Aislamiento Incluso cuando varias transacciones se ejecuten de forma concurrente, para cada transacción T debe parecer que el resto de transacciones se han ejecutado antes o después de T, pero no antes y después. Durabilidad Una vez que una transacción ha finalizado con éxito (compromiso), cambia hacia un estado estable a prueba de fallos. Transacciones en JDBC Hay momentos en los que no desea una declaración entre en vigor a menos que otra completa. Por ejemplo, cuando el propietario de The Coffee Break actualiza la cantidad de café que se vende cada semana, el propietario también desee actualizar la cantidad total vendida hasta la fecha. Sin embargo, la cantidad vendida por semana y la cantidad total vendida debe actualizarse al mismo tiempo; de lo contrario, los datos serán inconsistentes. La manera de estar seguro de que se produzcan, ya sea ambas acciones o ninguna acción ocurre es utilizar una transacción.Una transacción es un conjunto de una o más sentencias que se ejecuta como una unidad, por lo que o bien todas las sentencias se ejecutan, o ninguna de las declaraciones se ejecuta. Desactivación del modo de confirmación automática
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
123
Cuando se crea una conexión, que está en modo auto-commit. Esto significa que cada sentencia SQL individuo es tratado como una transacción y se compromete de forma automática después de que se ejecuta. (Para ser más precisos, el valor predeterminado es para una sentencia SQL que se comete cuando se haya completado, no cuando se ejecuta. Se completa una declaración cuando todos sus conjuntos de resultados y cuentas de actualización se han recuperado. En casi todos los casos, sin embargo, se completa una declaración, y por lo tanto comprometido, justo después de que se ejecute.) La manera de permitir que dos o más declaraciones a agruparse en una transacción es desactivar el modo auto-commit. Esto se demuestra en el siguiente código, donde con una conexión activa: con.setAutoCommit (false); Uso de transacciones para Preservar la integridad de los datos Además de la agrupación de estados juntos para la ejecución como una unidad, las transacciones pueden ayudar a preservar la integridad de los datos en una tabla. Por ejemplo, imagine que un empleado tenía que ingresar los nuevos precios del café en la tabla COFFEES pero no lo hizo durante unos días. Mientras tanto, los precios subieron, y en la actualidad el propietario se encarga de introducir los precios más altos. El empleado finalmente consigue ingresar los precios ahora obsoletos, al mismo tiempo que el dueño está tratando de actualizar la tabla. Después de insertar los precios desfasados, el empleado se da cuenta de que ya no son válidos y llama al método rollback de la Connection para deshacer sus efectos. (El método rollback aborta la transacción y restaura los valores a lo que eran antes del intento de actualización.) Al mismo tiempo, el propietario está ejecutando una declaración SELECT para la impresión de los nuevos precios. En esta situación, es posible que el propietario imprimirá un precio que se había deshecho de su valor anterior, por lo que el precio impreso es incorrecto. Este tipo de situación se puede evitar mediante el uso de transacciones para proporcionar algún nivel de protección contra los conflictos que surgen cuando dos usuarios intentan acceder a los datos al mismo tiempo. Para evitar conflictos durante una transacción, un DBMS utiliza bloqueos, mecanismos para bloquear el acceso de otros a los datos que se esté accediendo a la transacción. (Tenga en cuenta que el modo de auto-commit, donde cada sentencia es una transacción, bloqueos se mantienen durante una sola declaración.) Después se establece un bloqueo, que permanece en vigor hasta que la transacción se confirma o se deshace. Por ejemplo, un DBMS podría bloquear una fila de una tabla por los cambios que se han comprometido. El efecto de este bloqueo sería la de evitar que un usuario conseguir una lectura sucia, es decir, la lectura de un valor antes de que se haga permanente. (Acceso a un valor actualizado que no se ha confirmado se considera una lectura sucia porque es posible que el valor que se revierte a su valor anterior. Si se lee un valor que luego se deshace, se ha leído un valor no válido) Cómo se establecen bloqueos está determinado por lo que se llama un nivel de aislamiento, que puede ir desde no apoyar transacciones en absoluto para apoyar transacciones que hacen cumplir las reglas de acceso muy estrictas. Un ejemplo de un nivel de aislamiento es TRANSACTION_READ_COMMITTED, que no permitirá que un valor sea accedido hasta después que se haya confirmado. En otras palabras, si el nivel de aislamiento de transacción se establece en
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
124
TRANSACTION_READ_COMMITTED , el DBMS no permite lecturas sucias que se produzcan. La interfaz Connection incluye cinco valores que representan los niveles de aislamiento de transacción que puede utilizar en JDBC:
Una lectura no repetible se produce cuando la transacción A recupera una fila, la transacción B posteriormente actualiza la fila, y la primera transacción más tarde recupera la misma fila de nuevo. Transacción A recupera la misma fila dos veces, pero ve datos diferentes. Una lectura fantasma se produce cuando la transacción A recupera un conjunto de filas que satisfacen una condición dada, la transacción B posteriormente inserta o actualiza una fila de tal manera que la fila ahora cumple la condición en la transacción A, y la primera transacción más tarde repite la recuperación condicional. Transacción A ahora ve una fila adicional. Esta fila se conoce como un fantasma. Por lo general, usted no tiene que hacer nada sobre el nivel de aislamiento de transacción; sólo puede utilizar el valor predeterminado para su DBMS. El nivel de aislamiento de transacción por defecto depende de su DBMS. Por ejemplo, para Java DB, TRANSACTION_READ_COMMITTED . JDBC permite averiguar cuál es el nivel de aislamiento de transacción de su DBMS (utilizando el método getTransactionIsolation de Connection) y también le permite establecerlo a otro nivel (usando el método setTransactionIsolation de Connection). Nota: Un controlador JDBC no admite todos los niveles de aislamiento de transacción. Si un conductor no soporta el nivel de aislamiento especificado en una invocación de setTransactionIsolation , el conductor puede sustituir un nivel de aislamiento más restrictivo superior. Si un conductor no puede sustituir a un nivel de transacción superior, lanza una SQLException. Utilice el método DatabaseMetaData.supportsTransactionIsolationLevel para determinar si el controlador es compatible con un determinado nivel. Ajuste y Recuperando los Puntos de salvaguarda El método Connection.setSavepoint, establece un objeto Savepoint dentro de la transacción actual. El método Connection.rollback está sobrecargado para tomar un argumento Savepoint. Liberar Puntos de salvaguarda El método Connection.releaseSavepoint toma un objeto Savepoint como parámetro y lo elimina de la transacción actual. Después que un punto de rescate ha sido puesto en libertad, y se trata de hacer referencia a ella en una operación de reversión puede causar que se lance una
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
125
SQLException. Cualquier punto de salvaguarda que se han creado en una transacción se liberan automáticamente y dejan de ser válidas cuando se confirma la transacción, o cuando la transacción se devuelve. Rodar una transacción a un punto de salvaguarda se desconecta automáticamente y hace inválido a cualquier otro punto de rescate que se crearon tras el punto en cuestión. Al llamar al método rollback Como se mencionó anteriormente, la llamada al método rollback termina una transacción y devuelve los valores que se han modificado a sus valores anteriores. Si usted está tratando de ejecutar una o más declaraciones en una transacción y obtiene una SQLException, llame al método rollback para poner fin a la operación y comenzar la operación de nuevo. Esa es la única manera de saber lo que se ha cometido y lo que no se ha cometido. La captura de un SQLException te dice que algo está mal, pero no le dice lo que fue o no fue cometido. Porque no se puede contar con el hecho de que nada se haya cometido, una llamada al método rollback es la única manera de estar seguro. El método CoffeesTable.updateCoffeeSales demuestra una transacción e incluye una catch bloque que invoca el método rollback . Si la aplicación continúa y utiliza los resultados de la transacción, esta llamada a la rollback método en la catch bloque impide el uso de datos posiblemente incorrectos.
3.2.3 Aplicación Ajax y Transacción Recuperar el proyecto anterior. Pasos a seguir: 1. Crear la clase ClienteDTO, BoletaDTO,DeatalleBoletaDTO dentro del paquete beans, según la siguiente imagen:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
126
Clase DetalleBoletaDTO
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
127
Clase ClienteDTO
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
128
Clase BoletaDTO
2. Crear la interface ClienteDAO, BoletaDAO dentro del paquete interfaces, según la siguiente imagen:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
129
ClienteDAO
BoletaDAO
Actualizar la interface ProductoDAO
3. Registrar el DAO BoletaDAO y ClienteDAO dentro de la clase DAOFactory.
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
130
4. Actualizar la clase MySqlDAOFactory, según la siguiente imagen:
5. Actualizar la clase MySqlProductoDAO en el método buscarProducto, según la siguiente imagen:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
6.
131
Programar en la clase MySqlClienteDAO en el método buscarCliente según la siguiente imagen:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
132
7. Programar en la clase MySqlBoletaDAO en el método registrarBoleta, según la siguiente imagen:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
133
8. Crear la clase ClienteService dentro del paquete services, según la siguiente imagen:
9. Actualizar la clase ProductoService, según la siguiente imagen:
10. Crear la clase BoletaService dentro del paquete services, según la siguiente imagen:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
134
11. Crear el servlet ServletCliente dentro del paquete misServlets y escribir las siguientes instrucciones:
12.
Actualizar el servlet ServletProducto, según la siguiente imagen:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
135
13. Crear la página: registrarBoleta.jsp y escribir las siguientes instrucciones: <%@ taglib uri="http://displaytag.sf.net" prefix="displaySession"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1"> Boleta <script src="js/jquery.js" type="text/javascript"> <script src="js/jquery.functions.js" type="text/javascript"> <script type="text/javascript"> function addProducto(){ document.getElementById("tipo").value ='ingresa'; document.getElementById("frmBoleta").action = 'ServletBoleta'; document.getElementById("frmBoleta").submit(); } function addBoleta(){ document.getElementById("tipo").value ='registra'; document.getElementById("frmBoleta").action = 'ServletBoleta'; document.getElementById("frmBoleta").submit(); } function verCliente(){ document.getElementById("fondo").style.display ='block'; document.getElementById("divCliente").style.display ='block'; } function verProducto(){ document.getElementById("fondo").style.display ='block'; document.getElementById("divProducto").style.display ='block'; } function ocultaCliente(){ document.getElementById("fondo").style.display ='none'; document.getElementById("divCliente").style.display ='none'; } function ocultaProducto(){ document.getElementById("fondo").style.display ='none'; document.getElementById("divProducto").style.display ='none'; } Boleta de Venta Datos del Cliente Seleccione Producto
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
137
14. Al ejecutar la página registroBoleta.jsp se mostrará la siguiente imagen:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
138
15. Abrir el archivo jquey.functions.js y escribir las siguientes instrucciones:
16. Crear las páginas: buscarCliente.jsp y escribir las siguientes instrucciones: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here ID Apellidos y Nombres Sexo DNI Direccion Distrito
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
139
${f.codigo} ${f.apellido} ${f.nombre} ${f.sexo} ${f.dni} ${f.direccion} ${f.nomDistrito}
17. Crear las páginas: buscarProducto.jsp y escribir las siguientes instrucciones: <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Insert title here ID Descripcion Precio Stock Marca ${f.codigo} ${f.descripcion} ${f.precio} ${f.stock} ${f.nomMarca}
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
140
18. Al ejecutar la página registroBoleta.jsp se mostrará la siguiente imagen:
Al hacer clic se mostrará una ventana para buscar el cliente por el campo apellido
Al hacer clic se mostrará una ventana para buscar el producto por su descripción.
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
141
19. Crear el servlet : ServletBoleta y escribir las siguientes instrucciones: package misServlets; import java.io.IOException; public class ServletBoleta extends HttpServlet { BoletaService serviBoleta=new BoletaService(); private static final long serialVersionUID = 1L; public ServletBoleta() { super(); } protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String tipo=request.getParameter("tipo"); if(tipo.equals("verCliente")) verCliente(request,response); else if(tipo.equals("verProducto")) verProducto(request,response); else if(tipo.equals("ingresa")) ingresa(request, response); else if(tipo.equals("elimina")) eliminar(request, response); else if(tipo.equals("registra")) registra(request, response); } private void registra(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); //Boleta que esta en sesion ArrayList boleta =(ArrayList) session.getAttribute("boleta"); //Cliente que esta en sesion String cliente[]= (String[])session.getAttribute("datoCliente"); int codCliente = Integer.parseInt(cliente[0]); //Creamos la Boleta EmpleadoDTO codEmpleado=(EmpleadoDTO) session.getAttribute("datos"); BoletaDTO b = new BoletaDTO(); b.setCodEmpleado(codEmpleado.getCodigo()); b.setCodCiente(codCliente); //Creamos el detalle ArrayList detalles = new ArrayList(); for (ProductoDTO x : boleta) { DetalleBoletaDTO det = new DetalleBoletaDTO(0, x.getCodigo(), x.getStock(), x.getPrecio()); detalles.add(det); } serviBoleta.registrarBoleta(b, detalles); //limpiamos la sesion session.removeAttribute("boleta"); session.removeAttribute("datoCliente"); session.removeAttribute("datoProducto"); //reenvio request.getRequestDispatcher("registrarBoleta.jsp"). forward(request, response); }
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
142
private void eliminar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getParameter("id"); int codi = Integer.parseInt(id); HttpSession session = request.getSession(); ArrayList boleta = (ArrayList) session.getAttribute("boleta"); for (int i = 0; i < boleta.size(); i++) { if(boleta.get(i).getCodigo() == codi){ boleta.remove(i); break; } } //la lista se agrega a sesion session.setAttribute("boleta", boleta); //reenvio request.getRequestDispatcher("registrarBoleta.jsp"). forward(request, response); } private void ingresa(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String cod = request.getParameter("txt_cod_pro"); String des = request.getParameter("txt_des_pro"); String can= request.getParameter("txt_can_pro"); String pre= request.getParameter("txt_pre_pro"); int codi = Integer.parseInt(cod.trim()); int cant = Integer.parseInt(can.trim()); double prec = Double.parseDouble(pre.trim()); ArrayList boleta ; //Se verifica si existe en sesion HttpSession session = request.getSession(); if(session.getAttribute("boleta") == null){ boleta = new ArrayList(); }else{ 20. Modificar la pagina: registrarBoleta.jsp y escribir las siguientes instrucciones: boleta = (ArrayList) session.getAttribute("boleta"); } //Se crear el objeto ProductoDTO p = new ProductoDTO(); p.setCodigo(codi);p.setDescripcion(des); p.setPrecio(prec); p.setStock(cant); boolean noExiste = true; //se verifica los repetidos for (int i = 0; i < boleta.size(); i++) { if(boleta.get(i).getCodigo() == codi){ boleta.set(i, p); noExiste = false; break; } } //Si no existe se agrega if(noExiste){ boleta.add(p); } //la lista se agrega a sesion session.setAttribute("boleta", boleta); request.getRequestDispatcher("registrarBoleta.jsp"). forward(request, response); }
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
143
private void verProducto(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String codigo = request.getParameter("codigo"); String des = request.getParameter("des"); String pre = request.getParameter("pre"); String producto[]=new String[3]; producto[0]=codigo;producto[1]=des;producto[2]=pre; HttpSession session = request.getSession(); session.setAttribute("datoProducto", producto); request.getRequestDispatcher("registrarBoleta.jsp"). forward(request, response); } private void verCliente(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String codigo = request.getParameter("codigo"); String datos = request.getParameter("datos"); String cliente[]=new String[2]; cliente[0]=codigo;cliente[1]=datos; HttpSession session = request.getSession(); session.setAttribute("datoCliente", cliente); request.getRequestDispatcher("registrarBoleta.jsp"). forward(request, response); } }
21. Actualizar la página: registrarBoleta.jsp y escribir las siguientes instrucciones:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
144
22. Ejecutar la página index.jsp y se mostrará lo siguiente:
23. Se mostrará la página con los tres menús, luego clic en Boleta.
24. Se mostrará la página registrarBoleta.jsp, como se muestra a continuación:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
145
25. Clic en el botón (…) que se encuentra cerca de la caja de Apellidos y Nombres, se mostrará lo siguiente:
26. Clic en el botón (…) que se encuentra cerca de la caja de Cantidad, se mostrará lo siguiente:
Ingresar una cantidad, luego clic en el botón agregar
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
146
27. Luego de realizar la venta de los productos para registrar la venta, clic en el botón Registrar y en las tablas: tb_boleta y tb_boleta_has_producto se realizó el registro, como se muestra a continuación: Tabla: tb_boleta
Tabla: tb_boleta_has_producto
3.3 Listeners 3.3.1 Tipos En aplicación web los eventos son nuevos, a partir en la especificación Servlet 2.3. Ellos le dan mayor grado de control sobre su aplicación web. En este capítulo, se va a estudiar la aplicación de dos importantes eventos: Inicio y apagado de una aplicación La creación y la invalidación de sesiones Como sus nombres indican, la aplicación de inicio de evento se produce cuando su aplicación web se carga por primera vez y comenzó por el contenedor de Servlets; y solicitud de cierre se produce cuando la aplicación web se cierra. El período de sesiones se produce en la creación de una nueva sesión cada vez que se crea en el servidor y de manera similar el período de sesiones se origina con la invalidación de una sesión cada vez que se anula. Para hacer uso de estas aplicaciones web y eventos para hacer algo útil, tendrá que crear y hacer uso de "clases oyentes". De aquí en adelante, vamos a implementar clases oyentes y cómo se pueden utilizar. Clases oyentes Estos son simples clases Java que implementan una de las dos siguientes interfaz: - javax.servlet.ServletContextListener
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
147
- javax.servlet.http.HttpSessionListener La implementación de ServletContextListener permite escuchar la creación o destrucción del contexto. La implementación de HttpSessionListener le permite escuchar la creación de una sesión. Veamos cuáles son los diferentes métodos de esta interfaz, que se tendrán que aplicar. ServletContextListener: Esta interfaz contiene dos métodos:
public void contextInitialized (ServletContextEvent SCE); //Creación de un Contexo. public void contextDestroyed (ServletContextEvent SCE); //Destrucción de un contexto.
Un ejemplo de esa clase es el siguiente:
import javax.servlet.ServletContextListener; import javax.servlet.ServletContextEvent; public class ApplicationWatch implements ServletContextListener ( public static applicationInitialized long = 0L; / * Aplicación de inicio del evento * / public void contextInitialized (ServletContextEvent ce) ( applicationInitialized = System.currentTimeMillis (); ) / * Aplicación del evento de apagado * / public void contextDestroyed (ServletContextEvent ce) () ) En el código anterior, una clase Java ApplicationWatch implementa ServletContextListener. Al implementar sus dos métodos realmente sólo usa uno de ellos y el segundo método sigue teniendo el cuerpo vacío. En esta categoría, se observa en el momento de la solicitud de inicio en public static que puede ser llamado desde otra aplicación para saber qué clase fue la última vez que esta solicitud se inició. Se explicará cómo decirle al servidor de aplicaciones que tienen esta clase de oyente; además, se quiere que se les diga la aplicación de estos acontecimientos en un momento, pero primero vamos a ver cuáles son los diferentes métodos de HttpSessionListener interfaz. HttpSessionListener Esta interfaz te permite poder escuchar al crear o destruir una sesión.
public void sessionCreated (HttpSessionEvent se); public void sessionDestroyed (HttpSessionEvent se);
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
148
Al igual que lo que hicimos en el caso de ApplicationWatch anterior, tendrá que crear una clase Java y aplicar HttpSessionListener interfaz. Un ejemplo de esa clase es el siguiente: import javax.servlet.http.HttpSessionListener; import javax.servlet.http.HttpSessionEvent; public class SessionCounter implements HttpSessionListener ( private static int activeSessions = 0; / * Creación de eventos de sesión * / public void sessionCreated (HttpSessionEvent se) ( activeSessions + +; ) / * Sesión de invalidación del evento * / public void sessionDestroyed (HttpSessionEvent se) ( if (activeSessions> 0) activeSessions -; ) public static int getActiveSessions () ( activeSessions retorno; ) ) En el código anterior, SessionCounter clase implementa HttpSessionListener para contar el número de sesiones activas. Se ha aprendido cuáles son los eventos de aplicaciones web, interfaz de lo que está disponible para nosotros y también se han visto ejemplos de la aplicación de la interfaz de las clases. Veamos cómo decirle al servidor de aplicaciones acerca de estas clases oyentes. Registro de las clases oyentes en el web.xml Eso es lo que hacemos poniendo classpath de estas clases en / WEB-INF/web.xml archivo con etiquetas especiales . Un ejemplo de este tipo de archivo web.xml es el siguiente: xml version = "1.0" encoding = "ISO-8859-1"> com.stardeveloper.web.listener.SessionCounter oyente de clase> oyente> com.stardeveloper.web.listener.ApplicationWatch oyente de clase> oyente> web-app>
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
149
Como se indica anteriormente, es muy fácil declarar oyentes en el archivo web.xml. Ahora, cada vez que el servidor se inicia o cierre, una sesión se crea o destruye.
3.3.2 Aplicación Auditoria Recuperar el proyecto anterior. Pasos a seguir: En aplicación web los eventos son nuevos, a partir en la especificación Servlet 2.3. Ellos le dan mayor grado de control sobre su aplicación web. En este capítulo, se va a estudiar la aplicación de dos importantes eventos: Como sus nombres indican, la aplicación de inicio de evento se produce cuando su aplicación web se carga por primera vez y comenzó por el contenedor de Servlets; y solicitud de cierre se produce cuando la aplicación web se cierra. 1. Crear dentro del paquete beans la clase AuditoriaDTO con los siguientes atributos: private private private private private private
int idAuditoria; int codigoempleado; String fechaLogin; String fechaLogout; String usuario; String tiempo;
Crear los métodos de acceso: set, get y el constructor. 2. Crear una interfaz dentro del paquete interfaces con el nombre AuditoriaDAO que tenga los siguientes métodos: public void registraSesionLogin(AuditoriaDTO audi); public void registraSesionLogout(AuditoriaDTO audi); 3. Proceda a registrar el DAO y crear la clase MySqlAuditoriaDAO para implementar los métodos de la interfaz: AuditoriaDAO. 4. Crear un servicio dentro del paquete service con el nombre AuditoriaService que permita trabajar con los métodos que existen en MySqlAuditoriaDAO. 5. Crear un paquete con el nombre: listener y una clase con EscuchaAtributoSesion, la estructura será la siguiente en su proyecto:
CIBERTEC
el
nombre:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
CARRERA DE COMPUTACIÓN E INFORMÁTICA
150
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
151
6. La clase EscuchaAtributoSesion tendrá el siguiente código:
7. Crear la clase AuditoriaSrevice dentro del paquete service y escribir las siguientes instrucciones:
CIBERTEC
CARRERA DE COMPUTACIÓN E INFORMÁTICA
LENGUAJE DE PROGRAMACIÓN II
152
8. Para registrar el listener y el tiempo de la sesión inactiva abrir el archivo web.xml y escribir lo siguiente:
CARRERA DE COMPUTACIÓN E INFORMÁTICA
CIBERTEC
LENGUAJE DE PROGRAMACIÓN II
153
Resumen Evita el envío automático
conn.setAutoCommit(false); Permite el envío de todas las sentencias sqls
conn.commit(); Permite la cancelación de las sentencias sqls
conn.rollback(); El uso de etiquetas personalizadas le permitirá al programador poder reutilzar la etiqueta en otra página. Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta unidad: o http://www.tutorialspoint.com/jdbc/jdbc-transactions.htm Transacciones o
CIBERTEC
http://www.java2s.com/Code/Java/Database-SQLJDBC/CommitorrollbacktransactioninJDBC.htm Ejemplos de transacciones
CARRERA DE COMPUTACIÓN E INFORMÁTICA