java - implementar - peticion ajax servlet
¿Cómo usar Servlets y Ajax? (7)
Ajax (también AJAX) un acrónimo de JavaScript asíncrono y 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 asíncrona. A continuación se muestra un código de ejemplo:
La función de script java de la página Jsp para enviar datos al servlet con dos variables nombre y apellido:
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 a jsp en formato xml (También puede usar texto. Solo necesita cambiar el contenido de la respuesta al texto y generar 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>");
}
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 asíncrono y XML . Sin embargo, el año pasado es más frecuente que JavaScript asíncrono y JSON . Básicamente, le permite a JS ejecutar una solicitud HTTP asíncrona y actualizar el árbol de DOM HTML según los datos de respuesta.
Ya que es un trabajo bastante tedious hacerlo funcionar en todos los navegadores (especialmente en Internet Explorer en comparación con 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 , como jQuery , Prototype , Mootools . Dado que jQuery es el más popular en estos días, lo usaré en los siguientes ejemplos.
Ejemplo de inicio que devuelve String
como texto simple
Cree un /some.jsp
como abajo (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>
<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>
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 muestra a continuación (obviamente, el patrón de URL es gratuito para su elección, pero deberá modificar la URL de someservlet
en los ejemplos de código JS en todos los lugares correspondientes):
@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
// ...
}
O bien, cuando aún no esté en un contenedor compatible con Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc.), web.xml
en web.xml
la manera antigua (vea también nuestra página wiki Servlets ):
<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 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.
Devolviendo la List<String>
como JSON
Con JSON lugar de texto plano como formato de respuesta, incluso puede obtener algunos pasos más. Permite más dinámica. Primero, le gustaría tener una herramienta para convertir entre objetos Java y cadenas JSON. También hay muchos de ellos (consulte la parte inferior de esta página para obtener una descripción general). Mi favorito personal es Google Gson . Descargue y ponga su archivo JAR en la carpeta /WEB-INF/lib
de su aplicación web.
Aquí hay un ejemplo que muestra la 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 configura el tipo de contenido de respuesta en application/json
. Si olvida configurarlo o confía 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 tendría que manipular manualmente JSON.parse()
después, lo cual es totalmente innecesario si establece el tipo de contenido en primer lugar.
Devolviendo el 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 la 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>
Devolviendo la List<Entity>
como JSON
Este es un ejemplo que muestra la List<Product>
en una <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. Cuando use JSP como generador de salida XML, verá que es menos tedioso codificar la tabla y todo. JSTL es de esta manera mucho más útil, ya que puede usarlo 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 coloca la <table>
en un <jsp:include>
, 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" %>
<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".
});
});
A estas alturas, probablemente se dará cuenta de por qué XML es mucho más poderoso que JSON con el propósito particular de actualizar un documento HTML utilizando 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 coberturas para su magia ajax.
Ajaxifying un formulario existente
Puede usar jQuery $.serialize()
para ajustar fácilmente los formularios POST existentes sin tener que recoger y pasar los parámetros de entrada de formularios individuales. Asumiendo una forma 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>
Puede 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 solicitudes normales y solicitudes 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 jQuery Form hace más o menos lo mismo que en el ejemplo de jQuery anterior, pero tiene soporte transparente adicional para multipart/form-data
según lo requiera la carga de archivos.
Enviando manualmente los parámetros de solicitud al servlet.
Si no tiene un formulario en absoluto, pero solo quería interactuar con el servlet "en el fondo", por lo que le gustaría $.param()
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 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 al servlet
Sin embargo, si por alguna razón intenta enviar el objeto JSON como un todo en lugar de como parámetros de solicitud individuales, entonces necesita serializarlo a una cadena usando JSON.stringify()
(no es parte de jQuery) e instruir a jQuery para establecer solicite el tipo de contenido a application/json
lugar de (predeterminado) application/x-www-form-urlencoded
. Esto no puede hacerse 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 entrantes mezclan contentType
con dataType
. El contentType
representa el tipo del cuerpo de la solicitud . El dataType
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.
Luego, 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 forma anterior, solo necesita analizar manualmente el cuerpo de la solicitud utilizando una herramienta JSON en lugar de usar getParameter()
la forma habitual. Es decir, los servlets no admiten application/json
formato de application/json
, pero solo solicitudes con formato de application/x-www-form-urlencoded
o multipart/form-data
. 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 solo usar $.param()
. Normalmente, desea utilizar JSON.stringify()
solo si el servicio de destino es, por ejemplo, un servicio JAX-RS (RESTful) que por alguna razón solo puede consumir cadenas JSON y no parámetros de solicitud regulares.
Enviando un redireccionamiento desde servlet
Es importante comprender y comprender que cualquier sendRedirect()
y forward()
del servlet en una solicitud ajax solo reenviará o redireccionará la solicitud ajax en sí y no el documento / ventana principal donde se originó la solicitud ajax. En tal caso, JavaScript / jQuery solo recuperaría la respuesta redirigida / reenviada como variable de responseText
en la función de devolución de llamada. Si representa una página HTML completa y no una respuesta JSON o XML específica de ajax, entonces todo lo que podría 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 el usuario final ve en la barra de direcciones del navegador. Así que hay problemas con la marcabilidad. Por lo tanto, es mucho mejor simplemente 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, 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;
}
// ...
}
Ver también:
La forma correcta de actualizar la página que se muestra actualmente en el navegador del usuario (sin volver a cargarla) es hacer que se ejecute un código en el navegador para actualizar el DOM de la página.
Ese código suele ser javascript que está incrustado o vinculado desde la página HTML, de ahí la sugerencia de AJAX. (De hecho, si asumimos 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 utilizando algún complemento o complemento del navegador, aunque puede ser difícil para un complemento acceder 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).
Normalmente no puedes 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 de una parte de una página existente. Esta técnica se llama Ajax.
Te mostraré un ejemplo completo de servlet y cómo llamo ajax.
Aquí, vamos a crear el ejemplo simple para crear el formulario de inicio de sesión utilizando servlet.
index.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);
}
}
}
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")
$.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);
}
});