关于java:如何使用Servlets和Ajax?

How to use Servlets and Ajax?

我对Web应用程序和servlet非常陌生,我有以下问题:

每当我在servlet中打印内容并由WebBrowser调用时,它会返回包含该文本的新页面。有没有一种方法可以使用Ajax打印当前页面中的文本?


实际上,关键字是"ajax":异步JavaScript和XML。然而,过去几年,它常常是异步JavaScript和JSON。基本上,您可以让JS执行一个异步HTTP请求,并根据响应数据更新HTMLDOM树。好的。

由于让它在所有浏览器(尤其是Internet Explorer和其他浏览器)上工作相当繁琐,因此有大量的javascript库可以在单个函数中简化这一过程,并尽可能多地覆盖引擎盖下特定于浏览器的错误/怪癖,如jquery、原型、moootools。由于jquery最近最流行,我将在下面的示例中使用它。好的。将String返回为纯文本的启动示例

创建一个/some.jsp如下(注意:代码不希望JSP文件被放在子文件夹中,如果这样做,请相应地更改servlet url):好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
    <head>
        SO question 4112686
        <script src="http://code.jquery.com/jquery-latest.min.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(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.
                });
            });
       
    </head>
    <body>
        <button id="somebutton">press here</button>
       
    </body>
</html>

使用doGet()方法创建servlet,如下所示:好的。

1
2
3
4
5
6
7
8
@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代码示例中更改someservleturl):好的。

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

或者,当您还没有使用与servlet 3.0兼容的容器(Tomcat 7、Glassfish 3、JBoss as 6等或更高版本)时,可以使用老式的方法(另请参见我们的servlet wiki页面)将其映射到web.xml中:好的。

1
2
3
4
5
6
7
8
<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并按按钮。您将看到,使用servlet响应更新了DIV的内容。好的。返回List作为json

使用JSON而不是纯文本作为响应格式,您甚至可以进一步了解一些步骤。它允许更多的动力。首先,您希望有一个在Java对象和JSON字符串之间转换的工具。它们也有很多(参见本页底部的概述)。我个人最喜欢的是谷歌GSON。下载并将其JAR文件放在webapplication的/WEB-INF/lib文件夹中。好的。

下面是一个示例,它将List显示为

  • 。servlet:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @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代码:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $(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>
    .
            });
        });
    });

    请注意,当您将响应内容类型设置为application/json时,jquery会自动将响应解析为json,并直接给您一个json对象(responseJson作为函数参数)。如果您忘记设置它或依赖于默认的text/plaintext/html,那么responseJson参数不会给您一个JSON对象,而是一个普通的字符串,之后您需要手动处理JSON.parse(),如果您首先正确设置内容类型,这是完全不必要的。好的。返回Map作为json

    下面是另一个将Map显示为的示例:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @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:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $(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>.
            });
        });
    });

    具有好的。

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

    返回List作为json

    这里有一个例子,它显示了List

    中,Product类具有Long id属性、String name属性和BigDecimal price属性。servlet:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @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代码:好的。

1
2
3
4
5
6
7
8
9
10
11
$(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返回为xml

这里有一个示例,它与前面的示例实际上是相同的,但是使用XML而不是JSON。当使用JSP作为XML输出生成器时,您会发现编写表和所有内容的代码就不那么繁琐了。JSTL通过这种方式更有用,因为您可以实际使用它来迭代结果并执行服务器端数据格式化。servlet:好的。

1
2
3
4
5
6
7
@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代码(注意:如果您将

放在中,它可以在非Ajax响应中的其他地方重用):好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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代码:好的。

1
2
3
4
5
$(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。好的。一种现有的形式

您可以使用jquery $.serialize()轻松地半开现有的post表单,而不必费心收集和传递单个表单输入参数。假设现有表单在没有javascript/jquery的情况下运行良好(因此当最终用户禁用了javascript时会有良好的降级):好的。

1
2
3
4
5
6
<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逐步增强它,如下所示:好的。

1
2
3
4
5
6
7
8
9
$(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请求,如下所示:好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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编码的查询字符串。好的。

1
2
3
4
5
6
7
8
9
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()完成,如下所示。好的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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) {
        // ...
    }
});

请注意,许多启动器将contentTypedataType混合在一起。contentType表示请求主体的类型。dataType表示响应主体的(预期的)类型,这通常是不必要的,因为jquery已经根据响应的Content-Type头自动检测它。好的。

然后,为了处理servlet中的JSON对象,它不是作为单独的请求参数发送的,而是作为一个整体的JSON字符串,您只需要使用JSON工具手动解析请求体,而不需要使用通常的方法getParameter()。即servlet不支持application/json格式的请求,只支持application/x-www-form-urlencodedmultipart/form-data格式的请求。GSON还支持将JSON字符串解析为JSON对象。好的。

1
2
3
4
5
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发送重定向

重要的是要认识和理解的是,servlet对Ajax请求的任何sendRedirect()forward()调用只会转发或重定向Ajax请求本身,而不是生成Ajax请求的主文档/窗口。在这种情况下,javascript/jquery只能在回调函数中以responseText变量的形式检索重定向/转发响应。如果它代表整个HTML页面,而不是Ajax特定的XML或JSON响应,那么您所能做的就是用它替换当前文档。好的。

1
2
3
document.open();
document.write(responseText);
document.close();

请注意,这不会改变最终用户在浏览器地址栏中看到的URL。因此,书签功能存在问题。因此,最好只返回一条"指令",让javascript/jquery执行重定向,而不是返回重定向页面的全部内容。例如,通过返回布尔值或URL。好的。

1
2
3
4
5
6
7
8
9
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);

好的。

1
2
3
4
5
6
7
8
function(responseJson) {
    if (responseJson.redirect) {
        window.location = responseJson.redirect;
        return;
    }

    // ...
}

参见:

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

好啊。


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

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

也可以使用一些浏览器插件或附加组件来实现这类功能,尽管插件访问浏览器的数据结构以更新DOM可能会很困难。(本机代码插件通常写入页面中嵌入的某些图形框架。)


我将向您展示一个完整的servlet示例,以及Ajax如何调用。

这里,我们将创建一个使用servlet创建登录表单的简单示例。

索引文件

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

这是Ajax示例

1
2
3
4
5
6
7
8
9
10
       $.ajax
        ({
            type:"POST",          
            data: 'LoginServlet='+name+'&name='+type+'&pass='+password,
            url: url,
        success:function(content)
        {
                $('#center').html(content);          
            }          
        });

LoginServerlet servlet代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    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(又称Ajax)是异步JavaScript和XML的缩写,是一组相互关联的Web开发技术,用于在客户端创建异步Web应用程序。使用Ajax,Web应用程序可以异步地向服务器发送数据并从服务器检索数据。下面是示例代码:

JSP Page Java脚本函数,用两个变量FrestNew和LaSTNEDE向servlet提交数据:

1
2
3
4
5
6
7
8
9
10
11
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函数上呈现数据。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * @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>");
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$.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."+
       "The  Details are as follws :  Name :");

    }else{
        $('#info').html("Sorry, there is some thing wrong with the data provided.");
    }
},
 error: function(e){
   alert('Error: ' + e);
 }
});

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


使用引导多重选择

阿贾克斯

1
2
3
4
5
6
7
8
9
10
11
12
13
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中

1
request.getParameter("input")