2012-05-14 8 views
3

То, что я пытаюсь выполнить, не слишком сложное, но у меня проблемы, поскольку я не очень разбираюсь в AJAX.Вызов асинхронного сервлета от AJAX

Когда он будет реализован, у меня будет JSP, у которого есть кнопка, которая вызывает асинхронный сервлет. Сервлет выполнит долговременную задачу и предоставит динамическую обратную связь пользователю, добавив строки в таблицу, когда части задачи будут завершены.

Прежде чем я попытаюсь написать окончательную версию, я делаю доказательство концепции, чтобы понять, как это будет работать. Однако я сталкиваюсь с проблемой. Когда я использую вызов AJAX при нажатии кнопки, функция работает так, как ожидалось, когда вызов выполняется для обычного синхронного сервлета. Однако, как только я делаю сервлет асинхронным, обновления не отображаются.

Может ли кто-нибудь дать представление о том, что происходит не так?

My 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, который возникает, когда я нажимаю кнопку, принимает только ответ из основного потока сервлета. Возможно, мне нужно вызвать функцию JavaScript из асинхронных вызовов write()? Я просто не знаю, как это сделать или если это будет правильный метод исполнения.

ответ

0

OK!

Итак, я понял. Это не совсем так, как мне хотелось бы, но это работает. И это просто доказательство концепции реализации того, над чем я работаю. Если кто-то может обеспечить более глубокое понимание, я бы хотел реализовать это, используя серверный push вместо опроса.

Мысли?

My 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); Если сервер не поддерживает async, он должен был исключить исключение. – dragon66

+0

Когда я запускаюсь из NetBeans локально, есть проблемы с фильтрами, которые использует NetBeans. Я должен установить этот флаг, чтобы он работал. Однако при развертывании он работает без этого флага. – Zach

Смежные вопросы