Cómo utilizar Servlets y Ajax?


Soy muy nuevo en aplicaciones web y Servlets y tengo la siguiente pregunta:

Cada vez que imprimo algo dentro del servlet y lo llamo por el navegador web, devuelve una nueva página que contiene ese texto. ¿Hay alguna forma de imprimir el texto en la página actual usando Ajax?

Author: Taryn, 2010-11-06

7 answers

De hecho, la palabra clave es "ajax": JavaScript asíncrono y XML. Sin embargo, los últimos años es más que a menudo JavaScript asíncrono y JSON. Básicamente, permite que JS ejecute una solicitud HTTP asíncrona y actualice el árbol DOM HTML en función de los datos de respuesta.

Dado que es bastante un tedioso trabajo para que funcione en todos los navegadores (especialmente Internet Explorer frente a otros), hay un montón de bibliotecas de JavaScript que simplifica esto en funciones individuales y cubre tantos como sea posible errores/peculiaridades específicos del navegador bajo las capuchas, como jQuery, Prototipo, Mootools . Dado que jQuery es más popular en estos días, lo usaré en los siguientes ejemplos.

Ejemplo de Kickoff que devuelve String como texto sin formato

Cree un /some.jsp como el siguiente (nota: el código no espera que el archivo JSP se coloque en una subcarpeta, si lo hace, altere la URL del servlet en consecuencia):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>SO question 4112686</title>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script>
        <script>
            $(document).on("click", "#somebutton", function() { // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
                $.get("someservlet", function(responseText) {   // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response text...
                    $("#somediv").text(responseText);           // Locate HTML DOM element with ID "somediv" and set its text content with the response text.
                });
            });
        </script>
    </head>
    <body>
        <button id="somebutton">press here</button>
        <div id="somediv"></div>
    </body>
</html>

Crear un servlet con un método doGet() que se ve así:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String text = "some text";

    response.setContentType("text/plain");  // Set content type of the response so that jQuery knows what it can expect.
    response.setCharacterEncoding("UTF-8"); // You want world domination, huh?
    response.getWriter().write(text);       // Write response body.
}

Mapee este servlet en un patrón de URL de /someservlet o /someservlet/* como se muestra a continuación (obviamente, el patrón de URL es libre a su elección, pero tendría que alterar la URL someservlet en ejemplos de código JS sobre todo lugar en consecuencia):

@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
    // ...
}

O, cuando aún no esté en un contenedor compatible con Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc. o más reciente), mapéelo en web.xml a la antigua usanza (vea también nuestro wiki de Servlets página):

<servlet>
    <servlet-name>someservlet</servlet-name>
    <servlet-class>com.example.SomeServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>someservlet</servlet-name>
    <url-pattern>/someservlet/*</url-pattern>
</servlet-mapping>

Ahora abre el http://localhost:8080/context/test.jsp en el navegador y pulse el botón. Verás que el contenido del div se actualiza con la respuesta del servlet.

Volviendo List<String> como JSON

Con JSON en lugar de texto plano como formato de respuesta, incluso puede obtener algunos pasos más. Permite más dinámica. Primero, te gustaría tener una herramienta para convertir entre objetos Java y cadenas JSON. Hay un montón de ellos también (ver la parte inferior de esta página para una visión general). Mi favorito personal es Google Gson . Descargue y coloque su archivo JAR en la carpeta /WEB-INF/lib de su aplicación web.

Aquí hay un ejemplo que muestra List<String> como <ul><li>. El servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<String> list = new ArrayList<>();
    list.add("item1");
    list.add("item2");
    list.add("item3");
    String json = new Gson().toJson(list);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

El código JS:

$(document).on("click", "#somebutton", function() {  // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {    // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $ul = $("<ul>").appendTo($("#somediv")); // Create HTML <ul> element and append it to HTML DOM element with ID "somediv".
        $.each(responseJson, function(index, item) { // Iterate over the JSON array.
            $("<li>").text(item).appendTo($ul);      // Create HTML <li> element, set its text content with currently iterated item and append it to the <ul>.
        });
    });
});

Tenga en cuenta que jQuery analiza automáticamente la respuesta como JSON y le proporciona directamente un objeto JSON (responseJson) como argumento de función cuando establece el tipo de contenido de respuesta en application/json. Si se olvida de configurarlo o se basa en un valor predeterminado de text/plain o text/html, entonces el argumento responseJson no le daría un objeto JSON, sino una cadena de vainilla simple y necesitaría juguetear manualmente con JSON.parse() después, lo cual es totalmente innecesario si establece el tipo de contenido correcto en primer lugar.

Volviendo Map<String, String> como JSON

Aquí hay otro ejemplo que muestra Map<String, String> como <option>:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Map<String, String> options = new LinkedHashMap<>();
    options.put("value1", "label1");
    options.put("value2", "label2");
    options.put("value3", "label3");
    String json = new Gson().toJson(options);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

Y el JSP:

$(document).on("click", "#somebutton", function() {               // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {                 // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $select = $("#someselect");                           // Locate HTML DOM element with ID "someselect".
        $select.find("option").remove();                          // Find all child elements with tag name "option" and remove them (just to prevent duplicate options when button is pressed again).
        $.each(responseJson, function(key, value) {               // Iterate over the JSON object.
            $("<option>").val(key).text(value).appendTo($select); // Create HTML <option> element, set its value with currently iterated key and its text content with currently iterated item and finally append it to the <select>.
        });
    });
});

Con

<select id="someselect"></select>

Volviendo List<Entity> como JSON

Aquí hay un ejemplo que muestra List<Product> en un <table> donde la clase Product tiene las propiedades Long id, String name y BigDecimal price. El servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<Product> products = someProductService.list();
    String json = new Gson().toJson(products);

    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

El código JS:

$(document).on("click", "#somebutton", function() {        // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseJson) {          // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response JSON...
        var $table = $("<table>").appendTo($("#somediv")); // Create HTML <table> element and append it to HTML DOM element with ID "somediv".
        $.each(responseJson, function(index, product) {    // Iterate over the JSON array.
            $("<tr>").appendTo($table)                     // Create HTML <tr> element, set its text content with currently iterated item and append it to the <table>.
                .append($("<td>").text(product.id))        // Create HTML <td> element, set its text content with id of currently iterated product and append it to the <tr>.
                .append($("<td>").text(product.name))      // Create HTML <td> element, set its text content with name of currently iterated product and append it to the <tr>.
                .append($("<td>").text(product.price));    // Create HTML <td> element, set its text content with price of currently iterated product and append it to the <tr>.
        });
    });
});

Devolviendo List<Entity> como XML

Aquí hay un ejemplo que hace efectivamente lo mismo que el ejemplo anterior, pero luego con XML en lugar de JSON. Al usar JSP como generador de salida XML verás que es menos tedioso codificar la tabla y todo. JSTL es de esta manera mucho más útil, ya que en realidad se puede utilizar para iterar sobre los resultados y realizar el formateo de datos del lado del servidor. El servlet:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    List<Product> products = someProductService.list();

    request.setAttribute("products", products);
    request.getRequestDispatcher("/WEB-INF/xml/products.jsp").forward(request, response);
}

El código JSP (nota: si pones el <table> en un <jsp:include>, puede ser reutilizable en otro lugar en una respuesta no ajax):

<?xml version="1.0" encoding="UTF-8"?>
<%@page contentType="application/xml" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<data>
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.id}</td>
                <td><c:out value="${product.name}" /></td>
                <td><fmt:formatNumber value="${product.price}" type="currency" currencyCode="USD" /></td>
            </tr>
        </c:forEach>
    </table>
</data>

El código JS:

$(document).on("click", "#somebutton", function() {             // When HTML DOM "click" event is invoked on element with ID "somebutton", execute the following function...
    $.get("someservlet", function(responseXml) {                // Execute Ajax GET request on URL of "someservlet" and execute the following function with Ajax response XML...
        $("#somediv").html($(responseXml).find("data").html()); // Parse XML, find <data> element and append its HTML to HTML DOM element with ID "somediv".
    });
});

Probablemente se dará cuenta de por qué XML es mucho más poderoso que JSON para el propósito particular de actualizar un documento HTML usando Ajax. JSON es divertido, pero después de todo generalmente solo es útil para los llamados "servicios web públicos". Los frameworks MVC como JSF usan XML bajo las carátulas para su magia ajax.

Ajaxificar una forma existente

Puede usar jQuery $.serialize() para ajaxificar fácilmente los formularios POST existentes sin jugar con la recopilación y el paso de los parámetros de entrada de formularios individuales. Asumiendo un formulario existente que funciona perfectamente bien sin JavaScript / jQuery (y por lo tanto se degrada con gracia cuando el usuario final tiene JavaScript desactivado):

<form id="someform" action="someservlet" method="post">
    <input type="text" name="foo" />
    <input type="text" name="bar" />
    <input type="text" name="baz" />
    <input type="submit" name="submit" value="Submit" />
</form>

Puedes mejorarlo progresivamente con ajax de la siguiente manera:

$(document).on("submit", "#someform", function(event) {
    var $form = $(this);

    $.post($form.attr("action"), $form.serialize(), function(response) {
        // ...
    });

    event.preventDefault(); // Important! Prevents submitting the form.
});

En el servlet puede distinguir entre peticiones normales y peticiones ajax de la siguiente manera:

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String foo = request.getParameter("foo");
    String bar = request.getParameter("bar");
    String baz = request.getParameter("baz");

    boolean ajax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));

    // ...

    if (ajax) {
        // Handle ajax (JSON or XML) response.
    } else {
        // Handle regular (JSP) response.
    }
}

El complemento de formulario jQuery hace menos o más lo mismo que el ejemplo anterior de jQuery, pero tiene soporte transparente adicional para los formularios multipart/form-data según lo requerido por las cargas de archivos.

Enviando manualmente parámetros de solicitud a servlet

Si no tienes un formulario en absoluto, pero solo quería interactuar con el servlet" en segundo plano " por lo que le gustaría publicar algunos datos, a continuación, puede utilizar jQuery $.param() para convertir fácilmente un objeto JSON en una cadena de consulta codificada por URL.

var params = {
    foo: "fooValue",
    bar: "barValue",
    baz: "bazValue"
};

$.post("someservlet", $.param(params), function(response) {
    // ...
});

El mismo método doPost() como se muestra aquí arriba puede ser reutilizado. Tenga en cuenta que la sintaxis anterior también funciona con $.get() en jQuery y doGet() en servlet.

Enviando manualmente el objeto JSON a servlet

Sin embargo, si tiene la intención de enviar el objeto JSON como un whole en lugar de como parámetros de solicitud individuales por alguna razón, entonces tendría que serializarlo a una cadena usando JSON.stringify() (no forma parte de jQuery) e indica a jQuery que establezca el tipo de contenido de la solicitud en application/json en lugar de (predeterminado) application/x-www-form-urlencoded. Esto no se puede hacer a través de la función de conveniencia $.post(), pero debe hacerse a través de $.ajax() como se muestra a continuación.

var data = {
    foo: "fooValue",
    bar: "barValue",
    baz: "bazValue"
};

$.ajax({
    type: "POST",
    url: "someservlet",
    contentType: "application/json", // NOT dataType!
    data: JSON.stringify(data),
    success: function(response) {
        // ...
    }
});

Ten en cuenta que muchos entrantes mezclan contentType con dataType. El contentTyperepresenta el tipo del cuerpo request. El dataType representa el tipo (esperado) del cuerpo response, que generalmente es innecesario ya que jQuery lo detecta automáticamente en función del encabezado Content-Type de response.

Entonces, para procesar el objeto JSON en el servlet que no se está enviando como parámetros de solicitud individuales sino como una cadena JSON completa de la manera anterior, solo necesita analizar manualmente el cuerpo de la solicitud usando una herramienta JSON en lugar de usar getParameter() de la manera habitual. Es decir, los servlets no admiten solicitudes con formato application/json , pero solo application/x-www-form-urlencoded o multipart/form-data solicitudes formateadas. Gson también admite el análisis de una cadena JSON en un objeto JSON.

JsonObject data = new Gson().fromJson(request.getReader(), JsonObject.class);
String foo = data.get("foo").getAsString();
String bar = data.get("bar").getAsString();
String baz = data.get("baz").getAsString();
// ...

Tenga en cuenta que todo esto es más torpe que simplemente usar $.param(). Normalmente, desea usar JSON.stringify() solo si el servicio de destino es, por ejemplo, un servicio JAX-RS (RESTful) que por alguna razón solo es capaz de consumir cadenas JSON y no parámetros de solicitud regulares.

Enviando una redirección desde servlet

Importante darse cuenta y entender es que cualquier sendRedirect() y forward()la llamada por el servlet en una solicitud ajax solo reenvía o redirige la solicitud ajax en sí y no el documento/ventana principal donde se originó la solicitud ajax. JavaScript / jQuery en tal caso solo recuperaría la respuesta redirigida/reenviada como variable responseText en la función callback. Si representa una página HTML completa y no una respuesta XML o JSON específica de ajax, entonces todo lo que puede hacer es reemplazar el documento actual con él.

document.open();
document.write(responseText);
document.close();

Tenga en cuenta que esto no cambia la URL como el usuario final ve en la barra de direcciones del navegador. Así que hay problemas con la bookmarkability. Por lo tanto, es mucho mejor simplemente devolver una "instrucción" para que JavaScript/jQuery realice una redirección en lugar de devolver todo el contenido de la página redirigida. Por ejemplo, devolviendo un booleano o una URL.

String redirectURL = "http://example.com";

Map<String, String> data = new HashMap<>();
data.put("redirect", redirectURL);
String json = new Gson().toJson(data);

response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);

function(responseJson) {
    if (responseJson.redirect) {
        window.location = responseJson.redirect;
        return;
    }

    // ...
}

Véase también:

 510
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:18

La forma correcta de actualizar la página que se muestra actualmente en el navegador del usuario (sin recargarla) es tener algún código ejecutándose en el navegador para actualizar el DOM de la página.

Ese código es típicamente javascript que está incrustado o vinculado desde la página HTML, de ahí la sugerencia AJAX. (De hecho, si asumimos que el texto actualizado proviene del servidor a través de una solicitud HTTP, esto es AJAX clásico.)

También es posible implementar este tipo de cosas usando algún complemento del navegador o add-on, aunque puede ser difícil para un plugin para llegar a las estructuras de datos del navegador para actualizar el DOM. (Los complementos de código nativo normalmente escriben en algún marco gráfico que está incrustado en la página.)

 13
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-16 22:40:36

Le mostraré un ejemplo completo de servlet y cómo llamar ajax.

Aquí, vamos a crear el ejemplo simple para crear el formulario de inicio de sesión usando servlet.

Índice.html

<form>  
   Name:<input type="text" name="username"/><br/><br/>  
   Password:<input type="password" name="userpass"/><br/><br/>  
   <input type="button" value="login"/>  
</form>  

Aquí está la muestra de ajax

       $.ajax
        ({
            type: "POST",           
            data: 'LoginServlet='+name+'&name='+type+'&pass='+password,
            url: url,
        success:function(content)
        {
                $('#center').html(content);           
            }           
        });

LoginServlet Código de Servlet :-

    package abc.servlet;

import java.io.File;


public class AuthenticationServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {   
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        try{
        HttpSession session = request.getSession();
        String username = request.getParameter("name");
        String password = request.getParameter("pass");

                /// Your Code
out.println("sucess / failer")
        } catch (Exception ex) {
            // System.err.println("Initial SessionFactory creation failed.");
            ex.printStackTrace();
            System.exit(0);
        } 
    }
}
 11
Author: Mitul Maheshwari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-29 17:08:28
$.ajax({
type: "POST",
url: "url to hit on servelet",
data:   JSON.stringify(json),
dataType: "json",
success: function(response){
    // we have the response
    if(response.status == "SUCCESS"){
        $('#info').html("Info  has been added to the list successfully.<br>"+
        "The  Details are as follws : <br> Name : ");

    }else{
        $('#info').html("Sorry, there is some thing wrong with the data provided.");
    }
},
 error: function(e){
   alert('Error: ' + e);
 }
});
 6
Author: SUBZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-09 09:11:57

Ajax (también AJAX) un acrónimo de Asynchronous JavaScript y XML) es un grupo de técnicas de desarrollo web interrelacionadas utilizadas en el lado del cliente para crear aplicaciones web asincrónicas. Con Ajax, las aplicaciones web pueden enviar y recuperar datos de un servidor de forma asíncrona A continuación se muestra un código de ejemplo:

Jsp page java script function to submit data to servlet with two variable FirstName and LastName:

function onChangeSubmitCallWebServiceAJAX()
    {
      createXmlHttpRequest();
      var firstName=document.getElementById("firstName").value;
      var lastName=document.getElementById("lastName").value;
      xmlHttp.open("GET","/AJAXServletCallSample/AjaxServlet?firstName="
      +firstName+"&lastName="+lastName,true)
      xmlHttp.onreadystatechange=handleStateChange;
      xmlHttp.send(null);

    }

Servlet para leer datos enviar de vuelta a jsp en formato xml (Usted podría usar texto también. Solo necesita cambiar el contenido de la respuesta a texto y renderizar datos en la función javascript.)

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String firstName = request.getParameter("firstName");
    String lastName = request.getParameter("lastName");

    response.setContentType("text/xml");
    response.setHeader("Cache-Control", "no-cache");
    response.getWriter().write("<details>");
    response.getWriter().write("<firstName>"+firstName+"</firstName>");
    response.getWriter().write("<lastName>"+lastName+"</lastName>");
    response.getWriter().write("</details>");
}
 6
Author: user3468976,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-02 22:09:12

Normalmente no se puede actualizar una página desde un servlet. El cliente (navegador) tiene que solicitar una actualización. El cliente Eiter carga una página completamente nueva o solicita una actualización a una parte de una página existente. Esta técnica se llama Ajax.

 4
Author: Peter Knego,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-06 10:30:37

Usando bootstrap multi select

Ajax

function() { $.ajax({
    type : "get",
    url : "OperatorController",
    data : "input=" + $('#province').val(),
    success : function(msg) {
    var arrayOfObjects = eval(msg); 
    $("#operators").multiselect('dataprovider',
    arrayOfObjects);
    // $('#output').append(obj);
    },
    dataType : 'text'
    });}
}

En Servlet

request.getParameter("input")
 3
Author: Thakhani Tharage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-03 11:04:14