问答中心分类: AJAX我应该如何使用servlet和Ajax?
0
匿名用户 提问 3月 前

每当我在servlet中打印一些内容并通过webbrowser调用它时,它都会返回一个包含该文本的新页面。有没有一种方法可以使用Ajax打印当前页面中的文本?
我对web应用程序和servlet非常陌生。

7 Answers
0
BalusC 回答 3月 前

实际上,关键字是“Ajax”:异步JavaScript和XML。然而,过去几年异步JavaScript和JSON。基本上,您可以让JavaScript执行异步HTTP请求,并根据响应数据更新HTML DOM树。
因为它很漂亮让它发挥作用的繁琐工作在所有浏览器中(尤其是Internet Explorer与其他浏览器相比),都有大量JavaScript库,这些库在单个功能中简化了这一点,并尽可能多地覆盖了特定于浏览器的漏洞/怪癖,例如jQuery,则,原型,则,Mootools公司。由于jQuery现在最流行,我将在下面的示例中使用它。
启动示例返回String作为纯文本
创建/some.jsp如下所示(注意:此答案中的代码片段并不期望JSP文件被放置在子文件夹中,如果这样做,请相应地更改servlet URL"someservlet""${pageContext.request.contextPath}/someservlet";为了简洁起见,代码片段中省略了它):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>SO question 4112686</title>
        <script src="https://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.
}

将此servlet映射到的URL模式/someservlet/someservlet/*如下所示(显然,URL模式可以自由选择,但您需要更改someservlet相应地,JS代码示例中的URL覆盖所有位置):

package com.example;

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

或者,当你不在Servlet3.0兼容容器(公猫7.玻璃鱼3.JBoss如6等或更新版本),然后将其映射到web.xml老式的方式(另请参见我们的Servlets 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响应更新。
正在返回List<String>作为JSON
具有JSON您甚至可以进一步获得一些步骤,而不是将明文作为响应格式。它允许更多的动态。首先,您希望有一个在Java对象和JSON字符串之间转换的工具。它们也有很多(参见此页以获取概述)。我个人最喜欢的是谷歌Gson。下载并将其JAR文件放入/WEB-INF/libweb应用程序的文件夹。
下面是一个示例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>.
        });
    });
});

请注意,jQuery会自动将响应解析为JSON,并直接向您提供一个JSON对象(responseJson)将响应内容类型设置为application/json。如果您忘记设置或依赖默认值text/plaintext/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>在a中<table>其中Product类具有以下属性Long id,则,String nameBigDecimal price。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>.
        });
    });
});

正在返回List<Entity>作为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代码(注意:如果您将<table>在a中<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服务”有用。MVC框架,如JSF公司在ajax魔术的掩护下使用XML。
对现有形式的抽象化
您可以使用jQuery$.serialize()轻松地ajaxify现有的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示例相比,它做得更少或更多,但它对multipart/form-data文件上载所需的表单。
手动将请求参数发送到servlet
如果您根本没有表单,只是想“在后台”与servlet交互,从而发布一些数据,那么可以使用jQuery$.param()将JSON对象轻松转换为URL编码的查询字符串。

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

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

同样的doPost()如上所示的方法可以重用。请注意,上述语法也适用于$.get()在jQuery和中doGet()在servlet中。
手动将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表示request身体这个dataType表示的(预期)类型回答正文,这通常是不必要的,因为jQuery已经根据响应自动检测它了Content-Type标题。
然后,为了处理servlet中的JSON对象,该对象不是作为单独的请求参数发送的,而是作为一个完整的JSON字符串,您只需要使用JSON工具手动解析请求体,而不是使用getParameter()通常的方式。也就是说,servlet不支持application/json格式化的请求,但仅限于application/x-www-form-urlencodedmultipart/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字符串,而不能使用常规请求参数。
从servlet发送重定向
重要的是要认识和理解sendRedirect()forward()servlet对ajax请求的调用只会转发或重定向Ajax请求本身而不是Ajax请求发起的主文档/窗口。在这种情况下,JavaScript/jQuery只能检索重定向/转发的响应responseText回调函数中的变量。如果它表示整个HTML页面,而不是特定于Ajax的XML或JSON响应,那么您所能做的就是用它替换当前文档。

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

请注意,这不会像最终用户在浏览器地址栏中看到的那样更改URL。因此,书签功能存在问题。因此,最好只返回一条“指令”,让JavaScript/jQuery执行重定向,而不是返回重定向页面的全部内容。E、 例如,通过返回布尔值或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;
    }

    // ...
}

另请参见:

shinzou 回复 3月 前

需要解析最后一个示例中的json。

BalusC 回复 3月 前

@库哈库:没有。若你们从上到下阅读这篇文章,你们就会明白为什么。

Jonathan Laliberte 回复 3月 前

这个答案是我上个月左右的生命线,哈哈。从中我学到了很多。我喜欢XML示例。谢谢你把这些放在一起!如果你有时间的话,还有一个问题。是否有理由将xml文件夹放在WEB-INF中?

BalusC 回复 3月 前

@乔纳森·拉利伯特:所以用户无法下载。

629 回复 3月 前

@BalusC,您的XML示例很好,谢谢。但我得到“无法获取未定义或空引用的属性‘replace’”$("#somediv").html($(responseXml).find("data").html())这条线。它还表示“参数数量错误或属性分配无效”。我还可以看到,在调试XML时,XML中填充了数据。有什么想法吗?

BalusC 回复 3月 前

@629:也许你没有<div id="somediv">

629 回复 3月 前

@巴卢斯,当我在边缘打开页面时,它起作用了。关于如何使其也适用于IE11,有什么想法吗?

0
Stephen C 回答 3月 前

更新用户浏览器中当前显示的页面(无需重新加载)的正确方法是让浏览器中执行的一些代码更新页面的DOM。
该代码通常是嵌入HTML页面或从HTML页面链接的JavaScript,因此建议使用Ajax。(事实上,如果我们假设更新的文本通过HTTP请求来自服务器,这就是经典的Ajax。)
也可以使用一些浏览器插件或附加组件来实现这类功能,尽管插件可能很难进入浏览器的数据结构来更新DOM。(本机代码插件通常写入嵌入页面中的某些图形框架。)

0
Mitul Maheshwari 回答 3月 前

我将向您展示一个servlet的完整示例,以及如何进行Ajax调用。
这里,我们将创建一个使用servlet创建登录表单的简单示例。
文件指数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 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);
        }
    }
}
0
SUBZ 回答 3月 前
$.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);
    }
});
Peter Mortensen 回复 3月 前

应该有一个解释。E、 g.想法/要点是什么?请回复编辑(更改)您的答案,不在评论中(没有“编辑:”、“更新:”,或类似内容-答案应该看起来像是今天写的)。

0
user3468976 回答 3月 前

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