| 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.sqlque representa las Clases para conectarse a Bases de Datos,java.utilque contiene Clases utilitarias Java ycom.osmosislatina.basesdedatosdonde se encuentra un "Pool" para conectarse a Bases de Datos.Se define la Clase(Servlet)
InsertarServletla cual hereda("inherit") el comportamiento deHttpServletcomo lo hace cualquier otro Servlet, para posteriormente definir dos campos (poolyconn) 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 entradaHttpServletRequestyHttpServletResponse, 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 ClaseStatementmediantePreparedStatmentes 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 objetoconnque es asignado aPreparedStatementya posee la conexión hacia la Base de Datos, la cual es realizada através del métodoinitdescrito posteriormente.Através del método
setStringdel Objetostatementes 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
ResultSetque representará los resultados de nuestra búsqueda; el inicio de la búsqueda es iniciado por medio del métodoexecuteQueryperteneciente 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 denextes 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
rsque indica la existencia del correo electrónico en la Base de Datos, si dicho correo existe ocurre lo siguiente:Es colocado un atributo llamado
razonrechazoen el Objetorequestque contiene la razón por la que no fue posible continuar con el proceso.Se invoca el método
rechazarInsertarcon los Objetosrequestyresponse(NOTA: El métodorechazarInsertarse describe posteriormente.
Son colocados los diversos valores proporcionados por el usuario en el objeto
request.Se invoca el método
aceptarInsertarcon los Objetosrequestyresponse(NOTA: El métodoaceptarInsertarse describe posteriormente.
Se invoca el método
closede la ClasesPreparedStatementyResultSetpara indicar el cierre de la búsqueda.Terminada la condicional se define la sección catch del Bloque, la cual invoca el método
rechazarInsertaren 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
RequestDispatcherque toma como parámetro el JSPerror.jsp.Se invoca el método
forwarddel Objetodispatchque 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ónconndeclarada como campo de la Clase y asignada en el métodoinitdel Servlet.Através del método
setStringdel Objetostatementson 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
executeUpdateque inicia el proceso de inserción en la Base de Datos.Se llama el método
closede la ClasePreparedStatementpara indicar el cierre de la inserción.Y finalmente termina el bloque definiéndose un Objeto del tipo
RequestDispatcherque 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
rechazarInsertardefinido 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
initprimeramente 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 campopooldefinido 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
destroysimplemente 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.
