Получить JSF bean по имени в любом классе, связанном с Servlet

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

http://host/app/myBean/myProperty

to:

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

Можно ли загрузить bean по имени из обычного сервлета? Я могу использовать сервлет или помощник JSF для этого?

Кажется, я испорчен Spring, в котором все это слишком очевидно.

Ответ 1

В сервлете вы можете получить запрос beans с помощью:

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

и область сеанса beans:

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

и область приложения beans:

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

Если вы работаете в платформе/контейнере с поддержкой зависимостей, а bean управляется CDI @Named вместо JSF @ManagedBean, это еще проще:

@Inject
private Bean bean;

Независимо от области действия, когда вы находитесь внутри FacesContext (т.е. текущий HTTP-запрос был отправлен через FacesServlet), тогда обычный способ JSF2 использует 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");

Однако, когда вы уже находитесь в @ManagedBean, используйте @ManagedProperty является более чистым, поскольку он более декларативный.

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

Ответ 2

Я использую следующий метод:

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

Вы пробовали такой подход, как по этой ссылке? Я не уверен, что createValueBinding() все еще доступен, но такой код должен быть доступен из простого старого сервлета. Это требует, чтобы bean уже существовал.

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);

Ответ 4

Вы можете получить управляемый bean, передав имя:

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;
}

Ответ 5

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

Я использовал метод ниже, чтобы получить его.

У меня был сеанс bean.

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

Я использовал приведенный ниже код в моем методе doPost() сервлета.

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

он решил мою проблему.

Ответ 6

Я использую это:

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);

Таким образом вы можете без проблем реорганизовать свой код и отслеживать использование.