2013-01-17 54 views
1

我想在Spring中使用reverse ajax創建羣聊的演示。我正在使用Spring 3.2.0.RELEASE版本。使用Spring 3.2.0.RELEASE的DeferredResult反轉ajax。不在IE中工作

我正在使用DeferredResult在我的控制器中執行反向ajax。以下是我的控制器類的片段。

@Autowired 
private AsyncRepository asyncRepository; 

Map<Integer, List<DeferredResult<String>>> watchers = new ConcurrentHashMap<Integer, List<DeferredResult<String>>>(); 

@RequestMapping(value="/asyncRequest/getMessages/{id}", method=RequestMethod.GET) 
@ResponseBody 
public DeferredResult<String> getMessages(final @PathVariable("id") Integer id){ 
    final DeferredResult<String> deferredResult = new DeferredResult<String>(null, Collections.emptyList()); 

    if(watchers.containsKey(id)) { 
     watchers.get(id).add(deferredResult); 
    } else { 
     watchers.put(id, new ArrayList<DeferredResult<String>>()); 
     watchers.get(id).add(deferredResult); 
    } 

    deferredResult.onCompletion(new Runnable() { 
     @Override 
     public void run() { 
      watchers.get(id).remove(deferredResult); 
     } 
    }); 

    return deferredResult; 
} 

@RequestMapping(value="/asyncRequest/setMessages/{id}/{message}", method=RequestMethod.GET) 
@ResponseBody 
public String setMessage(@PathVariable("id") Integer id, @PathVariable("message") String message) { 
    asyncRepository.setMessage(id, message); 

    return ""; 
} 

@Scheduled(fixedRate=1000) 
public void processQueues() { 
    for (Map.Entry<Integer, Queue<AsyncDataBean>> entry : asyncRepository.getAsyncBeans().entrySet()) { 
     while(entry != null && entry.getValue() != null && !entry.getValue().isEmpty()) { 
      AsyncDataBean asyncDataBean = entry.getValue().poll(); 
      for (DeferredResult<String> deferredResult : watchers.get(asyncDataBean.getId())) { 
       deferredResult.setResult(asyncDataBean.getMessage()); 
      } 
     } 
    } 
} 

下面是存儲GroupID及其相關messageQueue映射的Repository類。它還具有獲取和設置相關組ID的消息的功能。

@Repository 
public class AsyncRepository { 

    private Map<Integer, Queue<AsyncDataBean>> asyncBeans = new ConcurrentHashMap<Integer, Queue<AsyncDataBean>>(); 

    public String getMessages(Integer id) { 
     StringBuilder stringBuilder = new StringBuilder(); 
     while (asyncBeans.get(id) != null && !asyncBeans.get(id).isEmpty()) { 
      stringBuilder.append(asyncBeans.get(id).poll().getMessage()).append("~"); 
     } 

     return stringBuilder.toString(); 
    } 

    public void setMessage(Integer id, String message) { 
     if(asyncBeans.containsKey(id)) { 
      asyncBeans.get(id).add(new AsyncDataBean(id, message)); 
     } else { 
      Queue<AsyncDataBean> messageQueue = new ConcurrentLinkedQueue<AsyncDataBean>(); 
      messageQueue.add(new AsyncDataBean(id, message)); 
      asyncBeans.put(id, messageQueue); 
     } 
    } 

    public Map<Integer, Queue<AsyncDataBean>> getAsyncBeans() { 
     return asyncBeans; 
    } 

    public void setAsyncBeans(Map<Integer, Queue<AsyncDataBean>> asyncBeans) { 
     this.asyncBeans = asyncBeans; 
    } 
} 

下面是我用來存儲每個消息與它的組ID的數據bean。

public class AsyncDataBean { 
    private Integer id; 
    private String message; 

    public AsyncDataBean() { 
    } 

    public AsyncDataBean(int id, String message) { 
     this.setId(id); 
     this.setMessage(message); 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getMessage() { 
     return message; 
    } 

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

然後進入羣聊的jsp頁面。看起來像下面。

<script type="text/javascript"> 
    var messagesWaiting = false; 
    function getMessages(){ 
     if(!messagesWaiting){ 
      $.ajax({ url: "${pageContext.servletContext.contextPath}/asyncRequest/getMessages/${id}", 
        dataType:"text", 
        success: function(data,textStatus,jqXHR) { 
         if(textStatus == 'success'){ 
          messagesWaiting = false; 
          var arr = data.split("~"); 
          for(var i=0; i<arr.length; i++) 
          { 
            try 
            { 
             if(arr[i] != '') { 
              $("#txtaMessages").val($("#txtaMessages").val() + "\n\n" + arr[i]); 
              document.getElementById("txtaMessages").scrollTop = document.getElementById("txtaMessages").scrollHeight; 
             } 
            } 
            catch(e){ 
            alert(e.message); 
            } 
          } 
         } 
        }, 
        complete: function(j) { 
        }, 
        error: function(xhr) { 
        } 
      }); 
      messagesWaiting = true; 
     } 
    } 
    setInterval(getMessages, 1000); 
    getMessages(); 

    function sendMessage() { 
     var xmlhttp1 = new XMLHttpRequest(); 
     xmlhttp1.open("GET", '${pageContext.servletContext.contextPath}/asyncRequest/setMessages/${id}/' + $("#txtMessage").val(), true); 
     xmlhttp1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
     xmlhttp1.send(); 
     $("#txtMessage").val(""); 
     $("#txtMessage").focus(); 
    } 
</script> 

</head> 
<body> 
    <h1>Hello World!</h1> 
    <table> 
     <tr> 
      <td>Messages :: </td> 
      <td> 
       <textarea cols="100" rows="10" id="txtaMessages"></textarea> 
      </td> 
     </tr> 
     <tr> 
      <td>Send Message :: </td> 
      <td><input type="text" id="txtMessage"/></td> 
     </tr> 
     <tr> 
      <td><input type="button" value="Send" onclick="sendMessage();"/></td> 
     </tr> 
    </table> 
</body> 
</html> 

這就是我編碼到現在爲止得到這個工作。並且FF和Chrome中的所有功能都可以使用。但在IE瀏覽器中,它不能按預期工作。該請求永遠不會在服務器上得到保留,並且每次都會按照JavaScript代碼中的配置每秒執行一次。它總是返回與以前相同的結果。我曾嘗試使用其他幾種方法爲IE發送ajax請求,但它不起作用。任何人都可以爲我工作嗎?

因爲在FF和Chrome中一切正常,我懷疑問題是用JavaScript代碼發送請求來獲取消息。

請幫幫我。

在此先感謝。

回答

1

這非常令人沮喪。

爲了讓這個東西在IE中正常工作我需要在我使用jQuery爲getMessages創建的ajax請求中設置cache:false屬性。否則,IE不會將請求保留在掛起狀態,並始終使用舊的應答文本返回。

它是IE的一個非常大的問題。我希望沒有人再次面對這個問題,或者儘早找到答案。

:)