Действительно, ключевое слово «ajax»: асинхронный JavaScript и XML . Однако в последние годы это чаще, чем асинхронный JavaScript и JSON . По сути, вы позволяете JS выполнять асинхронный HTTP-запрос и обновлять дерево DOM HTML на основе данных ответа.
Поскольку это довольно утомительная работа, чтобы заставить его работать во всех браузерах (особенно Internet Explorer и других), существует множество библиотек JavaScript, которые упрощают это в отдельных функциях и покрывают как можно больше специфичных для браузера ошибок / извращений. такие как jQuery , Prototype , Mootools . Поскольку jQuery наиболее популярен в наши дни, я буду использовать его в следующих примерах.
Пример Kickoff, возвращающийся в String
виде простого текста
Создайте /some.jsp
подобное ниже (примечание: код не ожидает, что файл JSP будет помещен в подпапку, если вы это сделаете, измените URL сервлета соответствующим образом):
<!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>
Создайте сервлет с doGet()
методом, который выглядит следующим образом:
@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.
}
Сопоставьте этот сервлет с шаблоном URL /someservlet
или /someservlet/*
как показано ниже (очевидно, шаблон URL является бесплатным по вашему выбору, но вам необходимо изменить someservlet
URL в примерах кода JS для всех мест соответственно):
@WebServlet("/someservlet/*")
public class SomeServlet extends HttpServlet {
// ...
}
Или, если вы еще не находитесь в контейнере, совместимом с Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6 и т. Д. Или более поздней web.xml
версии ), то сопоставьте его старомодным способом (см. Также нашу вики-страницу 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>
Теперь откройте http: // localhost: 8080 / context / test.jsp в браузере и нажмите кнопку. Вы увидите, что содержимое div обновляется ответом сервлета.
Возвращаясь List<String>
как JSON
С JSON вместо открытого текста в качестве формата ответа вы можете даже продвинуться дальше. Это учитывает больше динамики. Во-первых, вы хотели бы иметь инструмент для преобразования между объектами Java и строками JSON. Их также много (см. Обзор в нижней части этой страницы ). Мой личный фаворит - Google Gson . Скачайте и поместите его JAR-файл в /WEB-INF/lib
папку вашего веб-приложения.
Вот пример, который отображается List<String>
как <ul><li>
. Сервлет:
@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);
}
Код 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>.
});
});
});
Обратите внимание, что jQuery автоматически анализирует ответ как JSON и дает вам непосредственно объект JSON ( responseJson
) в качестве аргумента функции, когда вы устанавливаете тип содержимого ответа в application/json
. Если вы забудете установить его или полагаться на значение по умолчанию text/plain
или text/html
, то responseJson
аргумент не даст вам объект JSON, а будет простой ванильной строкой, и вам придется вручную JSON.parse()
потом поиграться, что, таким образом, совершенно не нужно, если вы установить тип контента прямо на первом месте.
Возвращаясь Map<String, String>
как JSON
Вот еще один пример, который отображается Map<String, String>
как <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);
}
И 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>.
});
});
});
с участием
<select id="someselect"></select>
Возвращаясь List<Entity>
как JSON
Вот пример , который показывает List<Product>
в <table>
котором Product
класс обладает свойствами Long id
, String name
и BigDecimal price
. Сервлет:
@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);
}
Код 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>.
});
});
});
Возврат в List<Entity>
виде XML
Вот пример, который делает то же самое, что и предыдущий пример, но затем с XML вместо JSON. При использовании JSP в качестве генератора вывода XML вы увидите, что кодировать таблицу и все менее утомительно. JSTL намного удобнее, так как вы можете использовать его для перебора результатов и выполнения форматирования данных на стороне сервера. Сервлет:
@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);
}
Код JSP (примечание: если вы вставите <table>
в <jsp:include>
, он может быть использован в другом месте в ответе не-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>
Код 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".
});
});
Теперь вы, вероятно, поймете, почему XML настолько мощнее, чем JSON, для конкретной цели обновления HTML-документа с помощью Ajax. JSON забавен, но в конце концов полезен только для так называемых «публичных веб-сервисов». Фреймворки MVC, такие как JSF, используют XML под прикрытием для своей магии ajax.
Аяксификация существующей формы
Вы можете использовать jQuery, $.serialize()
чтобы легко изменить существующие формы POST без необходимости собирать и передавать отдельные входные параметры формы. Предполагая, что существующая форма прекрасно работает без JavaScript / jQuery (и, следовательно, изящно ухудшается, когда в enduser отключен JavaScript):
<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>
Вы можете постепенно улучшать его с помощью AJAX, как показано ниже:
$(document).on("submit", "#someform", function(event) {
var $form = $(this);
$.post($form.attr("action"), $form.serialize(), function(response) {
// ...
});
event.preventDefault(); // Important! Prevents submitting the form.
});
В сервлете вы можете различить обычные запросы и запросы ajax, как показано ниже:
@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.
}
}
Плагин JQuery форма делает больше или меньше такой же , как описано выше , например JQuery, но имеет дополнительную прозрачную поддержку multipart/form-data
форм в соответствии с требованиями загрузки файлов.
Отправка параметров запроса в сервлет вручную
Если у вас вообще нет формы, но вы просто хотите взаимодействовать с сервлетом «в фоновом режиме», с помощью которого вы хотите разместить некоторые данные, вы можете использовать jQuery $.param()
для простого преобразования объекта JSON в кодировку URL-адреса. Строка запроса.
var params = {
foo: "fooValue",
bar: "barValue",
baz: "bazValue"
};
$.post("someservlet", $.param(params), function(response) {
// ...
});
Тот же doPost()
метод, который показан здесь выше, можно использовать повторно. Обратите внимание, что приведенный выше синтаксис также работает $.get()
в jQuery и doGet()
в сервлете.
Отправка объекта JSON вручную в сервлет
Однако если вы по какой-то причине намереваетесь отправить объект JSON целиком, а не как отдельные параметры запроса, вам нужно будет сериализовать его в строку, используя JSON.stringify()
(не являясь частью jQuery), и указать jQuery application/json
вместо этого установить тип содержимого запроса из (по умолчанию) application/x-www-form-urlencoded
. Это не может быть сделано с помощью $.post()
вспомогательной функции, но должно быть сделано, $.ajax()
как показано ниже.
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) {
// ...
}
});
Обратите внимание, что многие закуски смешиваются contentType
с dataType
. contentType
Представляет тип запроса органа. dataType
Представляет (ожидаемый) тип реакции тела, которое, как правило , нет необходимости , поскольку JQuery уже автоматически определяет его основе ответа в Content-Type
заголовке.
Затем, чтобы обработать объект JSON в сервлете, который отправляется не как отдельные параметры запроса, а как целая строка JSON описанным выше способом, вам нужно только вручную проанализировать тело запроса с помощью инструмента JSON вместо использования getParameter()
обычного путь. А именно, сервлеты не поддерживают application/json
отформатированные запросы, но только application/x-www-form-urlencoded
или multipart/form-data
отформатированные запросы. Gson также поддерживает анализ строки JSON в объект 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();
// ...
Обратите внимание, что все это более неуклюже, чем просто использование $.param()
. Обычно вы хотите использовать, JSON.stringify()
только если целевой службой является, например, служба JAX-RS (RESTful), которая по какой-то причине способна только принимать строки JSON, а не обычные параметры запроса.
Отправка перенаправления из сервлета
Важно осознать и понять, что любой sendRedirect()
и forward()
вызов сервлет на запрос AJAX будет только вперед или перенаправить запрос Ajax сам и не главный документ / окно , в котором запрос Ajax возник. В этом случае JavaScript / jQuery будет получать только перенаправленный / перенаправленный ответ как responseText
переменную в функции обратного вызова. Если он представляет собой целую HTML-страницу, а не специфичный для ajax ответ XML или JSON, тогда все, что вы можете сделать, это заменить текущий документ им.
document.open();
document.write(responseText);
document.close();
Обратите внимание, что это не меняет URL, как видит конечный пользователь в адресной строке браузера. Так что есть проблемы с закладкой. Поэтому гораздо лучше просто вернуть «инструкцию» для JavaScript / jQuery для выполнения перенаправления, а не для возврата всего содержимого перенаправленной страницы. Например, возвращая логическое значение или 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;
}
// ...
}
Смотрите также:
$("#somediv").html($(responseXml).find("data").html())
этой строки. Там также написано «Неверное количество аргументов или неверное присвоение свойства». Я также вижу, что мой XML заполняется данными, когда я их отлаживаю. Любые идеи ?Правильный способ обновить страницу, отображаемую в данный момент в браузере пользователя (без перезагрузки), - это выполнить некоторый код, выполняемый в браузере, для обновления DOM страницы.
Этот код, как правило, представляет собой javascript, который встроен или связан с HTML-страницей, отсюда и предложение AJAX. (Фактически, если мы предположим, что обновленный текст поступает с сервера через HTTP-запрос, это классический AJAX.)
Также возможно реализовать подобные вещи, используя некоторый плагин для браузера или надстройку, хотя плагину может быть сложно получить доступ к структурам данных браузера для обновления DOM. (Родные плагины кода обычно записывают в некоторый графический фрейм, встроенный в страницу.)
источник
Я покажу вам целый пример сервлета и как вызывать ajax.
Здесь мы собираемся создать простой пример для создания формы входа с использованием сервлета.
index.html
Вот пример AJAX
Код сервлета ЛогинСервлет: -
источник
источник
Ajax (также AJAX) аббревиатура для асинхронного JavaScript и XML) представляет собой группу взаимосвязанных методов веб-разработки, используемых на стороне клиента для создания асинхронных веб-приложений. С помощью Ajax веб-приложения могут отправлять данные и получать данные с сервера асинхронно. Ниже приведен пример кода:
JSP-страница java-скрипт для отправки данных сервлету с двумя переменными firstName и lastName:
Сервлет для чтения данных отправляется обратно в jsp в формате xml (вы также можете использовать текст. Просто вам нужно изменить содержимое ответа на текст и отобразить данные с помощью функции javascript.)
источник
Обычно вы не можете обновить страницу из сервлета. Клиент (браузер) должен запросить обновление. Клиент Eiter загружает целую новую страницу или запрашивает обновление части существующей страницы. Эта техника называется Ajax.
источник
Использование начальной загрузки
Ajax
В сервлете
источник