2012-05-14 155 views
3

我試圖完成的並不是太複雜,但由於我對AJAX不熟悉,所以遇到了一些麻煩。從AJAX調用異步Servlet

當它被實現時,我將擁有一個具有調用異步Servlet的按鈕的JSP。該servlet將運行長時間運行的任務,並在部分任務完成時向表中添加行以向用戶提供動態反饋。

在我試圖編寫最終版本之前,我正在做一個概念驗證以瞭解這將如何工作。但是,我遇到了一個障礙。當我點擊一個按鈕時使用AJAX調用時,該函數在調用常規同步servlet時按預期工作。但是,只要我使servlet異步,不會顯示更新。

有人能夠提供一些有關錯誤的信息嗎?

我的JSP是這樣的:

<html> 
    <body> 
     <script type="text/javascript" charset="utf-8"> 
      $(document).ready(function() { 
       $('#mybutton').click(function() { 
        $.get('someservlet', function(responseJson) { 
         $.each(responseJson, function(index, item) { 
          $('<ul>').appendTo('#somediv'); 
          $('<li>').text(item.row1).appendTo('#somediv'); 
          $('<li>').text(item.row2).appendTo('#somediv'); 
          $('<li>').text(item.row3).appendTo('#somediv'); 
          $('<li>').text(item.row4).appendTo('#somediv'); 
         }); 
        }); 
       }); 
      }); 
     </script> 
     <p><button id="mybutton">Click to add things</button></p> 
     <div id="somediv"></div> 
    </body> 
</html> 

我的異步Servlet的doGet()方法是這樣的:

response.setContentType("application/json"); 
response.setCharacterEncoding("UTF-8"); 
final AsyncContext asyncContext = request.startAsync(); 
final PrintWriter writer = response.getWriter(); 
asyncContext.setTimeout(10000); 
asyncContext.start(new Runnable() { 

@Override 
public void run() { 
    for (int i = 0; i < 10; i++) { 
     List<Row> rows = new ArrayList<Row>(); 
     rows.add(new Row(i, i + 1, i + 2, i + 3)); 
     String json = new Gson().toJson(rows); 
     writer.write(json); 
     writer.flush(); 
     log.info("Wrote to JSON: " + i); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException ex) { 
     } 
    } 
    asyncContext.complete(); 
    } 
}); 

有什麼想法?看起來像我單擊按鈕時發生的AJAX調用只接受來自主servlet線程的響應。也許我需要調用異步調用write()的JavaScript函數?我只是不確定如何做到這一點,或者如果這將是正確的執行方法。

回答

0

好的!

所以,我想通了。這不像我喜歡它那樣花哨,但它有效。而且,這只是實施我正在工作的概念的證明。如果任何人都可以提供進一步的見解,我很樂意使用服務器推送而不是輪詢來實現這一點。

想法?

我的JSP是這樣的:

<html> 
    <head> 
     <script src="jquery-1.7.1.min.js" type="text/javascript" ></script> 
     <script> 
      $(document).ready(function() { 
       var prevDataLength; 
       var nextLine = 0; 
       var pollTimer; 
       $('#abutton').click(function() { 
        $(function(){ 
         var x = new $.ajaxSettings.xhr(); 
         x.open("POST", "someservlet"); 
         handleResponseCallback = function(){ 
          handleResponse(x); 
         }; 
         x.onreadystatechange = handleResponseCallback; 
         pollTimer = setInterval(handleResponseCallback, 100); 
         x.send(null); 
        }); 
       }); 

       function handleResponse(http) { 
        if (http.readyState != 4 && http.readyState != 3) 
         return; 
        if (http.readyState == 3 && http.status != 200) 
         return; 
        if (http.readyState == 4 && http.status != 200) { 
         clearInterval(pollTimer); 
        } 

        while (prevDataLength != http.responseText.length) { 
         if (http.readyState == 4 && prevDataLength == http.responseText.length) 
          break; 
         prevDataLength = http.responseText.length; 
         var response = http.responseText.substring(nextLine); 
         var lines = response.split('\n'); 
         nextLine = nextLine + response.lastIndexOf(']') + 1; 
         if (response[response.length-1] != ']') 
          lines.pop(); 
         for (var i = 0; i < lines.length; i++) { 
          var line = $.parseJSON(lines[i]); 
          addToTable(line); 
         } 
        } 

        if (http.readyState == 4 && prevDataLength == http.responseText.length) 
         clearInterval(pollTimer); 
       } 

       function addToTable(JSONitem) { 
        $.each(JSONitem, function(index, item) { 
         $('<tr>').appendTo('#sometablebody') 
         .append($('<td>').text(item.name)) 
         .append($('<td>').text(item.message)) 
         .append($('<td>').text(item.number)) 
         .append($('<td>').append($('<a>').attr('href', item.link).text('link'))); 
        }); 

       } 
      }); 
     </script> 
     <title>Async Test</title> 
    </head> 
    <body> 
     <p><button id="abutton">Click to add things</button></p> 
     <div id="somediv"> 
      <table border="1"> 
       <thead> 
        <tr> 
         <td>Name</td> 
         <td>Message</td> 
         <td>Number</td> 
         <td>Link</td> 
        </tr> 
       </thead> 
       <tbody id="sometablebody"></tbody> 
      </table> 
     </div> 
    </body> 
</html> 

我的異步Servlet的doGet()方法是這樣的:

request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); 

     final AsyncContext asyncContext = request.startAsync(); 
     final PrintWriter writer = response.getWriter(); 
     asyncContext.setTimeout(60000); 
     asyncContext.start(new Runnable() { 

      @Override 
      public void run() { 
       for (int i = 0; i < 10; i++) { 
        try { 
         List<Row> list = new ArrayList<Row>(); 
         list.add(new Row("First", "This is the first", String.valueOf(i), "link" + i)); 
         list.add(new Row("Second", "This is the second", String.valueOf(i), "link" + i)); 
         list.add(new Row("Third", "This is the third", String.valueOf(i), "link" + i)); 
         String json = new Gson().toJson(list); 

         asyncContext.getResponse().setContentType("application/json"); 
         asyncContext.getResponse().setCharacterEncoding("UTF-8"); 
         try { 
          asyncContext.getResponse().getWriter().write(json); 
          asyncContext.getResponse().getWriter().flush(); 
         } catch (IOException ex) { 
          System.out.println("fail"); 
         } 

         Thread.sleep(250); 
        } catch (InterruptedException ex) { 
         break; 
        } 
       } 
       asyncContext.complete(); 
      } 
     }); 

此外,對於這一切的工作,我實現了一個簡單的類:

public class Row { 

    private String name; 
    private String message; 
    private String number; 
    private String link; 

    public Row(String name, String message, String number, String link) { 
     setName(name); 
     setMessage(message); 
     setNumber(number); 
     setLink(link); 
    } 

    public String getLink() { 
     return link; 
    } 

    public void setLink(String link) { 
     this.link = link; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getNumber() { 
     return number; 
    } 

    public void setNumber(String number) { 
     this.number = number; 
    } 
} 
+1

那麼究竟是什麼問題呢?它是這樣一行:request.setAttribute(「org.apache.catalina.ASYNC_SUPPORTED」,true); 如果服務器不支持異步,它應該拋出異常。 – dragon66

+0

當我從本地運行NetBeans時,NetBeans使用的篩選器存在問題。我必須設置這個標誌來使它工作。雖然現場直播,但它沒有這個標誌。 – Zach