Play Framework 2.x: как обновить отображаемый вид со стороны сервера?

У меня проблемы с игрой! фреймворк. Фреймворк новый для меня, и моя первая и единственная практика с ним — это руководство здесь.

У меня есть представление, в котором перечислены некоторые данные. Контроллер, у которого есть один метод для отображения представления и другой метод, который может получать некоторые данные с помощью JSON. Теперь я хотел бы обновить представление при получении новых данных (JSON).

Я обнаружил, что для реализации этого я могу использовать либо comet socket, websocket, либо события, отправленные сервером. (Постоянный опрос AJAX мне не подходит.)

Как лучше всего это сделать?

Я пытался решить эту проблему с помощью веб-сокетов, но это не работает так, как я хочу...

Вот мой код:

public class MyController extends Controller{   
    public static Result showMyView() {
        return ok(views.html.showMyView.render(Data.all()));
    }

    @BodyParser.Of(play.mvc.BodyParser.Json.class)
    public static Result jsonReceiver() {
        JsonNode json = request().body().asJson();
        String rcvData = json.findPath("someData").textValue();

        if(rcvData != null) {
            /*FLAG*/
            //SEND SOME DATA OVER THE WEBSOCKET FROM HERE?! ..To update the view
            //something like: out.write("Now from here!");
            return ok();
        } else {
            return badRequest();
        }
    }

    public static WebSocket<String> websocket() {
        return new WebSocket<String>() {

            public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
                out.write("Hello!");
            }
        };
    }
}

Есть ли способ отправлять сообщения или другие данные через сокет с позиции /*FLAG*/ в приведенном выше коде?

Мой взгляд выглядит так:

@(dataContent: List[Data])
@main(title = "MyViews Observation Page") {
    @*
    SOME HTML CODE ...
    *@

<script type="text/javascript">
    var socket = new WebSocket("ws://" + location.host + "/path/to/my/websocket")

    socket.onmessage = function(event) {
        alert("Received: " + event.data); // only for testing... will be replaced later
    }
</script>
}

Может ли кто-нибудь помочь мне здесь? Я не знаю, как обновить представление при получении новых данных.

Я был бы очень признателен, если бы вы могли показать это на основе моего примера кода выше. если проще сделать по другому(comet или server-sent events), тоже очень благодарен за примеры.

В моем предыдущем исследовании я нашел несколько примеров для комет и событий, отправленных сервером, но они были только в scala, и я их не понял.

Я использую play framework 2.2.2 с java.


person Manalishi    schedule 03.04.2014    source источник
comment
Я работал с вебсокетами, это сложно по некоторым причинам (совместимость с прокси, неожиданное закрытие коннекта). Вы все еще можете сделать это, если у вас есть совместимый прокси-сервер и если вы пингуете соединение каждые x секунд, чтобы восстановиться в случае сбоя.   -  person Julien D    schedule 03.04.2014
comment
Ok. Я никогда раньше не работал с веб-сокетами. Можете ли вы порекомендовать подход к решению моей проблемы? Я очень гибкий в способе сделать это. В конце мне в основном нужна «страница наблюдения», которая обновляется после получения данных JSON.   -  person Manalishi    schedule 03.04.2014


Ответы (1)


Каждый клиент будет генерировать WebSocket.Out на вашем сервере.

Сохраните их в списке, а затем вызовите WebSocket.Out.write(objectNode)

public class MyController extends Controller{   
    //1. you store your client channels here
    private static ArrayList<WebSocket.Out> channels=new ArrayList<>();

    public static Result showMyView() {
        return ok(views.html.showMyView.render(Data.all()));
    }

    @BodyParser.Of(play.mvc.BodyParser.Json.class)
    public static Result jsonReceiver() {
        JsonNode json = request().body().asJson();
        String rcvData = json.findPath("someData").textValue();

        if(rcvData != null) {
           //3. you can write in your channels :)
           for(WebSocket.Out channel : channels){
               channel.write("blah");
           }

            return ok();
        } else {
             return badRequest();
        }
    }

    public static WebSocket<String> websocket() {
        return new WebSocket<String>() {

            public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
                  //2. each time a client connects, you save a reference to its channel
                  channels.add(out);
            }
        };
    }

}

person Julien D    schedule 03.04.2014
comment
Спасибо, это помогло мне. В своем посте выше... вы написали, что соединение может неожиданно закрыться. Я думал, что веб-сокеты - прекрасное решение такой проблемы. Не так ли? Было бы лучше использовать кометные или серверные события? - person Manalishi; 03.04.2014