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

我正在尝试编写一个定制的 servlet (用于 AJAX/JSON) ,其中我希望按名称引用我的 @ManagedBeans。我希望能绘制出:

http://host/app/myBean/myProperty

致:

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

是否可以通过名称从普通的 servlet 加载 bean?是否有一个 JSF servlet 或者 helper 可以用于它?

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

156074 次浏览

Have you tried an approach like on this link? I'm not sure if createValueBinding() is still available but code like this should be accessible from a plain old Servlet. This does require to bean to already exist.

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

In a servlet based artifact, such as @WebServlet, @WebFilter and @WebListener, you can grab a "plain vanilla" JSF @ManagedBean @RequestScoped by:

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

and @ManagedBean @SessionScoped by:

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

and @ManagedBean @ApplicationScoped by:

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

Note that this prerequires that the bean is already autocreated by JSF beforehand. Else these will return null. You'd then need to manually create the bean and use setAttribute("beanName", bean).


If you're able to use CDI @Named instead of the since JSF 2.3 deprecated @ManagedBean, then it's even more easy, particularly because you don't anymore need to manually create the beans:

@Inject
private Bean bean;

Note that this won't work when you're using @Named @ViewScoped because the bean can only be identified by JSF view state and that's only available when the FacesServlet has been invoked. So in a filter which runs before that, accessing an @Injected @ViewScoped will always throw ContextNotActiveException.


Only when you're inside @ManagedBean, then you can use @ManagedProperty:

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

Note that this doesn't work inside a @Named or @WebServlet or any other artifact. It really works inside @ManagedBean only.


If you're not inside a @ManagedBean, but the FacesContext is readily available (i.e. FacesContext#getCurrentInstance() doesn't return null), you can also use Application#evaluateExpressionGet():

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

which can be convenienced as follows:

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

and can be used as follows:

Bean bean = findBean("bean");

See also:

I use the following method:

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

This allows me to get the returned object in a typed manner.

You can get the managed bean by passing the name:

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

I use this:

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

And then call:

MyManageBean bean = getBean(MyManageBean.class);

This way you can refactor your code and track usages without problems.

I had same requirement.

I have used the below way to get it.

I had session scoped bean.

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

I have used the below code in my servlet doPost() method.

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

it solved my problem.