Guía JSP - JDBC
Short Description
Download Guía JSP - JDBC...
Description
PONTIFICIA UNIVERSIDAD CATÓLICA DEL PERÚ Ingeniería de las Telecomunicaciones
LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 – INF228 2
LABORATORIO NÚMERO:
TEMA:
SEMESTRE : 2009 - 1
INTRODUCCIÓN A JSP Y JDBC
OBJETIVOS: Poder desarrollar aplicaciones web usando JSPs. Conocer algunas características básicas de JSPs Crear y Utilizar de forma básica los JDBC. ACTIVIDADES A REALIZAR No. DESCRIPCIÓN 0 Prueba de Entrada 1 Introducción Aplicaciones Web , Servlets, JSP y JDBC 2 Desarrollo de los ejercicios propuestos en la evaluación del laboratorio.
DURACIÓN
PUNTAJE
-
-
Advertencia El desarrollo de las actividades contenidas en esta guía es de carácter estrictamente personal. Cualquier falta de probidad (plagio) que a criterio del Jefe de Práctica sea cometida, será sancionada con la nota CERO no anulable para todos los involucrados, los cuales serán además sancionados de acuerdo con el Reglamento Disciplinario de la PUCP.
Importante Todos los programas que figuran en la presente guía (y los archivos leídos y/o generados por éstos) deberán ser grabados en una carpeta especialmente creada para tales efectos, la cual será referida a lo largo de la guía como su “carpeta de trabajo”.
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
1. Introducción En nuestra experiencia de navegar en Internet nos hemos encontrado con las páginas Web el cual es un documento de la World Wide Web, normalmente en formato HTML que proviene del estándar SGML o XHTML que proviene del estándar XML. Algunas de estas páginas web son dinámicas ya que dependen de una aplicación que varía su contenido por ejemplo las que uno observa al entrar a un webmail ya que su contenido varía automáticamente dependiendo del usuario que se logueó, etc; también tenemos las páginas web estáticas aquellas cuyo contenido varía pero de forma manual. Toda página Web es distribuida por medio de un Servidor Web el cual podría ser Apache, el IIS (Internet Information Service), Tomcat, JBOSS, etc. El servidor Tomcat es un Servidor de Aplicaciones que cumple las especificaciones de servlets y jsp.
Estructura de Directorios de Tomcat 5.X
Pág. 2
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
2. Servlets
•Un Servlet es una clase Java usada para extender la capacidad de las aplicaciones basadas en el modelo cliente servidor y ejecución petición respuesta. •Los Servlets son una potente herramienta para la generación de contenido dinámico en la Web. •El Servlet Container es el componente encargado de la creación, acceso y destrucción de los Servlets, controla su ciclo de vida.
2.1 Arquitectura de los Servlets El principal componente de la Servlet API es la interfaz Servlet. Todos los servlets implementan esta interfaz directamente, por medio de la extensión de la clase que la implementa, HttpServlet. Esta interfaz está provista de métodos que manipulan a los servlets y la comunicación con sus clientes. Cuando un servlet es llamado desde un cliente, este recibe dos objetos: ServletRequest y ServletResponse. La interfaz ServletRequest se encarga de la comunicación desde el cliente al servidor, mientras que la interfaz ServletResponse atiende la comunicación desde el servlet al cliente.
Las clases e interfaces descritas conforman a un servlet básico. Pero existen métodos adicionales que provee la API con la capacidad para controlar sesiones o múltiples conexiones, entre muchas más aplicaciones. Pág. 3
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
3. JSP • Un JSP, es una página dinámica de servidor Java. • Este tipo de archivo de texto esta compuesto de: 1. Cabecera con importaciones y parámetros. 2. Código cliente, normalmente HTML, XML y Javascript. 3. Código servidor Java, denominado Scriptlet y escrito entre los caracteres . 4. Tags: instrucciones en formato XML, asociadas a clases Java. • Un dato muy importante es que un “JSP se transforma en un Servlet en tiempo de ejecución” esto se observa claramente en la siguiente gráfica:
La primera vez que se realiza una petición sobre un JSP el JSP Engine lo traduce en un Servlet, lo compila y lo procesa. En sucesivas peticiones simplemente se procesa a través del Servlet Container. Esta puede estar conformada de las siguientes partes: • • • • •
Código estático HTML Directivas JSP Scripts de elementos y variables JSP Actions JSP Tags Customizables
Pág. 4
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
3.1. Directivas JSP
3.1.1 Directiva page La directiva page nos permite definir uno o más de los siguientes atributos sensibles a las mayúsculas: •
import="package.class" ó import="package.class1,...,package.classN". Esto nos permite especificar los paquetes que deberían ser importados. Por ejemplo:
El atributo import es el único que puede aparecer múltiples veces. •
•
•
•
•
•
• •
contentType="MIME-Type" ó contentType="MIME-Type; charset=Character-Set" esto especifica el tipo MIME de la salida. El valor por defecto es text/html. Por ejemplo, la directiva: tiene el mismo valor que el scriptlet isThreadSafe="true|false". Un valor de true (por defecto) indica un procesamiento del servlet normal, donde múltiples peticiones pueden procesarse simultáneamente con un sólo ejemplar del servlet, bajo la suposición que del autor sincroniza las variables de ejemplar. Un valor de false indica que el servlet debería implementar SingleThreadModel, con peticiones enviadas serialmente o con peticiones simultáneas siendo entregadas por ejemplares separados del servlet. session="true|false". Un valor de true (por defecto) indica que la variable predefinida session (del tipo HttpSession) debería unirse a la sesión existente si existe una, si no existe se debería crear una nueva sesión para unirla. Un valor de false indica que no se usarán sesiones, y los intentos de acceder a la variable session resultarán en errores en el momento en que la página JSP sea traducida a un servlet. buffer="sizekb|none". Esto especifica el tamaño del buffer para el JspWriter out. El valor por defecto es específico del servidor, debería ser de al menos 8kb. autoflush="true|false". Un valor de true (por defecto) indica que el buffer debería descargase cuando esté lleno. Un valor de false, raramente utilizado, indica que se debe lanzar una excepción cuando el buffer se sobrecargue. Un valor de false es ilegal cuando usamos buffer="none". extends="package.class". Esto indica la superclase del servlet que se va a generar. Debemos usarla con extrema precaución, ya que el servidor podría utilizar una superclase personalizada. info="message". Define un string que puede usarse para ser recuperado mediante el método getServletInfo. errorPage="url". Especifica una página JSP que se debería procesar si se lanzará cualquier Throwable pero no fuera capturado en la página actual. Pág. 5
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
• •
isErrorPage="true|false". Indica si la página actual actúa o no como página de error de otra página JSP. El valor por defecto es false. language="java". En algunos momentos, esto está pensado para especificar el lenguaje a utilizar. Por ahora, no debemos preocuparnos por él ya que java es tanto el valor por defecto como la única opción legal Ejemplo:
3.1.2 Directiva include JSP Esta directiva nos permite incluir ficheros en el momento en que la página JSP es traducida a un servlet. La directiva se parece a esto:
3.2 Scriptlets JSP Si queremos hacer algo más complejo que insertar una simple expresión, los scriptlets JSP nos permiten insertar código arbitrario dentro del método servlet que será construido al generar la página. Los Scriptlets tienen la siguiente forma: Ejemplo:
Pág. 6
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
3.3 Variables Predefinidas Para simplificar el código en expresiones y scriplets JSP, tenemos ocho variables definidas automáticamente, algunas veces llamadas objetos implícitos. Las variables disponibles son: request, response, out, session, application, config, pageContext y page. 3.3.1 request Este es el HttpServletRequest asociado con la petición, y nos permite mirar los parámetros de la petición (mediante getParameter), el tipo de petición (GET, POST, HEAD, etc.), y las cabeceras HTTP entrantes (cookies, Referer, etc.). Estrictamente hablando, se permite que la petición sea una subclase de ServletRequest distinta de HttpServletRequest, si el protocolo de la petición es distinto del HTTP. Esto casi nunca se lleva a la práctica. T
3.3.2 response Este es el HttpServletResponse asociado con la respuesta al cliente. Observa que, como el stream de salida (ver out más abajo) tiene un buffer, es legal seleccionar los códigos de estado y cabeceras de respuesta, aunque no está permitido en los servlets normales una vez que la salida ha sido enviada al cliente. 3.3.3 out Este es el PrintWriter usado para enviar la salida al cliente. Sin embargo, para poder hacer útil el objeto response (ver la sección anterior), esta es una versión con buffer de PrintWriter llamada JspWriter. Observa que podemos ajustar el tamaño del buffer, o incluso desactivar el buffer, usando el atributo buffer de la directiva page. También observa que out se usa casi exclusivamente en scriptlets ya que las expresiones JSP obtienen un lugar en el stream de salida, y por eso raramente se refieren explícitamente a out. 3.3.4 session Este es el objeto HttpSession asociado con la petición. Recuerda que las sesiones se crean automáticamente, por ello esta variable se une incluso si no hubiera una sesión de referencia entrante. La única excepción es usar el atributo session de la directiva page para desactivar las sesiones, en cuyo caso los intentos de referenciar la variable session causarán un error en el momento de traducir la página JSP a un servlet.
Pág. 7
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
3.4 Acción 3.4.1 Acción jsp:useBean Esta acción nos permite cargar y utilizar un JavaBean en la página JSP. Esta es una capacidad muy útil porque nos permite utilizar la reusabilidad de las clases Java sin sacrificar la conveniencia de añadir JSP sobre servlets solitarios. La sintaxis más simple para especificar que se debe usar un Bean es:
Esto normalmente significa "ejemplariza un objeto de la clase especificada por class, y unido a una variable con el nombre especificado por id". Sin embargo, también podemos especificar un atributo scope que hace que ese Bean se asocie con más de una sola página. Ahora, una vez que tenemos un bean, podemos modificar sus propiedades mediante jsp:setProperty, o usando un scriptlet y llamando a un método explícitamente sobre el objeto con el nombre de la variable especificada anteriormente mediante el atributo id. Recuerda que con los beans, cuando decimos "este bean tiene una propiedad del tipo X llamada foo", realmente queremos decir "Esta clase tiene un método getFoo que devuelve algo del tipo X, y otro método llamado setFoo que toma un X como un argumento". La acción jsp:setProperty se describe con más detalle en la siguiente sección, pero ahora observemos que podemos suministrar un valor explícito, dando un atributo param para decir que el valor está derivado del parámetro de la petición nombrado, o sólo lista las propiedades para indicar que el valor debería derivarse de los parámetros de la petición con el mismo nombre que la propiedad. Leemos las propiedades existentes en una expresión o scriptlet JSP llamando al método getXxx, o más comúnmente, usando la acción jsp:getProperty. No olvidar que todas las clases que se usan deben ir en el directorio classes o si es un fichero JAR en el directorio lib, no en el directorio servlets. 3.4.2 Acción jsp:getProperty Este elemento recupera el valor de una propiedad del bean, lo convierte a un string, e inserta el valor en la salida. Los dos atributos requeridos son name, el nombre de un bean referenciado anteriormente mediante jsp:useBean, y property, la propiedad cuyo valor debería ser insertado. Aquí tenemos un ejemplo:
Pág. 8
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
3.4.3 Acción jsp:forward Esta acción nos permite reenviar la petición a otra página. Tiene un sólo atributo, page, que debería consistir en una URL relativa. Este podría ser un valor estático, o podría ser calculado en el momento de la petición, como en estos dos ejemplos:
Ejercicios prácticos
Se trabajará con el Servidor Tomcat que viene por defecto en el IDE Netbeans 6.5, luego se debe crear un Nuevo Proyecto para ello seleccionar File > New Project .. ( Crtl + Shift + N ) ó
En el wizard seleccionamos en Categorías : Web y en Proyectos: Web Application y luego Siguiente (Next)
Pág. 9
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Se coloca el nombre del Proyecto: WebJSP, la ubicación física de este en la PC y luego Siguiente (Next).
Luego en Servidor (Server): Apache Tomcat 6.X, lo demás se mantiene igual y luego Finalizamos (Finish).
Pág. 10
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Nota.- Se debe apreciar que en Context Path hace referencia a como accederemos a la aplicación http://....../WebJSP esto se verá mas adelante. Como resultado se debe observar en el IDE
Modificamos el contenido de index.jsp usando los Scriptlets antes mencionados que nos permite colocar código java directamente
Pág. 11
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Luego se debe Ejecuta el Proyecto : Run > Run Main Project ó resultado obtenido seria :
Añadimos otro archivo JSP : File > New ó Ctrl + N y en el Wizard en Categorías seleccionar Web y en tipo de archivo JSP y luego Siguiente:
Pág. 12
(F6) y el
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
El nombre del archivo será “index2”
Pág. 13
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Luego colocar el siguiente código en el archivo index2:
index3.jsp recibe los datos
index2.jsp
Pág. 14
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Del código anterior se observa que el valor que se coloque en los campos dato_nombre y dato_apellido será enviado a otro archivo jsp (index3.jsp).
Luego crear el package beans y dentro crear la clase Persona que tiene el siguiente código:
Pág. 15
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Luego añadir otro archivo JSP y llamarlo index3 y colocar el siguiente código:
index3.jsp El archivo index3 recupera los valor enviados por index2.jsp y los muestra. Como array_persona es una variable de session los valores se almacenan mientras dure la sesión, esto se verifica insertando varios datos.
Pág. 16
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
4. JDBC Es el acrónimo de Java Database Connectivity, es un API (incluida tanto en las diferentes versiones de J2SE y J2EE) que permite la ejecución de operaciones mediante sintaxis SQL sobre bases de datos desde el lenguaje de programación Java. Entre las operaciones que se podrían realizar con la base de datos a las que tenga permiso son: consultas, actualizaciones, creado, modificado y borrado de tablas, etc. El api JDBC se puede encontrar en los paquetes: java.sql y javax.sql
java.sql.Connection Es la interfaz del paquete java.sql que representa la conexión con la base de datos. Pasos para obtener una conexión : Class.forName("com.mysql.jdbc.Driver").newInstance(); “Siempre se debe indicar el driver de la base de datos que se vaya utilizar.” Mediante la clase DriverManager (Gestor de drivers para acceso a bases de datos) obtenemos la conexión pasando como parámetros la cadena de conexión especificada por el proveedor de base de datos, usuario y password. La cadena de conexión suele llevar incluido la máquina (host) y puerto (port) donde se encuentra la instancia de base de datos a la que accedemos. Connection conn = DriverManager.getConnection ("jdbc:mysql://host:port/db”,“admin”,”pass”); // Mysql Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@HOST:PORT:SID",“admin”,”pass”); // ORACLE
Pág. 17
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
java.sql.Statement Es el objeto utilizado para ejecutar las sentencias SQL, el cual debe pedírselo al objeto Connection. Statement stmt = conn.createStatement(); A través del objeto Statement podemos lanzar las sentencias SQL. Los métodos más utilizados para ejecutar SQL son: “executeUpdate”, “executeQuerie” o “execute”. obtener una conexión : int updates = stmt.executeUpdate(“update USUARIOS set TLF = ‘917658991’ where COD = ‘1’ ”); stmt.close(); conn.close(); El cierre de los objetos al finalizar su uso es muy importante en el orden correspondiente al último abierto. java.sql.PreparedStatment La interfase PreparedStatement deriva directamente de Statement. Si queremos ejecutar muchas veces un objeto Statement, reduciremos el tiempo de ejecución si utilizamos un objeto PreparedStatement, en su lugar. PreparedStatement pstmt = conn.prepareStatement(“update USUARIOS set TLF = ? where COD = ? ”); pstmt.setString(“1”, “917658991”); pstmt.setString(“2”, “1”); pstmt.close(); java.sql.ResultSet Es el objeto en el cual se almacenan el resultado de las consultas, se obtiene a través del Statement, PreparedStament, CallableStament. Por ejemplo a través del Statement obtenido lanzamos consultas con el método executeQuery, este método nos devuelve un objeto Resultset con el resultado de la consulta. Pasos para obtener: ResultSet rs = stmt.executeQuery(“SELECT * FROM EMPLOYEES”); while(rs.next()) { System.out.println(rs.getString(“first_name”)); System.out.println(rs.getString(“last_name”)); } Pág. 18
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Para obtener los datos debemos ejecutar siempre el método “next” del Resultset, este método devuelve true/false en función de la disponibilidad de datos. rs.close(); Una vez procesada la información debemos cerrar el resultset. Existen otras muchas interfaces en los paquetes java.sql y javax.sql las anteriores servirán para los siguientes ejemplos. Ejercicio práctico Se tienen las siguientes pantallas:
Se tiene una pantalla de inicio donde luego se selecciona Lista de Empleados ó Nuevo Empleado:
Pág. 19
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Al seleccionar Lista de Empleados muestra una lista de personas con la información por columnas del Nombre, Apellido, Departamento y Email y una columna adicional que permite Borrar la fila correspondiente como se muestra en la siguiente pantalla.
Si hacemos clic en el enlace de William nos muestra la información del empleado del respectivo ID como se muestra en la siguiente pantalla.
Como se observa se tiene los Botones Inicio y Actualizar, el primero nos envía a la pantalla de inicio y el segundo guarda cualquier modificación realizada en el campo de texto correspondiente al Email y retornar a la pantalla de Lista de Empleados.
Pág. 20
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Para poder realizar lo anterior se tiene el siguiente esquema hr.
Para poder obtener las pantallas y el respectivo flujo entre ellas se crea el siguiente proyecto. Para poder obtener las pantallas y el respectivo flujo entre ellas se crea el proyecto: WebMysql igual que en el ejercicio anterior, se crea 4 nuevos jsp: o lista_employee.jsp (Muestra lista de Empleados) o data_employee.jsp o update_employee.jsp
Además se crea un package llamado conn y dentro los packages: bean y dao. Dentro de conn.bean crear las clases: BEmployee.java, BDepartments.java y BJobs.java Dentro de conn.servlet crear: DBase.java, DEmployees.java y DDepartments.java Se tendría:
Pág. 21
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Adicionalmente se debe agregar la librería necesaria para conectarse a la BD MySql para esto seleccionar con el botón derecho el Proyecto WebMysql y hacer click en Propiedades.
Pág. 22
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Hacer click en el botón Add Library, adicionar la librería MySQL JDBC Driver y luego hacer click en el botón Ok
La estructura de BEmployee.java tiene en cuenta los campos de la tabla Employees como se muestra en el código:
Pág. 23
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Pág. 24
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
La estructura de BDepartments.java tiene en cuenta los campos de la tabla Departments como se muestra en el código:
Pág. 25
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
La estructura de BJob.java tiene en cuenta los campos de la tabla Jobs como se muestra en el código:
Pág. 26
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
La clase DBase.java permite cargar el driver para MySQL, colocar la dirección, usuario y contraseña adecuados de la base de datos como se muestra en el siguiente código:
Usuario Contraseña
La clase DEmployee.java permite obtener del esquema hr , la lista de usuarios: List(); los datos de trabajador en función de su id: Data(int employee_id); y actualizar el correo de un usuario por medio de un objeto del tipo BEmployee: Update(BEmployee bemployee) como se muestra en el siguiente código:
Pág. 27
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Pág. 28
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Pág. 29
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Pág. 30
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
La clase DDepartments.java permite obtener del esquema hr , la lista de Departamentos: DepartmentsList();como se muestra en el siguiente código:
Pág. 31
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
El jsp index tiene 2 links como se muestra en el siguiente código:
El jsp list_employee muestra la información del empleado:
Pág. 32
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
Pág. 33
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
El jsp data_employee muestra la información del usuario seleccionado en la list_employee.jsp:
Pág. 34
INGENIERÍA DE LAS TELECOMUNICACIONES LABORATORIO DE SOFTWARE PARA TELECOMUNICACIONES 2 2009-1
El jsp update_employee actualiza el valor del email del usuario indicado por el parámetro “employee_id”:
Para finalizar solo resta ejecutar el Proyecto
Pág. 35
ó presionar F6.
View more...
Comments