Как использовать сервлеты и Ajax?

Я очень новичок в веб-приложениях и Сервлетах, и у меня есть следующий вопрос:

всякий раз, когда я печатаю что-то внутри сервлета и вызываю его веб-браузером, он возвращает новую страницу, содержащую этот текст. Есть ли способ распечатать текст на текущей странице с помощью Ajax?

7 ответов


действительно, ключевое слово "ajax":асинхронный JavaScript и XML. Однако в последние годы это происходит чаще, чем часто асинхронный JavaScript и JSON. В принципе, вы позволяете JS выполнять асинхронный HTTP-запрос и обновлять дерево HTML DOM на основе данных ответа.

так как это довольно нудно работа, чтобы заставить его работать во всех браузерах (особенно Internet Explorer по сравнению с другими), есть много библиотек JavaScript что упрощает это в отдельных функциях и охватывает как можно больше специфичных для браузера ошибок / причуд под капюшонами, таких как в jQuery, прототип, в 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 {
    // ...
}

или, когда вы еще не на контейнере, совместимом с сервлетом 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6 и т. д или новее), затем сопоставьте его в web.xml старомодный способ (см. также наша страница wiki сервлетов):

<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> as <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> as <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.

Ajaxifying существующую форму

вы можете использовать jQuery $.serialize() легко ajaxify существующие формы столба без возиться с собирать и проходить индивидуальные входные параметры формы. Предполагая существующую форму, которая отлично работает без JavaScript / jQuery (и, таким образом, изящно деградирует, когда у конечного пользователя отключен 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) {
        // ...
    }
});

обратите внимание, что много стартеров mix contentType с dataType. The contentType представляет тип из запрос тело. The dataType представляет (ожидаемый) тип ответ тело, которое обычно не требуется, поскольку jQuery уже автоопределяет его на основе ответа .

затем, чтобы обработать объект 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-адрес, как видит пользователь в адресной строке браузера. Так есть проблемы с bookmarkability. Поэтому гораздо лучше просто вернуть "инструкцию" для 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;
    }

    // ...
}

Читайте также:


правильный способ обновления страницы, отображаемой в настоящее время в браузере пользователя (без перезагрузки), - это выполнение некоторого кода в браузере для обновления DOM страницы.

этот код обычно является javascript, который встроен или связан с HTML-страницей, следовательно, предложение AJAX. (Фактически, если мы предположим, что обновленный текст поступает с сервера через HTTP-запрос, это классический AJAX.)

также можно реализовать такого рода вещи, используя некоторые плагин браузера или надстройка, хотя для плагина может быть сложно добраться до структур данных браузера для обновления DOM. (Плагины собственного кода обычно пишут в некоторый графический фрейм, встроенный в страницу.)


Я покажу вам целый пример сервлета и как сделать вызов ajax.

здесь мы создадим простой пример для создания формы входа с помощью сервлета.

.HTML-код

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

вот пример ajax

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

Код Сервлета 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.<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);
 }
});

Ajax (также AJAX) аббревиатура асинхронного JavaScript и XML) представляет собой группу взаимосвязанных методов веб-разработки, используемых на стороне клиента для создания асинхронных веб-приложений. С помощью Ajax веб-приложения могут асинхронно отправлять и извлекать данные с сервера Ниже приведен пример кода:

JSP page функция Java script для отправки данных в сервлет с двумя переменными firstName и 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);

    }

сервлет для чтения данных отправить обратно в jsp в xml формат (вы также можете использовать текст. Просто вам нужно изменить содержимое ответа на текст и отобразить данные в функции 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>");
}

обычно вы не можете обновить страницу из сервлета. Клиент (браузер)должен запросить обновление. Клиент Eiter загружает целую новую страницу или запрашивает обновление части существующей страницы. Эта техника называется "Аякса".


использование 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'
    });}
}

В Сервлет

request.getParameter("input")