在任何与Servlet相关的类中按名称获取JSF托管bean

Kon*_*rus 98 jsf servlets java-ee jsf-2 managed-bean

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

http://host/app/myBean/myProperty

至:

@ManagedBean(name="myBean")
public class MyBean {
    public String getMyProperty();
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bal*_*usC 259

在Servlet中,您可以通过以下方式获取请求范围的bean:

Bean bean = (Bean) request.getAttribute("beanName");
Run Code Online (Sandbox Code Playgroud)

和会话范围的bean:

Bean bean = (Bean) request.getSession().getAttribute("beanName");
Run Code Online (Sandbox Code Playgroud)

和应用程序作用域bean:

Bean bean = (Bean) getServletContext().getAttribute("beanName");
Run Code Online (Sandbox Code Playgroud)

如果你在支持依赖注入的框架/容器中运行并且bean由CDI @Named而不是JSF 管理@ManagedBean,那么它就更容易了:

@Inject
private Bean bean;
Run Code Online (Sandbox Code Playgroud)

无论范围如何,当你实际进入内部时FacesContext(即当前的HTTP请求已通过服务FacesServlet),那么正常的JSF2方式正在使用Application#evaluateExpressionGet():

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);
Run Code Online (Sandbox Code Playgroud)

这可以方便如下:

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

并可以使用如下:

Bean bean = findBean("bean");
Run Code Online (Sandbox Code Playgroud)

但是,当你已经在里面时@ManagedBean,那么使用@ManagedProperty更清洁,因为它更具说明性.

@ManagedProperty("#{bean}")
private Bean bean;
Run Code Online (Sandbox Code Playgroud)

  • 你是关于注入豆子的第二个建议非常简单,我完全忽略了它.与往常一样,您的反应非常恰当.非常感谢您在SO上的工作. (9认同)
  • 与此同时(从JSF 2.2开始),似乎使用第三个参数扩展了evaluateExpressionGet方法,该参数允许指定期望的类,因此不再需要强制转换.``PostBean bean = context.getApplication().evaluateExpressionGet(context,"#{beanName}",PostBean.class);`` (2认同)

Joh*_*ary 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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这已经被当前接受的答案所覆盖,甚至以更方便的方式(在这种结构中``Class`参数是不必要的). (3认同)