Spring でリバース ajax を使用してグループ チャットのデモを作成しようとしています。Spring 3.2.0.RELEASE バージョンを使用しています。
DeferredResult を使用して、コントローラーでリバース ajax を実行しています。以下は、私の Controller クラスのスニペットです。
@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 コードに問題があると思われます。
私を助けてください。
前もって感謝します。