¿Cómo usar 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 manera de imprimir el texto en la página actual usando Ajax?

De hecho, la palabra clave es “ajax”: JavaScript y XML asíncronos . Sin embargo, los últimos años es más que a menudo Asynchronous JavaScript and JSON . Básicamente, permite que JS ejecute una solicitud HTTP asíncrona y actualice el árbol DOM HTML basándose en los datos de respuesta.

Dado que es un trabajo bastante tedioso hacer que funcione en todos los navegadores (especialmente Internet Explorer versus otros), hay muchas bibliotecas de JavaScript que simplifican esto en funciones únicas y cubren la mayor cantidad posible de errores / peculiaridades específicas del navegador bajo las capuchas , como jQuery , Prototype , Mootools . Debido a que jQuery es más popular estos días, lo usaré en los ejemplos a continuación.

Ejemplo de reinicio que devuelve String como texto sin formato

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

 < !DOCTYPE html>   SO question 4112686      

Cree un servlet con un método doGet() que se vea 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. } 

Asigne este servlet a un patrón de URL de /someservlet o /someservlet/* como se /someservlet/* continuación (obviamente, el patrón de URL es libre para su elección, pero deberá modificar la URL de someservlet en ejemplos de código JS en todos los lugares según corresponda):

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

O bien, cuando todavía no está en un contenedor compatible con Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc. o más reciente), web.xml en web.xml la manera antigua (consulte también nuestra página wiki de Servlets ):

  someservlet com.example.SomeServlet   someservlet /someservlet/*  

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

Devolución de la List como JSON

Con JSON en lugar de texto sin formato como formato de respuesta, puede incluso dar algunos pasos más. Permite más dinámicas. En primer lugar, le gustaría tener una herramienta para convertir entre objetos Java y cadenas JSON. También hay muchos (consulte la parte inferior de esta página para obtener una descripció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 como

. El servlet:

 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List 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 = $("
    ").appendTo($("#somediv")); // Create HTML
    element and append it to HTML DOM element with ID "somediv". $.each(responseJson, function(index, item) { // Iterate over the JSON array. $("
  • ").text(item).appendTo($ul); // Create HTML
  • element, set its text content with currently iterated item and append it to the
      . }); }); });

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 a application/json . Si se olvida de configurarlo o depende de un text/plain predeterminado text/plain o text/html , entonces el argumento responseJson no le daría un objeto JSON, sino una cadena normal simple y tendría que manipularlo manualmente con JSON.parse() después, que es totalmente innecesario si configuras el tipo de contenido en primer lugar.

Retornando el Map como JSON

Aquí hay otro ejemplo que muestra Map como :

 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Map 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. $(" 

con

  

Devolución de la List como JSON

Aquí hay un ejemplo que muestra List en una

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 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 = $("").appendTo($("#somediv")); // Create HTML 
element and append it to HTML DOM element with ID "somediv". $.each(responseJson, function(index, product) { // Iterate over the JSON array. $("").appendTo($table) // Create HTML element, set its text content with currently iterated item and append it to the
. .append($(". .append($(". .append($(". }); }); });
").text(product.id)) // Create HTML element, set its text content with id of currently iterated product and append it to the
").text(product.name)) // Create HTML element, set its text content with name of currently iterated product and append it to the
").text(product.price)); // Create HTML element, set its text content with price of currently iterated product and append it to the

Devolución de la List como XML

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

 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List products = someProductService.list(); request.setAttribute("products", products); request.getRequestDispatcher("/WEB-INF/xml/products.jsp").forward(request, response); } 

El código JSP (nota: si coloca

en un , puede ser reutilizable en otro lugar en una respuesta que no sea 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" %>   
${product.id}

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  element and append its HTML to HTML DOM element with ID "somediv". }); }); 

Probablemente ya se habrá dado 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 cubiertas para su magia ajax.

Ajaxificar una forma existente

Puede usar jQuery $.serialize() para ajaxificar fácilmente los formularios de POST existentes sin tener que buscar y pasar 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 elegantemente cuando el usuario final tiene JavaScript desactivado):

 

Puedes mejorarlo progresivamente con ajax como se muestra a continuación:

 $(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 solicitudes normales y solicitudes ajax como a continuación:

 @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 jQuery Form hace menos o más lo mismo que el ejemplo anterior de jQuery, pero tiene soporte transparente adicional para multipart/form-data según lo requerido por las cargas de archivos.

Manualmente enviando parámetros de solicitud al servlet

Si no tiene un formulario en absoluto, pero solo quería interactuar con el servlet “en segundo plano” mediante el cual desea $.param() algunos datos, puede usar jQuery $.param() para convertir fácilmente un objeto JSON a una cadena de consulta codificada en URL.

 var params = { foo: "fooValue", bar: "barValue", baz: "bazValue" }; $.post("someservlet", $.param(params), function(response) { // ... }); 

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

Enviar manualmente el objeto JSON al servlet

Sin embargo, si tiene la intención de enviar el objeto JSON como un todo en lugar de como parámetros de solicitud individuales por alguna razón, entonces tendría que serializarlo en una cadena usando JSON.stringify() (que no forma parte de jQuery) e instruir a jQuery para establecer solicitar el tipo de contenido a application/json 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) { // ... } }); 

Tenga en cuenta que muchos de los principiantes mezclan contentType con dataType . contentType representa el tipo de cuerpo de la solicitud . El tipo de datos representa el tipo (esperado) del cuerpo de la respuesta , que generalmente no es necesario ya que jQuery ya lo detecta automáticamente en función del encabezado Content-Type la respuesta.

Entonces, para procesar el objeto JSON en el servlet que no se envía como parámetros de solicitud individuales, sino como una cadena JSON completa de la manera anterior, solo tiene que analizar manualmente el cuerpo de la solicitud utilizando una herramienta JSON en lugar de usar getParameter() la manera habitual. A saber, los servlets no son compatibles con las solicitudes formateadas de application/json , sino solo con solicitudes formateadas application/x-www-form-urlencoded o multipart/form-data . Gson también es compatible con 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 solo usar $.param() . Normalmente, desea utilizar JSON.stringify() solo si el servicio objective 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.

Envío de una redirección desde servlet

Es importante comprender y comprender que cualquier sendRedirect() y forward() por el servlet en una solicitud ajax solo reenviaría o redirigiría la solicitud ajax 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 de callback. Si representa una página HTML completa y no una respuesta XML o JSON específica para ajax, entonces todo lo que puede hacer es reemplazar el documento actual con ella.

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

Tenga en cuenta que esto no cambia la URL como usuario final ve en la barra de direcciones del navegador. Entonces hay problemas con la marcabilidad. Por lo tanto, es mucho mejor devolver una “instrucción” para JavaScript / jQuery para realizar una redirección en lugar de devolver todo el contenido de la página redirigida. Por ejemplo, al devolver un booleano o una URL.

 String redirectURL = "http://example.com"; Map 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; } // ... } 

Ver también:

  • Llame a Servlet e invoque el código Java desde JavaScript junto con los parámetros
  • Acceda a las variables Java / Servlet / JSP / JSTL / EL en JavaScript
  • ¿Cómo cambiar fácilmente entre un sitio web basado en Ajax y un sitio web HTML básico?
  • ¿Cómo subir archivos al servidor usando JSP / Servlet y Ajax?

La forma correcta de actualizar la página que se muestra actualmente en el navegador del usuario (sin volver a cargarla) es hacer que algún código ejecutado en el navegador actualice 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 de AJAX. (De hecho, si suponemos que el texto actualizado proviene del servidor a través de una solicitud HTTP, este es el AJAX clásico).

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

Te mostraré un ejemplo completo de servlet y cómo llama ajax.

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

index.html

 
Name:

Password:

Aquí está la muestra de ajax

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

Código de Servlet LoginServlet: –

  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); } } } 
 $.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.
"+ "The Details are as follws :
Name : "); }else{ $('#info').html("Sorry, there is some thing wrong with the data provided."); } }, error: function(e){ alert('Error: ' + e); } });

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

Función de script java de la página JSP para enviar datos a servlet con dos variables firstName y 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 los datos enviados de vuelta a jsp en formato xml (También podría usar texto. Solo necesita cambiar el contenido de la respuesta a texto y renderizar los 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("
"); response.getWriter().write(""+firstName+""); response.getWriter().write(""+lastName+""); response.getWriter().write("
"); }

Normalmente no puedes actualizar una página de 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 de una parte de una página existente. Esta técnica se llama Ajax.

Usar la selección múltiple de bootstrap

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")