Вещание подгруппе подписчиков в атмосфере
Что я пытаюсь сделать: иметь возможность подписки пользователей на несколько различных "комнат чата" и использовать обратную AJAX / комету для отправки сообщений из комнаты чата всем, кто вошел в эту комнату. (немного сложнее, но это аналогичный вариант использования).
Что я делаю: использование Grails с JMS и Atmosphere. Когда сообщение отправляется, я использую JMS для отправки объекта сообщения, полученного службой Grails, который затем транслируется по URL-адресу атмосферы (т.е. атмосфера / сообщения).
Очевидно, что JMS там немного избыточен, но я, хотя и мог бы использовать его, чтобы помочь мне отфильтровать, кто должен получить сообщение, хотя на самом деле это не выглядит так, как оно будет работать (учитывая, что подписчик - это в основном одно-сервисная служба...).
В любом случае, мне нужно уметь отправлять только сообщения нужной группе людей, слушающих атмосферу / сообщения. URL-адрес типа RESTful здесь будет идеальным (т. Е. Атмосфера /messages/*, где * - идентификатор комнаты), однако я понятия не имею, как это сделать с Atmosphere.
Любые идеи / предложения о том, как я могу достичь того, что я хочу? Здесь нет ничего конкретного, так что не стесняйтесь предлагать почти все. Я даже думал (основываясь на ответе на другой вопрос), например, могу ли я сделать что-то вроде отправки сообщений на сервер Node.js и обработать обратную часть AJAX / кометы.
3 ответа
Если я правильно понимаю ваши требования, должно работать следующее (jax-rs + scala code):
1) Каждый, кто хочет получать сообщения из чата, регистрируется на это:
@GET
@Path(choose/a/path)
def register(@QueryParam("chatroomId") chatroomId: Broadcaster) {
// alternatively, the Suspend annotation can be used
new SuspendResponse.SuspendResponseBuilder[String]()
.resumeOnBroadcast(false).broadcaster(chatroomId).scope(SCOPE.REQUEST)
.period(suspendTimeout, TimeUnit.MINUTES)
.addListener(new AtmosphereEventsLogger()).build
}
2) Чтобы отправить сообщение всем зарегистрированным пользователям, вызовите следующий метод:
@POST
@Broadcast
@Path(choose/a/path/{chatroomId})
def broadcast(@PathParam("chatroomId") id: String) {
// first find your broadcaster with the BroadcasterFactory
BroadcasterFactory.getDefault().lookupAll() // or maybe there is a find by id?
broadcaster = ...
broadcaster.broadcast(<your message>)
}
Я также рекомендую прочитать документ с описанием атмосферы, посмотреть список рассылки и блог Жанфрансуа Аркана.
Надеюсь, это поможет.
Существует неверное понимание концепции кометы. Это просто еще одна реализация публикации / подписки. Если у вас есть несколько чатов, то вам нужно иметь несколько "тем", то есть несколько каналов, на которые пользователь может зарегистрироваться. Например:
broadcaster['/atmosphere/chatRoom1'].broadcast('Hello world!')
broadcaster['/atmosphere/chatRoom2'].broadcast('Hello world!')
Поэтому я бы рекомендовал вам создать несколько каналов и не фильтровать вручную группу пользователей, которые должны извлекать сообщения (что определенно не так, как это должно быть сделано). Вам не нужно ничего создавать на стороне сервера, так как пользователь просто зарегистрируется на определенном канале и получит сообщения, которые кто-либо помещает в него.
Я бы порекомендовал вам создать AtmosphereHandler для одного URL-адреса, такого как / атмосфера / чат, а затем использовать AtmosphereResource и связать с ним BroadcastFilter, скажем, с именем ChatRoomBroadcastFilter.
Всякий раз, когда пользователь подписывается на новую комнату чата, на сервер (от клиента) отправляется сообщение, информирующее сервер о подписке. После подписки ведите список пользователей <> привязок чата где-нибудь на сервере.
Всякий раз, когда сообщение транслируется, передайте его с идентификатором чата. В ChatRoomBroadcastFilter (вам, вероятно, нужно сделать это PerRequestBroacastFilter) распространять сообщение для пользователя, только если пользователь подписался на комнату чата. Я не уверен, очищает ли это это. Если вам нужен пример кода, пожалуйста, укажите в комментариях. Я поставлю это, но это требует некоторого времени, так что не помещаю это прямо сейчас;).