Как обрабатывать RPC в клиент-серверной игре PlayN?

Я хотел бы использовать PlayN для создания карточной игры клиент/сервер, например. Сердца. Хотя я в основном сосредоточен на выводе HTML5, в идеале я хотел бы быть независимым от платформы вывода на случай, если в будущем я решу сделать клиент для Android. Как мне подойти к механизму RPC?

Вот такие варианты я придумал:

  1. Используйте JSON для RPC с методами get()/post() — напишите сервлет, который принимает/возвращает JSON, и используйте его во всех версиях клиентского кода. Это кажется выполнимым, но меня беспокоит многословие JSON. Как только я заставлю Hearts работать, я хотел бы перейти к более сложным играм, и я беспокоюсь, что JSON приведет к тому, что между клиентом и сервером будет передаваться много сообщений гораздо большего размера, чем необходимо. На самом деле я не знаю, как работать с JSON в Java, но предполагаю, что это выполнимо. Соответствуют ли мои предположения? Насколько хорошо Java работает с JSON?
  2. Продолжайте использовать GWT-RPC. Я могу сделать это, взяв асинхронный интерфейс службы в моем основном (независимом от платформы) конструкторе, а в моем HTML main() я передаю асинхронный интерфейс GWT, сгенерированный GWT.create(MyService.class) (или, по крайней мере, его оболочку). Я понятия не имею, насколько хорошо это будет работать для версий, отличных от HTML. Могу ли я напрямую использовать GWT-RPC из кода Java на стороне клиента?
  3. Используйте другую форму RPC. Какие-либо предложения?

person Mark Schmit    schedule 28.01.2012    source источник
comment
Не полный ответ, но немного: Java хорошо работает с Json, но все хорошие библиотеки Json не работают под PlayN. Я только что опубликовал вопрос сегодня, потому что мы создаем наш сервер как REST-приложение без сохранения состояния, используя Джерси и некоторые другие вещи из стека EE. stackoverflow.com/questions/9045455/ Это позволяет нам совместно использовать DTO и иметь безопасные обратные вызовы и приведения. Использование вашего метода GWT может нарушить сборку Java, и тогда вы можете просто придерживаться GWT и использовать некоторую структуру холста для Это.   -  person iuiz    schedule 28.01.2012


Ответы (1)


Для GWT RPC на платформах Java и Android я в настоящее время экспериментирую с использованием gwt-syncproxy, чтобы предоставить Java-клиенту доступ к методам GWT RPC, и я использую Guice, Gin и RoboGuice на соответствующих целевых платформах для внедрения соответствующие экземпляры асинхронной службы для созданного объекта Game.

В core/pom.xml для проекта PlayN я включаю следующие координаты зависимостей для поддержки DI от Gin/Guice/RoboGuice по мере необходимости:

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
</dependency>

Затем я добавляю аннотации @Inject к любым полям внутри конкретной реализации игры:

public class TestGame implements Game {

    @Inject
    TestServiceAsync _testService;

    ...

}

В html/pom.xml я включаю координаты зависимостей для Gin:

<dependency>
  <groupId>com.google.gwt.inject</groupId>
  <artifactId>gin</artifactId>
  <version>1.5.0</version>
</dependency>

И я создаю классы TestGameGinjector и TestGameModule:

TestGameGinjector.java

@GinModules(TestGameModule.class)
public interface TestGameGinjector extends Ginjector {
    TestGame getGame();
}

TestGameModule.java

public class TestGameModule extends AbstractGinModule {
    @Override
    protected void configure() {
    }
}

Поскольку на данный момент я внедряю только интерфейс TestServiceAsync, мне не нужно добавлять какую-либо реализацию в метод TestGameModule.configure(); Джин управляет созданием AsyncServices для меня через GWT.create().

Затем я добавил следующее в TestGame.gwt.xml.

<inherits name='com.google.gwt.inject.Inject'/>

И, наконец, я внес следующие изменения в TestGameHtml.java.

public class TestGameHtml extends HtmlGame {

    private final TestGameGinjector _injector = GWT.create(TestGameGinjector.class);

    @Override
    public void start() {
        HtmlPlatform platform = HtmlPlatform.register();
        platform.assetManager().setPathPrefix("test/");
        PlayN.run(_injector.getGame());
    }
}

И это в значительной степени охватывает платформу HTML5 для PlayN.

Для платформы Java я добавляю следующие координаты зависимостей в java/pom.xml:

<dependency>
  <groupId>com.gdevelop.gwt.syncrpc</groupId>
  <artifactId>gwt-syncproxy</artifactId>
  <version>0.4-SNAPSHOT</version>
</dependency>

<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>3.0-rc2</version>
</dependency>

Обратите внимание, что проект gwt-syncproxy в Google Code не содержит pom.xml. У меня есть mavenized версия gwt-syncproxy, разветвленная и доступная через git по адресу https://bitbucket.org/hatboyzero/gwt-syncproxy.git. Вы должны иметь возможность клонировать его, запустив mvn clean package install, чтобы загрузить его в локальный репозиторий Maven.

В любом случае, я создал TestGameModule.java для платформы Java следующим образом:

public class TestGameModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(TestServiceAsync.class).toProvider(TestServiceProvider.class);
    }

    public static class TestServiceProvider implements Provider<TestServiceAsync> {
        public TestServiceAsync get() {
            return (TestServiceAsync) SyncProxy.newProxyInstance(
                TestServiceAsync.class,
                Deployment.gwtWebPath(),  // URL to webapp -- http://127.0.0.1:8888/testgame
                "test"
            );
        }
    }
}

И я изменил TestGameJava.java следующим образом:

public class TestGameJava {

    public static void main(String[] args) {
        Injector _injector = Guice.createInjector(new TestGameModule());

        JavaPlatform platform = JavaPlatform.register();
        platform.assetManager().setPathPrefix("test/images");
        PlayN.run(_injector.getInstance(TestGame.class));
    }
}

Я проделал аналогичное упражнение с платформой Android и RoboGuice — не вдаваясь в подробности, соответствующие изменения/фрагменты следующие:

зависимости pom.xml

<dependency>
  <groupId>com.gdevelop.gwt.syncrpc</groupId>
  <artifactId>gwt-syncproxy</artifactId>
  <version>0.4-SNAPSHOT</version>
</dependency>

<dependency>
  <groupId>org.roboguice</groupId>
  <artifactId>roboguice</artifactId>
  <version>1.1.2</version>
</dependency>

<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>3.0-rc2</version>
  <classifier>no_aop</classifier>
</dependency>

TestGameApplication.java

public class TestGameApplication extends RoboApplication {
    @Override
    protected void addApplicationModules(List<Module> modules) {
        modules.add(new TestGameModule());
    }
}

TestGameModule.java

public class TestGameModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(TestServiceAsync.class).toProvider(TestServiceProvider.class);
    }

    public static class TestServiceProvider implements Provider<TestServiceAsync> {
        public TestServiceAsync get() {
            return (TestServiceAsync) SyncProxy.newProxyInstance(
                TestServiceAsync.class,
                Deployment.gwtWebPath(),  // URL to webapp -- http://127.0.0.1:8888/testgame
                "test"
            );
        }
    }
}

TestGameActivity.java

public class TestGameActivity extends GameActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    final Injector injector = ((RoboApplication) getApplication()).getInjector();
        injector.injectMembers(this);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void main(){
        platform().assetManager().setPathPrefix("test/images");
        final Injector injector = ((RoboApplication) getApplication()).getInjector();
        PlayN.run(injector.getInstance(TestGame.class));
    }
}

Это краткое изложение того, как я заставил Gin/Guice/RoboGuice + GWT работать в моем проекте, и я убедился, что он прекрасно работает как на платформах Java, так и на HTML.

В любом случае, есть подход GWT к обеспечению вызовов RPC для нескольких платформ PlayN :).

person hatboyzero    schedule 28.01.2012
comment
Я пошел дальше и немного обновил свой ответ, так как недавно мне удалось разобраться со многими перегибами в том, как это сделать... - person hatboyzero; 03.02.2012
comment
Похоже, я могу делать свое дело с GWT RPC и использовать этот подход, если/когда я хочу поддерживать режимы вывода, отличные от HTML. Спасибо за подробный ответ! - person Mark Schmit; 19.02.2012
comment
Не за что, рад быть полезным :) - person hatboyzero; 24.02.2012
comment
отличный ответ! Спасибо за публикацию! - person Chii; 10.06.2012
comment
есть ли случайно реализация для платформы iOS? - person Majid Laissi; 27.02.2013
comment
Где разместить интерфейсы TestService и TestServiceAsync? Это в html или в ядре? Мне кажется, что они должны быть в ядре, так как они общие для разных платформ, но com.google.gwt.user.client.rpc.RemoteService недоступно в ядре; только хтмл. - person Jon Newmuis; 18.09.2013