Написание приложений на основе кометы Атмосфера проста. Представьте себе использование Scala вместо Java … это становится действительно простым! Не нужно больше учиться лифту ?
Не будучи специалистом по Scala, я решил переписать приложение на основе чата, которое я недавно использовал при добавлении поддержки кластеров в Atmosphere. Это действительно мое первое Scala-приложение, поэтому не прыгайте, глядя на код! Вместо этого, твит мне лучшую реализацию. Я не буду вдаваться в подробности того, как написать приложение Atmosphere, поэтому, если вы впервые узнаете об Atmosphere, начните здесь .
Для чата мне нужно было реализовать два метода: один будет вызываться при приостановке ответа ( метод потоковой передачи HTTP Comet ), а другой — для отправки сообщений чата на этот приостановленный ответ (другому участнику чата). Чтобы сделать это в Scala, я сделал:
package org.atmosphere.samples.scala.chat
import javax.ws.rs.{GET, POST, Path, Produces, WebApplicationException, Consumes}
import javax.ws.rs.core.MultivaluedMap
import org.atmosphere.core.annotation.{Broadcast, BroadcastFilter, Suspend}
import org.atmosphere.util.XSSHtmlFilter
@Path("/chat")
class Chat {
var JUNK : String = "<!-- Comet is a programming technique that enables web " +
"servers to send data to the client without having any need " +
"for the client to request it. -->\n"
@Suspend
@GET
@Produces(Array("text/html;charset=ISO-8859-1"))
def suspend() = {
var s = new StringBuilder()
for (i <- 0 to 10){
s.append(JUNK)
}
s.toString()
}
@Broadcast
@Consumes(Array("application/x-www-form-urlencoded"))
@POST
@Produces(Array("text/html"))
@BroadcastFilter(Array(classOf[XSSHtmlFilter],classOf[JsonpFilter]))
def publishMessage(form: MultivaluedMap[String, String]) = {
val action = form.getFirst("action")
val name = form.getFirst("name")
val result: String = if ("login".equals(action)) "System Message" + "__" + name + " has joined."
else if ("post".equals(action)) name + "__" + form.getFirst("message")
else throw new WebApplicationException(422)
result
}
}
Чтобы приостановить ответ, я аннотировал метод suspend () (строка 15) с помощью @Suspend. Возвращаемое значение метода suspend () будет записано, а затем ответ будет приостановлен, ожидая события сервера, например, сообщений из другого чата. Теперь, когда кто-то публикует сообщение, будет вызван метод publishMessage (). Поскольку метод аннотирован @Broadcast (строка 26), возвращаемое значение метода будет передано всем приостановленным ответам, например, все приостановленные соединения получат возможность написать сообщение. Но так как я не хочу, чтобы пользователи публиковали сценарии или любые виды атак, я также добавил аннотацию @BroadcastFilter , которая обязательно отфильтрует вредоносные символы. Так как мой клиент JavaScript ожидает ответа JSONp, я решил написать BroadcastFilterв Scala, которые преобразуют сообщение:
package org.atmosphere.samples.scala.chat
import org.atmosphere.cpr.BroadcastFilter
class JsonpFilter extends BroadcastFilter[String] {
val BEGIN_SCRIPT_TAG = "<script type='text/javascript'>\n"
val END_SCRIPT_TAG = "</script>\n"
def filter(m : String) = {
var name = m
var message = ""
if (m.indexOf("__") > 0) {
name = m.substring(0, m.indexOf("__"))
message = m.substring(m.indexOf("__") + 2)
}
val result: String = (BEGIN_SCRIPT_TAG + "window.parent.app.update({ name: \""
+ name + "\", message: \""
+ message + "\" });\n"
+ END_SCRIPT_TAG)
}
}
Затем я просто передаю имя этого класса в аннотацию @BroadcastFilter:
@BroadcastFilter(Array(classOf[XSSHtmlFilter],classOf[JsonpFilter]))
Что меня удивляет, так это то, что один фильтр написан на Java, а другой — на Scala !. Вот и все. С этими двумя классами работает демо-чат Atmosphere REST Chat. Чтобы усложнить приложение, я решил развернуть его в кластере. Этого легко достичь, пометив publishMesaage с помощью:
@Cluster(Array(classOf[JGroupsFilter]))
Теперь мое Scala-приложение поддерживает Comet-Cluster! Это было весело!
По любым вопросам или для загрузки приведенного выше примера перейдите на наш основной сайт и воспользуйтесь нашим форумом Nabble (подписка не требуется) или подпишитесь на нас в Twitter и разместите там свои вопросы!