2014-03-29 10 views
2

Мне было предложено использовать #view.attributes карту для хранения view scoped data that I need to survive even after session destroys (с сохранением экономии на стороне клиента). Теперь, когда он работает идеально для моего требования, но я просто хочу убедиться, что это не плохая практика или плохая вещь.Плохо ли использовать JSF # view.attributes map вместо #viewScope для хранения данных приложения с областью просмотра?

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

ответ

3

В версиях JSF до 2.0 можно было хранить объекты только в режиме просмотра, используя UIViewRoot.set/getAttribute.

Однако в JSF 2.0 была введена отдельная область просмотра, которая может использоваться в EL через # {viewScope} или программно с использованием UIViewRoow.getViewMap(). Рекомендуется использовать область просмотра. Он реализуется с использованием Карты, хранящейся в UIViewRoot, и сериализуется так же, как и атрибуты вида в состоянии просмотра, так что она имеет ту же жизнь, что и атрибуты вида.

UPDATE

Согласно Леонардо Урибе из MyFaces команды:

В JSF 2.2 было решено просмотреть магазин области видимости фасолью всегда заседает (посмотрите на описание @ViewScoped аннотация в файле javadoc). Но вы можете просто вызвать facesContext.getViewRoot() и использовать карту атрибутов . Просто помните, что значения должны быть Serializable или реализовать StateHolder.

Так что портативный способ заключается в использовании карты атрибутов в UIViewRoot.

+0

но viewcope хранится в сеансе и, таким образом, он теряется, когда пользовательский сеанс уничтожается (что происходит очень быстро в моем приложении), поэтому как я могу заставить данные viewcope выжить даже после того, как сессия разрушится? Должен ли я разрабатывать пользовательскую реализацию для этих данных? есть идеи? –

+0

Вид сериализуется в сеансе, если ваш государственный метод сохранения - это сервер. Если этот метод является клиентом, состояние представления сериализуется, кодируется как base64 и отправляется в браузер, где он хранится в скрытом поле и отправляется обратно на сервер при выполнении следующего запроса. Таким образом, даже если сеанс истекает на сервере, клиент предоставит это состояние просмотра и будет успешно восстановлен. –

+0

Глядя на реализацию UIViewRoot, атрибуты компонента сохраняются вместе с картой вида, поэтому их жизненный цикл должен быть одинаковым. Какую реализацию и версию JSF вы используете? –

0

используя viewScope рекомендуется. избегать использования вида корня (компонент в целом) атрибуты по двум причинам:

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

  2. UIComponentBase.getAttributes возвращает конкретную реализацию Map: AttributesMap. эта реализация сначала проверяет, существует ли метод с тем же именем ключа карты в компоненте. а если нет, он проверяет внутреннюю карту. если он снова не найден, он проверяет карту ValueExpression. поэтому он не эффективен вообще и, в частном случае, может привести к бесконечной рекурсии.

взглянуть на AttributesMap.get, в примере:

public Object get(Object keyObj) { 
    String key = (String) keyObj; 
    Object result = null; 
    if (key == null) { 
     throw new NullPointerException(); 
    } 
    if (ATTRIBUTES_THAT_ARE_SET_KEY.equals(key)) { 
     result = component.getStateHelper().get(UIComponent.PropertyKeysPrivate.attributesThatAreSet); 
    } 
    Map<String,Object> attributes = (Map<String,Object>) 
      component.getStateHelper().get(PropertyKeys.attributes); 
    if (null == result) { 
     PropertyDescriptor pd = 
       getPropertyDescriptor(key); 
     if (pd != null) { 
      try { 
       Method readMethod = pd.getReadMethod(); 
       if (readMethod != null) { 
        result = (readMethod.invoke(component, 
          EMPTY_OBJECT_ARRAY)); 
       } else { 
        throw new IllegalArgumentException(key); 
       } 
      } catch (IllegalAccessException e) { 
       throw new FacesException(e); 
      } catch (InvocationTargetException e) { 
       throw new FacesException(e.getTargetException()); 
      } 
     } else if (attributes != null) { 
      if (attributes.containsKey(key)) { 
       result = attributes.get(key); 
      } 
     } 
    } 
    if (null == result) { 
     ValueExpression ve = component.getValueExpression(key); 
     if (ve != null) { 
      try { 
       result = ve.getValue(component.getFacesContext().getELContext()); 
      } catch (ELException e) { 
       throw new FacesException(e); 
      } 
     } 
    } 

    return result; 
} 

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

Вы можете рассказать нам пример реальной жизни?

Самый лучший пример, который приходит мне в голову, - это помнить активный индекс для tabView или аккордеона, но это значение может (и должно) сохраняться, если это важно.

однако каждая проблема имеет решение, первое, что я могу думать, это то, что вы можете реализовать настраиваемую область, которая сохраняет эти значения в области приложения, используя определенное значение cookie (client) в качестве ключа.

+0

, но viewcope хранится в сеансе и, таким образом, он теряется, когда пользовательский сеанс уничтожается (что происходит очень быстро в моем приложении), поэтому как я могу заставить данные viewcope выжить даже после того, как сессия разрушится? Должен ли я разрабатывать пользовательскую реализацию для этих данных? есть идеи? –

+0

см. Обновленный ответ –