每当我在servlet中打印一些内容并由web浏览器调用它时,它都会返回一个包含该文本的新页面。是否有一种方法可以使用Ajax打印当前页面中的文本?

我对web应用程序和servlet非常陌生。


当前回答

通常不能从servlet更新页面。客户端(浏览器)必须请求更新。客户端要么加载一个全新的页面,要么请求更新现有页面的某个部分。这种技术称为Ajax。

其他回答

通常不能从servlet更新页面。客户端(浏览器)必须请求更新。客户端要么加载一个全新的页面,要么请求更新现有页面的某个部分。这种技术称为Ajax。

更新用户浏览器中当前显示的页面(无需重新加载)的正确方法是在浏览器中执行一些代码来更新页面的DOM。

该代码通常是嵌入在HTML页面或从HTML页面链接的JavaScript,因此建议使用Ajax。(事实上,如果我们假设更新的文本通过HTTP请求来自服务器,这就是典型的Ajax。)

也可以使用一些浏览器插件或附加组件来实现这类事情,尽管插件要到达浏览器的数据结构来更新DOM可能有些棘手。(本地代码插件通常写入嵌入在页面中的图形帧。)

事实上,关键字是“Ajax”:异步JavaScript和XML。然而,在过去的几年里,更多的是异步JavaScript和JSON。基本上,让JavaScript执行异步HTTP请求,并根据响应数据更新HTML DOM树。

因为让它在所有浏览器上都能正常工作是一件非常繁琐的工作(尤其是Internet Explorer和其他浏览器),所以有很多JavaScript库可以在单个函数中简化它,并在底层覆盖尽可能多的浏览器特定的bug /癖好,比如jQuery、Prototype、Mootools。由于jQuery现在最流行,我将在下面的示例中使用它。

启动示例返回字符串为纯文本

创建如下所示的/some.jsp(注意:这个答案中的代码片段并不期望JSP文件被放置在子文件夹中,如果您这样做,将servlet URL相应地从“someservlet”更改为“${pageContext.request.contextPath}/someservlet”;只是为了简洁起见,在代码片段中省略了它):

<!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()方法创建一个servlet,如下所示:

@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.
}

将这个servlet映射到/someservlet或/someservlet/*的URL模式上,如下所示(显然,URL模式由您自由选择,但您需要在所有的JS代码示例中相应地更改someservlet URL):

package com.example;

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

或者,当你还没有使用Servlet 3.0兼容的容器(Tomcat 7, GlassFish 3, JBoss AS 6等或更新版本),然后用传统的方式在web.xml中映射它(参见我们的Servlet 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的内容随着servlet响应而更新。

返回String>的JSON格式

使用JSON而不是纯文本作为响应格式,您甚至可以更进一步。它允许更多的动态。首先,您希望有一个工具在Java对象和JSON字符串之间进行转换。也有很多这样的方法(请参阅本页底部的概述)。我个人最喜欢的是谷歌Gson。下载并将其JAR文件放在web应用程序的/ web - inf /lib文件夹中。

下面是一个将List<String>显示为<ul><li>的例子。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);
}

JavaScript代码:

$(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>.
        });
    });
});

Do note that jQuery automatically parses the response as JSON and gives you directly a JSON object (responseJson) as function argument when you set the response content type to application/json. If you forget to set it or rely on a default of text/plain or text/html, then the responseJson argument wouldn't give you a JSON object, but a plain vanilla string and you'd need to manually fiddle around with JSON.parse() afterwards, which is thus totally unnecessary if you set the content type right in first place.

返回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>.
        });
    });
});

with

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

返回列表<实体>为JSON

下面是一个例子,在<表>中显示List<Product>,其中Product类具有属性Long id, String名称和BigDecimal价格。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);
}

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>.
        });
    });
});

返回列表<实体>为XML

下面是一个示例,它与前面的示例有效地相同,但是使用XML而不是JSON。当使用JSP作为XML输出生成器时,您会发现编写表和其他内容不那么繁琐。JSTL在这方面更有帮助,因为您实际上可以使用它来迭代结果并执行服务器端数据格式化。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);
}

JSP代码(注意:如果您将<表>放在< 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>

JavaScript代码:

$(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".
    });
});

现在您可能已经意识到,在使用Ajax更新HTML文档的特定目的方面,XML为什么比JSON强大得多。JSON很有趣,但毕竟通常只对所谓的“公共web服务”有用。像JSF这样的MVC框架在它们的ajax魔法的掩护下使用XML。

对现有形式进行ajax化

您可以使用jQuery $.serialize()轻松地ajax现有的POST表单,而无需收集和传递单个表单输入参数。假设一个现有的表单在没有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.
});

你可以在servlet中区分普通请求和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示例差不多,但它有额外的透明支持,支持文件上传所需的多部分/ Form -data表单。

手动发送请求参数到servlet

如果你根本没有表单,但只是想与servlet“在后台”交互,因此你想要POST一些数据,那么你可以使用jQuery $.param()轻松地将JSON对象转换为url编码的查询字符串。

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

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

可以重用上面所示的doPost()方法。请注意,上述语法也适用于jQuery中的$.get()和servlet中的doGet()。

手动发送JSON对象到servlet

然而,如果你打算将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头自动检测到它。

然后,为了在servlet中处理JSON对象,它不是作为单个请求参数发送的,而是以上述方式作为一个完整的JSON字符串发送的,您只需要使用JSON工具手动解析请求体,而不是通常的方式使用getParameter()。也就是说,servlet不支持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()更笨拙。通常,只有当目标服务是一个JAX-RS (RESTful)服务时,你才需要使用JSON.stringify(),因为某种原因,这个服务只能使用JSON字符串,而不能使用常规的请求参数。

从servlet发送重定向

Important to realize and understand is that any sendRedirect() and forward() call by the servlet on an ajax request would only forward or redirect the Ajax request itself and not the main document/window where the Ajax request originated. JavaScript/jQuery would in such case only retrieve the redirected/forwarded response as responseText variable in the callback function. If it represents a whole HTML page and not an Ajax-specific XML or JSON response, then all you could do is to replace the current document with it.

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;
    }

    // ...
}

参见:

调用Servlet并从JavaScript调用Java代码以及参数 使用JavaScript访问Java / Servlet / JSP / JSTL / EL变量 如何在基于ajax的网站和基本HTML网站之间轻松切换? 如何使用JSP/Servlet和Ajax将文件上传到服务器?

Ajax(也称为Ajax)是异步JavaScript和XML的首字母缩写,是一组用于客户端创建异步web应用程序的相互关联的web开发技术。使用Ajax, web应用程序可以异步地向服务器发送数据,并从服务器检索数据。

下面是示例代码:

一个JSP页面JavaScript函数,通过两个变量firstName和lastName向servlet提交数据:

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读取以XML格式发送回JSP的数据(也可以使用文本)。您只需要将响应内容更改为文本并在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>");
}

使用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'
    });}
}

在Servlet

request.getParameter("input")