[Tutorial] Servlets y AJAX

Iniciado por Usuario Invitado, 25 Marzo 2015, 16:34 PM

0 Miembros y 1 Visitante están viendo este tema.

Usuario Invitado



SERVLETS Y AJAX



El presente pequeño tutorial, tiene como finalidad mostrar cómo interactuar entre Servlets y javascript, mediante AJAX, tomando como ejemplo un formulario de ingreso.


Se asume que el lector tiene noción de las siguientes tecnologías:

  • Lenguaje de programación Java
  • HTTP
  • Servlets
  • javascript
  • AJAX

    Si no se tiene nociones de las mencionadas tecnologías, se puede seguir el tutorial, ya que se explicarán algunos puntos. De todas maneras, el lector debe de investigar cada punto, término, trozo de código o afines que no entienda.

    Herramientas necesarias

    Para seguir perfectamente éste tutorial, se necesitarán las siguientes herramientas:

  • Eclipse Luna EE: IDE para programación en Java Enterprise Edition. No solo soporta el API estándar de Java, si no que también nos brinda soporte para la API empresarial.
  • NetBeans Java EE. Gran IDE con muy buen soporte para Java Enterprise Edition. Excelente editor de código y muy buen auto completado.
  • GlassFish: Servidor para aplicaciones Java web.
  • org.json.jar: Librería que nos permite transformar un Map o String a JSONObject y viceversa.



    Zona de descargas




    Notas de aclaración

    Dada la simpleza que requiere éste tutorial, NO se empleará un gestor de base de datos. El objetivo del presente documento es mostrar de forma práctica y sencilla, la comunicación entre servlets y AJAX.


    CONFIGURACIÓN DE ECLIPSE E INSTALACIÓN DE GLASSFISH



    Instalación de GlassFish Tools en Eclipse

    Abrimos nuestro Eclipse Luna EE. Si es primer uso, se preguntará dónde desea que sea el espacio de trabajo, por defecto es en la carpeta de usuario pero se puede especificar donde se desea (siempre y cuando tengamos permisos).

    Una vez abierto Eclipse, tenemos que instalar GlassFish Tools para poder instalar nuestro servidor GlassFish. Para ésto vamos a la opción Eclipse Marketplace del menú Help y buscamos "glassfish":


    Hacemos click en Install. Nos preguntará si aceptamos la licencia, elejimos el radio button "Yes. I accept..." y empezará a instalar GlassFish Tools (Si pregunta algo durante la instalación, dale "Yes"). Al finalizar la instalación nos pedirá reiniciar Eclipse. Aceptamos.

    Instalación de GlassFish 4.1

    Descomprimimos el zip que nos hemos bajado de la web de GlassFish y lo colocamos en:

    CitarC://program Files/

    De tal modo que la instalación de GlassFish quede así:

    CitarC://program Files/glassfish/

    Abrimos Eclipse y nos dirigimos hacia la opción Preferences del menú Window. Aquí desplegamos el menú Server -> Runtime Environments:


    Hacemos click en Add y nos mostrará una ventana con los adaptadores de servidores disponibles. Escogemos GlassFish 4 y hacemos click en Next:


    En la siguiente cara, tendremos que especificar la dirección de la instalación de GlassFish y el JDK:


    NOTA: Es bien importante que el elemento en "Java development kit" sea el JDK y no el JRE. Si les aparece JRE deben de agregar un nuevo "installed JRE" dentro de Java -> Installed JREs. Para ésto solo basta hacer click en Add y agregar la ruta del JDK de Java.

    Por último hacemos click en Next, dejamos todo por defecto y hacemos click en Finish para finalizar. Ya tenemos nuestro IDE listo para empezar a programar.


    INSTALAR NETBEANS Y GLASSFISH



    Al momento de instalar NetBeans Java EE, GlassFish viene incorporado. También Tomcat, pero pueden elegir no instalarlo sacando el checkbox de Tomcat 8:

"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

Usuario Invitado

#1
Primero que nada, necesitamos crear nuestro fichero index.jsp o index.html que contendrá el formulario de ingreso. Éste fichero va dentro del folder webapp, WebContent o WebPages (de acuerdo al IDE):

Código (html4strict) [Seleccionar]
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Identfíquese</title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="assets/css/login.css"/>
</head>
<body>
<div id="flogin" class="flogin">
        <section class="left-side">
            <section class="head">
                LOGIN
            </section>
            <section class="body">
                <section class="data">
                    <section class="form-group">
                        <span>Usuario:</span>
                        <section class="input-wrapper">
                            <input type="text" id="txt-username" class="txt"/>
                            <i class="fa fa-user"></i>
                        </section>
                    </section>
                    <section class="form-group">
                        <span>Contraseña:</span>
                        <section class="input-wrapper">
                            <input type="password" id="txt-password" class="txt"/>
                            <i class="fa fa-key"></i>
                        </section>
                    </section>
                </section>
                <section class="help">
                    <a href="">¿Olvidaste tu usuario o contraseña?</a>
                </section>
            </section>
        </section>
        <section id="btn-login" class="right-side">
            <i class="fa-4x fa fa-arrow-right"></i>
            <span>IR</span>
        </section>
    </div>

<!-- javascript files -->
<script src="assets/js/login.js"></script>
</body>
</html>


CSS:

Código (css) [Seleccionar]
* {
    margin: 0px;
    padding: 0px;
}
body {
    align-items: center;
    background-color: #f9f9f9;
    display: flex;
    height: 100vh;
    justify-content: center;
}
.flogin {
    display: flex;
    justify-content: space-between;
    width: 400px;
}
.flogin > .left-side {
    background-color: #363636;
    border: 9px solid #dedede;
    border-right: none;
    border-radius: 20px 0px 0px 20px;
    width: 80%;
}
.flogin  > .right-side {
    align-items: center;
    background-color: #34B5D5;
    border: 9px solid #dedede;
    border-left: none;
    border-radius: 0px 20px 20px 0px;
    display: flex;
    flex-flow: column nowrap;
    justify-content: space-between;
    padding: 1.3rem .2rem;
    width: calc(20% - 2*.2rem - 9px);
}
.flogin > .right-side:hover {
    cursor: pointer;
}

/*********************
      LEFT SIDE
*********************/
.left-side > .head {
    border-bottom: 2px dashed #ddd;
    color: #eee;
    font-family: "segoe ui";
    margin-bottom: 20px;
    padding: .75rem 1rem;
}
.left-side > .body {
    padding: .8rem 1.35rem;
    width: calc(100% * 2*1.35rem);
}
.body > .data {
    display: flex;
    justify-content: space-between;
}
.form-group {
    width: 45%;
}
.form-group > span {
    color: #ddd;
    display: block;
    font-family: "segoe ui";
    font-size: 10pt;
    margin-bottom: 7px;
}
.form-group > .input-wrapper {
    align-items: center;
    background-color: white;
    border-radius: 5px;
    box-shadow: 0px 2px 5px 1px rgba(0,0,0,.4) inset,
        0px -1px 2px 1px rgba(0,0,0,.25) inset;
    display: flex;
    justify-content: space-between;
}
.input-wrapper > .txt {
    width: 80%;
}
.input-wrapper > i {
    color: gold;
    width: 20%;
}
.txt {
    background-color: transparent;
    border: none;
    border-radius: 5px;
    padding: .4rem .25rem;
    width: calc(80% - 2*.35rem - 2*1px);
}
.txt:focus {
    outline: none;
}
.help {
    display: flex;
    justify-content: flex-end;
}

a {
    color: #ddd;
    display: block;
    font-family: "segoe ui";
    font-size: 10pt;
    font-style: italic;
    margin-top: 20px;
    text-align: right;
    text-decoration: none;
}

/*****************
    RIGHT SIDE
*****************/
.right-side > i {
    color: #fff;
    display: block;
}
.right-side > span {
    color: #fff;
    display: block;
    font-family: "segoe ui";
    font-size: 16pt;
}


Como ven es código HTML simple, en el cual se construye un formulario. Ahora, escribamos el código javascript que nos permita hacer la llamada AJAX al futuro servlet. Éste fichero va dentro del folder assets/js:

Código (javascript) [Seleccionar]
document.addEventListener("DOMContentLoaded", init, true);

function init() {
document.querySelector("#btn-login").addEventListener("click", handleLogin, true);

function handleLogin(e) {
e.preventDefault();
var txtUsername = document.querySelector("#txt-username");
var txtPassword = document.querySelector("#txt-password");

var userdata = '{"username":'+txtUsername.value+',"password":'+txtPassword.value+'}';

loginByAjax(userdata);
resetForm();
}

function loginByAjax(data) {
var request = new XMLHttpRequest();
request.open("POST", "LoginController", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.onreadystatechange = function() {
// si la respuesta fue exitosa
if(request.readyState == 4 && request.status == 200) {
var message = request.responseText;
alert(message);
}
// si la respuesta trajo error
else if(request.readyState == 4 && request.status != 200){
var message = request.responseText;
message = request.responseText;
alert(message);
}
};
request.send("userdata="+data);
}

function resetForm(form) {
var form = document.querySelector("#flogin");
var controls = form.querySelectorAll("input, select");

for(var i=0; i<controls.length; i++) {
var control = controls[i];
if(control.nodeName === "INPUT")
control.value = "";
else if(control.nodeName === "SELECT")
control.selectedIndex = 0;
}
controls[0].focus();
}

}


Como se puede observar, el código es muy sencillo. Escuchamos por evento submit del formulario y le decimos que se ejecutará la función handleLogin. Ésta función obtiene los valores ingresados en los textbox del formulario, crea un JSON en forma de texto y se lo envía al método loginByAjax(data) para que se envíe al servlet mediante AJAX.

El método loginByAjax tiene el siguiente código:

Código (javascript) [Seleccionar]
function loginByAjax(data) {
var request = new XMLHttpRequest();
request.open("POST", "LoginController", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.onreadystatechange = function() {
// si la respuesta fue exitosa
if(request.readyState == 4 && request.status == 200) {
var message = request.responseText;
alert(message);
}
// si la respuesta trajo error
else if(request.readyState == 4 && request.status != 200){
var message = request.responseText;
message = request.responseText;
alert(message);
}
};
request.send("userdata="+data);
}


Como vemos, el código lo único que hace es hacer una llamada AJAX al servet LoginController enviándole el parámetro recibido data, que es el JSON en forma de texto:

Código (javascript) [Seleccionar]
request.send("userdata="+data);

Si la llamada AJAX funciona exitosamente, mostraremos la respuesta retornada desde el servlet en un alert:

Código (javascript) [Seleccionar]
if(request.readyState == 4 && request.status == 200) {
var message = request.responseText;
alert(message);
}


Caso contrario, se mostrará también el mensaje de error en un alert. Quizás te estés preguntando, porqué la condición:

Código (javascript) [Seleccionar]
if(request.readyState == 4 && request.status == 200)

La petición tiene 5 estados, que son:

  • 0: Petición no inicializada
  • 1: Conexión establecida con el servidor.
  • 2: Petición recibida
  • 3: Procesando petición
  • 4: Petición finalizada y respuesta lista.

    Así mismo, cada petición tiene muchos códigos de estado. El código 200 indica que la petición ha sido exitosa, 404 indica que el recurso no ha sido encontrado, 500, error del servidor, etc. Puedes ver la lista de códigos aquí.

    Entonces, el código anterior se puede traducir a:

    Si la petición ha finalizado y la respuesta está lista, y además la petición ha sido exitosa...

    Por último, reseteamos el formulario para limpiar los campos y colocar el foco en el textbox del nombre de usuario.


    Ahora, nos queda crear nuestro servlet. Nuestro servlet se llamará LoginController y tendrá el siguiente código:

    Código (java) [Seleccionar]
    package com.company.controllers;

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.logging.Logger;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.json.JSONObject;

    @WebServlet(asyncSupported=true, urlPatterns={"/LoginController"})
    public class LoginController extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger("LoginLogger");

       public LoginController() {
           super();
       }

       public void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        response.setContentType("text/plain");
        String strJson = request.getParameter("userdata"); // obtiene lo enviado por AJAX
        JSONObject json = new JSONObject(strJson);
        String username = (String) json.get("username");
        String password = (String) json.get("password");
       
        if(username.equals("Duke") && password.equals("Duke777")) {
        writer.print("Usuario correctamente identificado");
        } else {
        writer.print("Usuario o contraseña incorrectas");
        }
        writer.flush();
        writer.close();
       }
       
       @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    try {
    processRequest(request, response);
    } catch(ServletException | IOException e) {
    logger.warning(e.getLocalizedMessage());
    }
    }

       @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        processRequest(request, response);
        } catch(ServletException | IOException e) {
        logger.warning(e.getLocalizedMessage());
        }
    }

    }


    Nuestro servlet no es nada del otro mundo, es muy sencillo. Explicaré las siguientes lineas:

    Código (java) [Seleccionar]
    String strJson = request.getParameter("userdata"); // obtiene lo enviado por AJAX
        JSONObject json = new JSONObject(strJson);


    ¿Recuerdas que en el código AJAX enviamos el JSON con el nombre de usuario y contraseña en formato texto? Bien, y tenía como identificador userdata.

    Como ves, esa variable userdata con el valor del JSON enviado desde AJAX, lo podemos obtener en nuestro Servlet mediante el método getParameter, el cual obtiene un valor pasado por parámetro mediante su identificador.

    En éste momento, strJson es equivalente al JSON en forma de texto enviado desde AJAX:

    Código (javascript) [Seleccionar]
    var userdata = '{"username":'+txtUsername.value+',"password":'+txtPassword.value+'}';

    Una vez que tenemos el valor enviado en nuestro servlet, lo que vamos a hacer es convertirlo a JSONObject:

    Código (java) [Seleccionar]
    JSONObject json = new JSONObject(strJson);

    JSONObject hace uso de un objeto tipo Map para poder trabajar fácilmente con pares "llave - valor". Por lo que, por medio de la llave podemos obtener su valor. Las llaves son username y password, entonces, solo obtenemos sus valores:

    Código (java) [Seleccionar]
    String username = (String) json.get("username");
        String password = (String) json.get("password");


    Y por último, evaluamos si el usuario es Duke y si la contraseña es Duke777. Si es correcto enviaremos el mensaje Usuario correctamente identificado o Usuario o contraseña incorrecta de vuelta a la llamada AJAX.

    Una vez que la respuesta ha sido devuelta a la llamada AJAX, solo la mostramos en un alert:

    Código (javascript) [Seleccionar]
    if(request.readyState == 4 && request.status == 200) {
    var message = request.responseText;
    alert(message);
    }
    // si la respuesta trajo error
    else if(request.readyState == 4 && request.status != 200){
    var message = request.responseText;
    message = request.responseText;
    alert(message);
    }




    CONCLUSIÓN



    Como el lector se ha dado cuenta, comunicar servlets con AJAX es realmente muy sencillo, tan sencillo como en otros lenguajes ;)


    ¡Hasta la próxima!
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein