Перекрестные ссылки с использованием GWT с Gin - PullRequest
1 голос
/ 29 апреля 2011

У меня есть приложение GWT MVP, использующее Активности и Места.Это вдохновлено примером Мауро Бертапелле (в этой теме ), по-видимому, основанном на некоторых работах Томаса Бройера .

Вот проблема: у меня есть LoginActivity makeвызов RPC, который для успешного входа возвращает пользователя.Этот пользователь имеет роль (например, администратор, обычный пользователь, гость).Несколько представлений и действий, включая NavigatorView, зависят от этой роли в зависимости от того, что они показывают или делают.Как я могу получить этот экземпляр пользователя для других операций?

У меня нет ClientFactory;инъекция (Джин) используется для создания экземпляров Представлений в ActivityProviders, которые предоставляют мои Activity / Presenters, а ActivityProviders внедряются в мой ActivityMapper.Так что это может сводиться к вопросу Джина: как получить ссылку на пользователя, где это необходимо?Это похоже на этот SO вопрос о глобальных ссылках в MVP.

Считай меня новичком Джина, это моя первая попытка его использования.Я предполагаю, что есть «способ Джина», чтобы сделать это, но я не знаю Джина достаточно хорошо, чтобы знать лучший способ сделать это (если Джин вообще должен использоваться).

Огромное спасибо.

Редактировать 1: Несмотря на все мои усилия по поиску аналогичного вопроса, я только что нашел этот вопрос , который в значительной степениидентичен моему (является ли алгоритм SO для поиска "связанных" ссылок лучше, чем поиск?).Я думаю, что ответ Джина Дэвида находится на правильном пути.

Я не думаю, что решение EventBus возможно.Я следую рекомендациям Google , которые включают в себя создание экземпляров Activity при каждом изменении Места, поэтому одного события само по себе недостаточно.

Ответы [ 2 ]

3 голосов
/ 30 апреля 2011

То, что я использую на стороне сервера с Guice, и будет работать так же хорошо на стороне клиента, это привязка к пользовательскому провайдеру. В вашем случае, однако, вам придется сделать провайдера единичным и вставить в него значение из обратного вызова RPC (а не извлекать его из некоторого контекста). Сначала вам нужен конкретный поставщик:

@Singleton
public class CurrentUserProvider implements Provider<User> {
  private User currentUser;

  public User get() { return currentUser; }
  public void setCurrentValue(User currentUser) {
    this.currentUser = currentUser;
  }
}

Вы бы связали User с провайдером: bind(User.class).toProvider(CurrentUserProvider.class) В вашем обратном вызове RPC вы вводите CurrentUserProvider, чтобы вы могли setCurrentValue, но везде вы вводите Provider<User>, чтобы сохранить CurrentUserProvider в качестве детали реализации. Для очень короткоживущих объектов вы можете напрямую ввести значение User вместо Provider<User>.

Если вам нужно уведомить объекты об изменении значения, вы можете отправить событие на шину глобального события.

Кроме того, вы всегда можете использовать конкретный тип CurrentUserProvider (который больше не должен был бы реализовывать Provider) и, возможно, сделать его HasValueChangeHandlers, чтобы вы могли регистрировать слушателей на нем, а не на шине событий ( но вы должны были бы выполнить очистку после себя в своих действиях 'onStop и onCancel, чтобы избежать утечек памяти, тогда как об этом позаботятся автоматически, если вы зарегистрируете обработчики на шине событий в onStart).

(если вы спросите меня, я бы предпочел уйти с аутентификацией из приложения, когда это возможно)

1 голос
/ 30 апреля 2011

У меня были похожие требования к недавнему проекту.

Когда я получаю ответ от входа (или выхода из системы) RPC, я отправляю пользовательский AuthenticationEvent на EventBus.Все мероприятия, которые заинтересованы в этом, слушают это событие.AuthenticationEvent имеет ссылку на объект AppUser, который является нулевым, если пользователь только что вышел из системы.AppUser содержит все необходимые данные (привилегии, группы и т. Д.), Чтобы действия могли проверять их и воздействовать на них.

О глобальных ссылках: у вас может быть класс со статическими методами, предоставляющими необходимые данные.Этот класс внутренне содержит одиночные ссылки на необходимые экземпляры.В моем примере у меня есть статический метод AppUtils.getCurrentUser ().Внутренне он содержит ссылку на AppUser, а также прослушивает AuthenticationEvent для установки / сброса этого поля.

В качестве примечания: не полагайтесь на сторону клиента для обеспечения ограничений доступа - вы должны разделить свои сервлеты RPC на двагруппы: государственные и частные.Общедоступный может быть доступен любому (это в основном RPC входа / выхода из системы и некоторые другие общедоступные информационные RPC), в то время как частный RPC требует, чтобы пользователь прошел аутентификацию.Ограничения доступа могут быть установлены для каждого пути / сервлета: http://code.google.com/appengine/docs/java/config/webxml.html#Security_and_Authentication

Обновление:

  1. Как вы заметили, класс со статическими методами не рекомендуетсяв этой настройке, потому что он не подлежит замене, и это препятствует тестированию (в этом и заключается весь смысл использования GIN).

  2. Решение состоит в том, чтобы внедрить служебный класс, содержащий глобальные переменные (AppUtils), в действия, для которых нужны глобальные переменные.AppUtils должен быть объявлен синглтоном в конфигурации GIN, так как для всего приложения достаточно одного экземпляра.

  3. Использовать Provider или нет, это просто вопрос, если вы хотите отложить инициализацию зависимостей(AppUtil - это зависимость).Поскольку AppUtils является единым целым для всего приложения, нет смысла его лениво инициализировать.

  4. Иногда у вас возникает ситуация, когда на экране отображается несколько действий (в моем случае это были MenuBar и InfoBar).В этом случае, когда пользователь входит в систему, вам потребуется способ уведомить его об изменении.Используйте EventBus.

...