代码之家  ›  专栏  ›  技术社区  ›  Amir Rachum

如何使用servlet和ajax?

  •  317
  • Amir Rachum  · 技术社区  · 14 年前

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

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

    7 回复  |  直到 6 年前
        1
  •  538
  •   Community CDub    7 年前

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

    因为它很漂亮 tedious 为了使它能够跨所有浏览器工作(尤其是Internet Explorer与其他浏览器),有大量的javascript库可以在单个函数中简化这一过程,并尽可能多地覆盖引擎盖下特定于浏览器的错误/怪癖,例如 jQuery , Prototype , Mootools . 由于jquery最近最流行,我将在下面的示例中使用它。

    启动示例返回 String 纯文本格式

    创建 /some.jsp 如下所示(注意:代码不希望JSP文件被放置在子文件夹中,如果这样做,请相应地更改servlet 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.
    }
    

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

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

    或者,当您还没有使用与servlet 3.0兼容的容器(Tomcat 7、Glassfish 3、JBoss as 6等或更高版本)时,将其映射到 web.xml 传统方式(另见 our Servlets wiki page ):

    <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<String> 作为JSON

    JSON 您甚至可以进一步了解一些步骤,而不是将纯文本作为响应格式。它允许更多的动力。首先,您希望有一个在Java对象和JSON字符串之间转换的工具。它们也有很多(见 this page 概述)。我个人最喜欢的是 Google Gson . 下载并放入jar文件 /WEB-INF/lib Web应用程序的文件夹。

    下面是一个显示 列表<字符串> 作为 <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);
    }
    

    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 ,然后 响应 参数不会给您一个JSON对象,而是一个普通的字符串,您需要手动处理 JSON.parse() 然后,如果您首先正确设置内容类型,这是完全不必要的。

    返回 Map<String, String> 作为JSON

    下面是另一个显示 映射字符串,字符串 作为 <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 . 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>
    

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

    到目前为止,您可能已经认识到,为了使用Ajax更新HTML文档的特定目的,XML为什么比JSON强大得多。JSON很有趣,但毕竟通常只对所谓的“公共Web服务”有用。MVC框架 JSF 在其Ajax魔力的封面下使用XML。

    一种现有的形式

    您可以使用jquery $.serialize() 在不影响收集和传递单个表单输入参数的情况下,可以轻松地半开现有的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 Form plugin 与上面的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和 小狗() 在servlet中。

    手动将JSON对象发送到servlet

    但是,如果出于某种原因,您打算将JSON对象作为一个整体而不是作为单个请求参数发送,那么您需要使用 JSON.stringify() (不是jquery的一部分)并指示jquery将请求内容类型设置为 应用程序/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 . 这个 内容类型 表示的类型 请求 身体。这个 数据库类型 表示 响应 body,这通常是不必要的,因为jquery已经根据响应自动检测它。 Content-Type 标题。

    然后,为了处理servlet中的JSON对象,该对象不是作为单独的请求参数发送的,而是作为一个整体的JSON字符串,您只需要使用JSON工具而不是使用 getParameter() 通常的方法。也就是说,servlet不支持 应用程序/JSON 格式化请求,但仅限于 应用程序/X-WWW-FORM-URLENCODED 多部分/表单数据 格式化请求。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执行重定向,而不是返回重定向页面的全部内容。例如,通过返回布尔值或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;
        }
    
        // ...
    }
    

    另请参见:

        2
  •  14
  •   JoaoFilipeClementeMartins    11 年前

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

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

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

        3
  •  12
  •   Alexander Farber    8 年前

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

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

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

    LoginServerlet 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);
            } 
        }
    }
    
        4
  •  7
  •   Aniket Kulkarni    10 年前
    $.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);
     }
    });
    
        5
  •  7
  •   BenMorel Manish Pradhan    10 年前

    Ajax(又称Ajax)是异步JavaScript和XML的缩写,是一组相互关联的Web开发技术,用于在客户端创建异步Web应用程序。使用Ajax,Web应用程序可以异步地向服务器发送数据并从服务器检索数据。 下面是示例代码:

    JSP Page Java脚本函数,用两个变量FrestNew和LaSTNEDE向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>");
    }
    
        6
  •  5
  •   Peter Knego    14 年前

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

        7
  •  4
  •   Jordi Castilla    9 年前

    使用引导多重选择

    阿贾克斯

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