105

我正在尝试编写一个自定义 servlet(用于 AJAX/JSON),我想在其中引用我@ManagedBeans的名字。我希望映射:

http://host/app/myBean/myProperty

至:

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

是否可以从常规 servlet 按名称加载 bean?是否有我可以使用的 JSF servlet 或助手?

我似乎被春天宠坏了,这一切都太明显了。

4

6 回答 6

266

@WebServlet在基于 servlet 的工件中,例如@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");

请注意,这预先要求 bean 已经由 JSF 预先自动创建。否则这些将返回null。然后,您需要手动创建 bean 并使用setAttribute("beanName", bean).


如果您能够使用 CDI@Named而不是自 JSF 2.3 deprecated 以来的版本@ManagedBean,那么它会更加容易,特别是因为您不再需要手动创建 bean:

@Inject
private Bean bean;

请注意,这在您使用时不起作用,@Named @ViewScoped因为 bean 只能由 JSF 视图状态标识,并且只有在FacesServlet被调用时才可用。因此,在之前运行的过滤器中,访问@Injected@ViewScoped总是会抛出ContextNotActiveException.


只有当你在里面时@ManagedBean,你才能使用@ManagedProperty

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

@Named请注意,这在 a or@WebServlet或任何其他工件内不起作用。它真的@ManagedBean只在里面有效。


如果您不在 a 内@ManagedBean,但aFacesContext随时可用(即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");

也可以看看:

于 2010-04-13T22:50:58.427 回答
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);
}

这允许我以键入的方式获取返回的对象。

于 2012-12-10T18:10:30.430 回答
3

您是否尝试过类似此链接的方法?我不确定是否createValueBinding()仍然可用,但应该可以从普通的旧 Servlet 访问这样的代码。这确实需要 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);
于 2010-04-13T21:10:02.027 回答
3

您可以通过传递名称来获取托管 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;
}
于 2014-07-29T19:50:18.973 回答
0

我有同样的要求。

我已经使用下面的方法来获取它。

我有会话范围的bean。

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

我在我的 servlet doPost() 方法中使用了以下代码。

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

它解决了我的问题。

于 2016-06-27T11:36:23.420 回答
-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);

通过这种方式,您可以毫无问题地重构代码并跟踪使用情况。

于 2015-09-11T18:05:27.310 回答