Vea el CODIGO FUENTE del JSP exito.jsp |
Vea el CODIGO FUENTE del JSP error.jsp |
Código Fuente InsertarServlet.java
Debido a la longitud del Servlet, éste se encuentra dividido en cinco secciones seguido de una descripción para cada fragmento; a diferencia del JSP empleado para realizar búsquedas en Bases de Datos, este Servlet se encuentra más modularizado através de funciones para incrementar la legibilidad y su uso en aplicaciones de alto tráfico.
package com.osmosislatina.basesdedatos; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import java.sql.*; import java.util.*; public class InsertarServlet extends HttpServlet {
|
En la parte superior de este Servlet se importan tres tipos de librerías ("packages"):
java.sql
que representa las Clases para conectarse a Bases de Datos,java.util
que contiene Clases utilitarias Java ycom.osmosislatina.basesdedatos
donde se encuentra un "Pool" para conectarse a Bases de Datos.Se define la Clase(Servlet)
InsertarServlet
la cual hereda("inherit") el comportamiento deHttpServlet
como lo hace cualquier otro Servlet, para posteriormente definir dos campos (pool
yconn
) que serán utilizados para definir la conexión hacia la Base de Datos así como su correspondiente "Pool".El primer método declarado corresponde al principal de cualquier Servlet (
service
) que contiene los conocidos objetos de entradaHttpServletRequest
yHttpServletResponse
, donde inicialmente se extraen los datos introducidos por el usuario en la forma HTML através del objetorequest
.
try { // Verificar si existe usario por Correo Electrónico String sql_busca = "select * CURSOJSP_ENCUESTA where email = ?"; PreparedStatement statement = conn.prepareStatement(sql_busca); statement.setString(1,email); ResultSet result = statement.executeQuery(); boolean rs = result.next(); if (rs) { // Si existe el usario, rechazar // Actualizar requisicion y llamar funcion de Rechazo request.setAttribute("razonrechazo", "El correo electrónico proporcionado ya existe en la Base de Datos"); rechazarInsertar(request,response); } else { // No existe el usuario, actualizar requisicion // Y llamar funcion para Insertar request.setAttribute("nombre",nombre); request.setAttribute("apellido",apellido); request.setAttribute("ciudad",ciudad); request.setAttribute("servcio",servicio); request.setAttribute("area",area); request.setAttribute("email",email); aceptarInsertar(request,response); } } statement.close(); result.close(); catch (SQLException exc) { // Registrar posibles error en SQL hacia registros ("Logs") // Actualizar requisicion y llamar funcion de Rechazo getServletContext().log(" Ocurrio un error en la base de Datos mientras se intentaba insertar datos", exc); request.setAttribute("razonrechazo", "Ocurrio un error en la Base de Datos"); rechazarInsertar(request,response); } } // TERMINA Método Service |
La sección anterior describe la parte central del Servlet ya que contiene la lógica para aceptar o rechazar datos, sin embargo, son utilizados métodos específicos para llevar acabo inserciones o rechazos de información a diferencia del JSP utilizado para realizar búsquedas.
Se inicia un bloque try/catch que incluirá el proceso de búsqueda en la Base de Datos.
Se define una secuencia de búqueda para la Base de Datos con la intención de verificar que el correo electrónico proporcionado no exista; nótese que la secuencia contiene el carácter
"?"
, dicho carácter será substituido por el dato proporcionado por el usuario.Es generado un Objeto del tipo
PreparedStatement
, a diferencia de la ClaseStatement
mediantePreparedStatment
es posible modificar parámetros de la secuencia SQL que cambian cada vez que sea producida una acción, esto permite que sea realizada una búsqueda en base al dato especifico proporcionado por el usuario; dicho Objeto es asociado con la conexión definida anteriormente, lo cual ocurre de la misma manera que la ClaseStatement
. El objetoconn
que es asignado aPreparedStatement
ya posee la conexión hacia la Base de Datos, la cual es realizada através del métodoinit
descrito posteriormente.Através del método
setString
del Objetostatement
es asociada la variable a la secuencia de búqueda SQL, los parámetros de este método indican la posición y valor asignado, donde la posición es representada por el carácter"?"
.Se genera un Objeto del tipo
ResultSet
que representará los resultados de nuestra búsqueda; el inicio de la búsqueda es iniciado por medio del métodoexecuteQuery
perteneciente a la ClasePreparedStatement
.Debido a que la búsqueda anterior retornará un renglón o un resultado nulo, se utiliza el método
next()
para verificar si existe el correo electrónico, si el resultado denext
es verdadero esto indica que fue retornado un resultado, caso contrario (falso) indica un resultado nulo; el valor de este método (next()
) es asignado a la variablers
.Es declarada una condicional en base al resultado de la variable
rs
que indica la existencia del correo electrónico en la Base de Datos, si dicho correo existe ocurre lo siguiente:Es colocado un atributo llamado
razonrechazo
en el Objetorequest
que contiene la razón por la que no fue posible continuar con el proceso.Se invoca el método
rechazarInsertar
con los Objetosrequest
yresponse
(NOTA: El métodorechazarInsertar
se describe posteriormente.
Son colocados los diversos valores proporcionados por el usuario en el objeto
request
.Se invoca el método
aceptarInsertar
con los Objetosrequest
yresponse
(NOTA: El métodoaceptarInsertar
se describe posteriormente.
Se invoca el método
close
de la ClasesPreparedStatement
yResultSet
para indicar el cierre de la búsqueda.Terminada la condicional se define la sección catch del Bloque, la cual invoca el método
rechazarInsertar
en caso de ocurrir un error imprevisto.
/** Redirecciona Errores a un Java Server Page **/ public void rechazarInsertar(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { RequestDispatcher dispatch = getServletContext().getRequestDispatcher("/servidordatos/error.jsp"); dispatch.forward(request, response); } |
El método rechazarInsertar
definido anteriormente es invocado en caso de ocurrir cualquier tipo de error al momento de insertar datos, a continuación se describe:
Se genera un Objeto del tipo
RequestDispatcher
que toma como parámetro el JSPerror.jsp
.Se invoca el método
forward
del Objetodispatch
que retorna el control hacia la página definida en el ObjetoRequestDispatcher
, en este caso el JSPerror.jsp
.
/** Insertar Datos en la Base de Datos **/ public void aceptarInsertar(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { try { // Preparar linea para insertar informacion String sql_inserta = "insert into CURSOJSP_ENCUESTA(nombre,apellido,ciudad,servicios,area,email) values ( ? , ? , ? , ? , ? , ?)"; PreparedStatement statement = conn.prepareStatement(sql_inserta); statement.setString(1,(String) request.getAttribute("nombre")); statement.setString(2,(String) request.getAttribute("apellido")); statement.setString(3,(String) request.getAttribute("ciudad")); statement.setString(4,(String) request.getAttribute("servicio")); statement.setString(5,(String) request.getAttribute("area")); statement.setString(6,(String) request.getAttribute("email")); // Ejecutar Inserción de Datos statement.executeUpdate(); statement.close(); // Enviar a Página de Exito RequestDispatcher dispatch = getServletContext().getRequestDispatcher("/servidordatos/exito.jsp"); } catch (SQLException exc) { // Registrar posibles error en SQL hacia registros ("Logs") // Actualizar requisición y llamar función de Rechazo getServletContext().log(" Ocurrió un error en la base de Datos mientras se intentaba insertar datos", exc); request.setAttribute("razonrechazo", "ocurrió un error en la Base de Datos"); rechazarInsertar(request,response); } } |
El método aceptarInsertar
es utilizado para llevar acabo la inserción en la Base de Datos, su funcionamiento es descrito en los siguientes incisos:
Se inicia un bloque try/catch que incluirá el proceso de inserción en la Base de datos.
Se define la secuencia de inserción para la Base de Datos; nótese que la secuencia contiene los caracteres
"?"
, dichos caracteres serán substituidos por los datos proporcionado por el usuario.Es generado un Objeto del tipo
PreparedStatement
, dicho Objeto es asociado con la conexiónconn
declarada como campo de la Clase y asignada en el métodoinit
del Servlet.Através del método
setString
del Objetostatement
son asociadas las variables a la secuencia de inserción, los parámetros de este método indican la posición y valor asignado, donde la posición es representada por el carácter"?"
.Se invoca el método
executeUpdate
que inicia el proceso de inserción en la Base de Datos.Se llama el método
close
de la ClasePreparedStatement
para indicar el cierre de la inserción.Y finalmente termina el bloque definiéndose un Objeto del tipo
RequestDispatcher
que redirecciona la solicitud hacia el JSPexito.jsp
.Dentro de la sección catch del Bloque es definida la lógica necesaria para invocar el método
rechazarInsertar
definido para procesar errores en la aplicación.
/** Crear el Pool de Conexión en Clase de Arranque init **/ public void init() { // Traer el Contexto de la Aplicación y colocar Pool recién generado ServletContext application = getServletContext(); pool = (IConexionPool) application.getAttribute("poolDeMysql"); if (pool == null) { // No había pool/conexión en el contexto // Generar pool/conexión try { // Asegurarse que el "Driver" este disponible Class.forName("com.mysql.jdbc.Driver").newInstance(); // Crear el Pool de Conexión y guardarlo en el contexto de la Aplicación pool = new ConexionPoolBasico("jdbc:mysql://localhost:3306/cursojsp","web","osmosis"); conn = pool.extraerConexion(); // Colocar conexión en el Contexto application.setAttribute("poolDeMysql",pool); } catch (Exception exc) { // Registrar posibles error en Driver hacia registros ("Logs") getServletContext().log("El \"Driver\" de la Base de Datos no se encontró u ocurrió un error al intentarse generar una conexión", exc); } } } /** Cerrar Conexión y re-asignar al Pool de Conexión en Clase de finalización destroy **/ public void destroy() { try { // Cerrar Conexión y Liberarla hacia Pool pool.liberarConexion(conn); } catch (Exception exc) { // Registrar posibles error en Driver hacia registros ("Logs") // Actualizar requisición y llamar función de Rechazo getServletContext().log("Error al liberar conexión", exc); } } |
Estos últimos métodos del Servlet son invocados al iniciarse y finalizarse la ejecución del método service, lo cual los hace idóneos para extraer y destruir una conexión hacia una Base de Datos.
En el método
init
primeramente se extrae el contexto de la aplicación y se revisa si existe un parámetro llamadopoolDeMysql
, este parámetro como su nombre lo indica representa el "Pool" de conexiones hacia la Base de Datos.En caso que este parámetro sea nulo (no exista) se define un bloque try/catch para adquirir un "Pool" de conexiones, en este bloque primeramente se verifica la existencia de la Clase
com.mysql.jdbc.Driver
, esta Clase es la que permite la conexión hacia una Base de Datos Mysql.Posteriormente se genera una instancia de la Clase principal del "Pool"
ConexionPoolBasico
, la cual toma como parámetros la información necesaria para conectarse a la Base de Datos Mysql y es asignada al campopool
definido al inicio del Servlet.Una vez establecido el Objeto
pool
éste es colocado dentro del Contexto de la aplicación, lo cual permite que otros JSP's y Servlets tengan acceso al mismo "Pool" simplemente extrayéndolo del objetoapplication
.Utilización de Contextos en Aplicación
El colocar objetos/parámetros en el contexto de una aplicación tiene el mismo principio que emplear "Pool's" hacia Bases de Datos, que es justamente reutilizar y eficientizar el uso de recursos en un diseño con JSP's y Servlets.
Al colocar un objeto en contexto se garantiza que éste se encuentre accesible a todos los usuarios de una aplicación, mientras el uso de sesiones permite guardar determinados datos para cada usuario que navegue determinada secuencia de JSP's o Servlets, mediante el contexto se puede compartir un recurso entre determinados usuarios.
En este caso, el generar un "Pool" de conexiones para cada usuario que accese el Servlet puede ocasionar una severa carga sobre el servidor y por ende en el tiempo de respuesta de la aplicación, por esta razón se opta por extraer un "Pool" ya generado dentro del contexto.
Finalmente vale mencionar que el colocar objetos dentro del contexto de una aplicación también puede ser de utilidad para otros objetos que sean compartidos entre diversos usuarios (sesiones) tales como un catalogo de productos o una lista de usuarios.
En el método
destroy
simplemente se define un bloque try/catch que invoca el métodoliberarConexion
(perteneciente al "Pool" de conexión diseñado anteriormente) que se hace cargo liberar la conexión hacia la Base de Datos.