Отримайте керований боб JSF по імені в будь-якому класі, що стосується сервлетів


101

Я намагаюся написати власний сервлет (для AJAX / JSON), у якому я хотів би посилатися на своє @ManagedBeansім’я. Я сподіваюся зробити карту:

http://host/app/myBean/myProperty

до:

@ManagedBean(name="myBean")
public class MyBean {
    public String getMyProperty();
}

Чи можна завантажувати квасоля на ім’я зі звичайного сервлета? Чи є серверт або помічник JSF, який я міг би використати для цього?

Мені здається, псується Весна, в якій все це занадто очевидно.


Я не впевнений, чи можете ви використовувати ці нові анотації поза JSF / EL, але я б почав з перегляду специфікації JSR 299: jcp.org/en/jsr/detail?id=299
McDowell

Інші люди, які мають проблеми з подібними проблемами, також можуть перевірити bpcatalog.dev.java.net/ajax/jsf-ajax (пов’язаний з AJAX та запит на картографування / обробку, не отримуючи боби по імені)
Конрад Гарус

Відповіді:


263

В артефакт на основі сервлетів, такий як @WebServlet, @WebFilterі @WebListener, ви можете схопити JSF "звичайної ванілі" @ManagedBean @RequestScoped:

Bean bean = (Bean) request.getAttribute("beanName");

і @ManagedBean @SessionScopedза:

Bean bean = (Bean) request.getSession().getAttribute("beanName");

і @ManagedBean @ApplicationScopedза:

Bean bean = (Bean) getServletContext().getAttribute("beanName");

Зауважте, що це попередньо вимагає, що квасоля вже заздалегідь автоматично створена JSF. Інакше ці повернуться null. Потім вам потрібно буде вручну створити боб і використовувати setAttribute("beanName", bean).


Якщо ви можете використовувати CDI @Namedзамість застарілого JSF 2.3 @ManagedBean, це ще простіше, особливо тому, що вам більше не потрібно вручну створювати боби:

@Inject
private Bean bean;

Зауважте, що це не буде працювати, коли ви використовуєте, @Named @ViewScopedтому що квадратик можна ідентифікувати лише за станом перегляду JSF, і це доступно лише тоді, коли FacesServletвиклик був. Тож у фільтр, який працює до цього, доступ до @Injectредактора @ViewScopedзавжди буде кинутий ContextNotActiveException.


Тільки коли ви всередині @ManagedBean, ви можете використовувати @ManagedProperty:

@ManagedProperty("#{bean}")
private Bean bean;

Зверніть увагу , що це не працює всередині @Namedабо @WebServletбудь-якої іншої артефакт. Це дійсно працює @ManagedBeanтільки всередині .


Якщо ви не знаходитесь у a @ManagedBean, але FacesContextвоно є доступним (тобто FacesContext#getCurrentInstance()не повертається null), ви також можете використовувати Application#evaluateExpressionGet():

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

що може бути зручним наступним чином:

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

і може використовуватися наступним чином:

Bean bean = findBean("bean");

Дивитися також:


9
Ви друга пропозиція про просто введення квасолі була настільки дивовижно простою, що я її зовсім не помітив. Як завжди, ваша відповідь ідеально зрозуміла. Величезне спасибі за вашу роботу тут, так.
jnt30

2
Тим часом (якщо говорити про JSF 2.2), схоже, метод AsseExpressionGet був розширений третім параметром, що дозволяє вказувати очікуваний клас, тому кастинг більше не буде потрібен. PostBean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", PostBean.class);
Marc Juchli

1
@Marc: З самого початку. Я думаю, що це просто залишок від помилки копіювання. Відповідь виправлено. Дякуємо за повідомлення.
BalusC

FacesContextдоступний, навіть якщо staticметод корисної програми findBean()визначений у простому класі Java. Як це доступно в простому класі Java, яким не керує JSF?
Крихітний

1
@Tiny: це, в свою чергу, викликається артефактом JSF в межах однієї теми.
BalusC

11

Я використовую наступний метод:

public static <T> T getBean(final String beanName, final Class<T> clazz) {
    ELContext elContext = FacesContext.getCurrentInstance().getELContext();
    return (T) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName);
}

Це дозволяє мені отримати повернутий об'єкт набраним способом.


3
Це вже охоплено прийнятою в даний час відповіддю і навіть більш зручним способом ( Classаргумент, а саме, в цій конструкції є непотрібним).
BalusC

3

Ви спробували такий підхід, як на цьому посиланні? Я не впевнений, чи createValueBinding()все ще доступний, але такий код повинен бути доступний із простого старого сервлета. Це вимагає, щоб боб вже існувало.

http://www.coderanch.com/t/211706/JSF/java/access-managed-bean-JSF-from

 FacesContext context = FacesContext.getCurrentInstance();  
 Application app = context.getApplication();
 // May be deprecated
 ValueBinding binding = app.createValueBinding("#{" + expr + "}"); 
 Object value = binding.getValue(context);

Це, ймовірно, не працюватиме в звичайному сервлеті. FacesContext - це артефакт локальної нитки на запит, встановлений життєвим циклом JSF (зазвичай це FacesServlet).
МакДауелл

7
ValueBinding застаріло з JSF 1.2 понад 4 роки тому.
BalusC

@BalusC: Це показує, наскільки я сучасний, я lol. З іншого боку, використання пошукової системи для дослідницьких методів виявляється контрпродуктивною зі всією старою інформацією. @McDowell: Це насправді має сенс. Я зроблю тест просто, щоб побачити, що станеться.
Джеймс П.

3

Ви можете отримати керований боб, передавши ім'я:

public static Object getBean(String beanName){
    Object bean = null;
    FacesContext fc = FacesContext.getCurrentInstance();
    if(fc!=null){
         ELContext elContext = fc.getELContext();
         bean = elContext.getELResolver().getValue(elContext, null, beanName);
    }

    return bean;
}

Я намагаюся зробити це з сервлета, але це не працює.
Фернандо

0

У мене була така ж вимога.

Я використав нижченаведений спосіб отримати його.

У мене був сеанс збору квасолі.

@ManagedBean(name="mb")
@SessionScopedpublic 
class ManagedBean {
     --------
}

Я використовував наведений нижче код в моєму сервлет-методі doPost ().

ManagedBean mb = (ManagedBean) request.getSession().getAttribute("mb");

це вирішило мою проблему.


Який сервлет ви використовуєте? товариш
Фернандо

1
Це HttpServlet.
Аніль

-1

Я використовую це:

public static <T> T getBean(Class<T> clazz) {
    try {
        String beanName = getBeanName(clazz);
        FacesContext facesContext = FacesContext.getCurrentInstance();
        return facesContext.getApplication().evaluateExpressionGet(facesContext, "#{" + beanName + "}", clazz);
    //return facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, nomeBean);
    } catch (Exception ex) {
        return null;
    }
}

public static <T> String getBeanName(Class<T> clazz) {
    ManagedBean managedBean = clazz.getAnnotation(ManagedBean.class);
    String beanName = managedBean.name();

    if (StringHelper.isNullOrEmpty(beanName)) {
        beanName = clazz.getSimpleName();
        beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
    }

    return beanName;
}

А потім зателефонуйте:

MyManageBean bean = getBean(MyManageBean.class);

Таким чином можна без проблем переробити код і відстежувати звичаї.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.