Понимание класса DeferredResult в Spring MVC в контексте github-приложения spring-mvc-chat
Я пытаюсь лучше понять, как работает следующее приложение Spring mvc 3.2:https://github.com/rstoyanchev/spring-mvc-chat
Мой вопрос оdeferredResult Spring MVC класс, Я заметил, что в данный момент столько же записей вchatRequests
Карта, так как есть пользователи, подключенные к приложению чата.
Скажи, что есть3 пользователя подключены в приложение чата. Вы увидите, что когдаПользователь № 3 отправляет сообщение (см. метод postMessage ниже), затемцикл for (в методе postMessage) повторяется три раза, Я могу'не понимаю, почему это так.
Я включаю пример кода ниже.
Код для контроллера:
@Controller
@RequestMapping("/mvc/chat")
public class ChatController {
private final ChatRepository chatRepository;
private final Map chatRequests = new ConcurrentHashMap();
@Autowired
public ChatController(ChatRepository chatRepository) {
this.chatRepository = chatRepository;
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public DeferredResult getMessages(@RequestParam int messageIndex) {
final DeferredResult deferredResult = new DeferredResult(null, Collections.emptyList());
this.chatRequests.put(deferredResult, messageIndex);
deferredResult.onCompletion(new Runnable() {
@Override
public void run() {
chatRequests.remove(deferredResult);
}
});
List messages = this.chatRepository.getMessages(messageIndex);
if (!messages.isEmpty()) {
deferredResult.setResult(messages);
}
return deferredResult;
}
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public void postMessage(@RequestParam String message) {
this.chatRepository.addMessage(message);
// Update all chat requests as part of the POST request
// See Redis branch for a more sophisticated, non-blocking approach
for (Entry entry : this.chatRequests.entrySet()) {
List messages = this.chatRepository.getMessages(entry.getValue());
entry.getKey().setResult(messages);
}
}
}
Javascript код:
$(document).ready(function() {
function ChatViewModel() {
var that = this;
that.userName = ko.observable('');
that.chatContent = ko.observable('');
that.message = ko.observable('');
that.messageIndex = ko.observable(0);
that.activePollingXhr = ko.observable(null);
var keepPolling = false;
that.joinChat = function() {
if (that.userName().trim() != '') {
keepPolling = true;
pollForMessages();
}
}
function pollForMessages() {
if (!keepPolling) {
return;
}
var form = $("#joinChatForm");
that.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
}));
$('#message').focus();
}
that.postMessage = function() {
if (that.message().trim() != '') {
var form = $("#postMessageForm");
$.ajax({url: form.attr("action"), type: "POST",
data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
error: function(xhr) {
console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
}
});
that.message('');
}
}
that.leaveChat = function() {
that.activePollingXhr(null);
resetUI();
this.userName('');
}
function resetUI() {
keepPolling = false;
that.activePollingXhr(null);
that.message('');
that.messageIndex(0);
that.chatContent('');
}
}
//Activate knockout.js
ko.applyBindings(new ChatViewModel());
});
и HTML-страница:
Chat
Chat
<p>
User:
Join Chat
</p>
<p>
You're chatting as <strong data-bind="text: userName"></strong>
Leave Chat
</p>
<p>
Post
</p>