JSF Managed Bean автоматически создает? - PullRequest
16 голосов
/ 12 января 2010

Можно ли автоматически создать управляемый компонент JSF?

Например, у меня есть несколько сессионных компонентов. Иногда возникает необходимость доступа к этим экземплярам в коде (а не только в JSF), это делается с помощью:

PageBean pageBean = (PageBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("pages");

Однако, если ни одна страница не была посещена, какие обращения к «# {pages}» это разрешает к нулю ... Есть ли способ заставить JSF создать компонент, когда область действия «начинается»? Таким образом, в этом случае, в идеале, когда пользовательский сеанс начинается, bean-объект «pages» будет создан в сеансе немедленно?

Ответы [ 4 ]

27 голосов
/ 12 января 2010

Используйте взамен Application#evaluateExpressionGet(). Он создаст бин, когда он еще не сделан.

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);

Где "bean" - это имя управляемого компонента, а Bean.class - соответствующий класс вспомогательного компонента.

Вы можете при необходимости обернуть это вспомогательным методом, так что приведение не нужно (ребята из JSF не воспользовались обобщениями и параметром Class в evaluateExpressionGet):

public static <T> T findBean(String managedBeanName, Class<T> beanClass) {
    FacesContext context = FacesContext.getCurrentInstance();
    return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass));
}

, который можно использовать как:

Bean bean = findBean("bean", Bean.class);

Или без типа, но с @SuppressWarnings:

@SuppressWarnings("unchecked")
public static <T> T findBean(String managedBeanName) {
    FacesContext context = FacesContext.getCurrentInstance();
    return (T) context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", Object.class);
}

, который можно использовать как:

Bean bean = findBean("bean");

Обновление : вышесказанное относится к JSF 1.2. Вот способ для JSF 1.1 или старше, использующий в настоящее время устарел Application#createValueBinding():

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().createValueBinding("#{bean}").getValue(context);
3 голосов
/ 07 мая 2011

А как насчет этого решения:

public static Object getBean(String beanName)
{          
    Object returnObject = FacesContext.getCurrentInstance().getELContext().getELResolver().getValue(FacesContext.getCurrentInstance().getELContext(), null, beanName);  
    if (returnObject == null)  
        System.out.println("Bean with name " + beanName + " was not found. Check the faces-config.xml file if the given bean name is ok.");          
    return returnObject;
}

Таким образом, вы можете даже избежать параметра Bean.class.

0 голосов
/ 07 декабря 2010

Вопрос: будет ли

FacesContext context = FacesContext.getCurrentInstance ();

Бобовая фасоль = (Бобовая) context.getApplication (). evaluateExpressionGet (контекст, "# {bean}", Bean.class);

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

0 голосов
/ 12 января 2010

Один из механизмов заключается в том, что бин вводится в боб, на который вы хотите сослаться, в другой боб, как показано здесь expensiveBean:

  <managed-bean>
    <managed-bean-name>requestBean</managed-bean-name>
    <managed-bean-class>lifetime.RequestBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
      <property-name>cachedAsset</property-name>
      <property-class>lifetime.ExpensiveBean</property-class>
      <value>#{expensiveBean}</value>
    </managed-property>
  </managed-bean>

Это не очень "лениво", но это может быть удобно.

...