所有 ajax 请求中 JSF ViewScoped bean 的唯一 ID?
Unique ID for a JSF ViewScoped bean across all ajax requests?
我(主要)使用 @ViewScoped @Named Faces bean(javax.faces.view.ViewScoped
和 javax.inject.Named
)并且想知道我是否可以从 ServletRequest(或 HttpServletRequest)中区分两者javax.servlet.Filter
中同一 bean 的不同实例化
例如,用户在两个不同的选项卡中打开同一个页面,但是这两个选项卡通过调用 httpRequest.getSession().getId()
具有相同的 SessionID。目前这对我没有帮助。
或者,我可以访问线程 ID,但这会随着每次 ajax 调用而改变,我需要在所有调用中为支持 bean 的实例保留一些独特的东西。直到 bean被摧毁了。
所以,像这样(这不起作用,但希望能说明我的需要)
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
// not real code, but this is what I'm looking for;
// get a unique identifier for just this instance of the bean that stays the same across all ajax requests
String beanId = request.getCurrentBackingBean.getInstanceId();
...
您可以通过 FacesContext
获得它,但 不能 在 ServletFilter
.ServletFilter
的 运行 上获得到 JSF 所在的 Servlet,因此在到达 de Servlet 之前无法访问 FacesContext
(您的入口点将是任何托管 bean)。
但是,如果您设法重塑业务逻辑以便能够在托管 bean 中执行您想要的操作,则可以通过以下方式获取视图 ID:
FacesContext.getCurrentInstance().getViewRoot().getViewId();
或者如果您使用的是 JSF 2.3,您可以在任何托管 bean 中注入 FacesContext
:
@Inject
FacesContext facesContext;
...
public void anyMethod() {
facesContext.getViewRoot().getViewId();
}
为了 FacesContext
的注入工作,您必须通过 CDI Bean 中的特殊注释激活 JSF 2.3 版特定功能,例如:
import javax.enterprise.context.ApplicationScoped;
import javax.faces.annotation.FacesConfig;
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
@ApplicationScoped
public class JSF23ActivationBean {
}
正如@BalusC 在评论中提到的,servlet 过滤器可能不是解决此问题的最佳位置,但我正在使用可能不允许重构的现有代码.
他的其他评论让我想到了这个解决方案:
在过滤器中:使用HttpServletRequest
,获取参数“javax.faces.ViewState”。这包含跨 Ajax 个请求的我的 (ViewScoped) 支持 bean 的视图的唯一 ID。它将为支持 bean 的每个新实例创建一个新的唯一 ID。
请注意,它似乎在第一次调用过滤器时不可用,我假设是因为尚未在新的支持 bean 上调用 @PostConstruct。我最初尝试解决这个问题是通过以下调用将其从 FacesContext(在@PostConstruct 中)中拉出来:
String viewState = FacesContext.getCurrentInstance().getApplication().getStateManager().getViewState(FacesContext.getCurrentInstance());
ThreadContext.put("viewState", viewState);
虽然这似乎获得了 viewState,但它似乎以某种方式破坏了生命周期,并且我的页面没有呈现。我想知道在页面呈现之前是否无法 'grab' viewState?
现在,Filter
中的工作代码现在看起来像这样(截断):
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
String viewState = httpRequest.getParameter("javax.faces.ViewState");
...
ThreadContext.put("viewState", viewState);
...
我(主要)使用 @ViewScoped @Named Faces bean(javax.faces.view.ViewScoped
和 javax.inject.Named
)并且想知道我是否可以从 ServletRequest(或 HttpServletRequest)中区分两者javax.servlet.Filter
例如,用户在两个不同的选项卡中打开同一个页面,但是这两个选项卡通过调用 httpRequest.getSession().getId()
具有相同的 SessionID。目前这对我没有帮助。
或者,我可以访问线程 ID,但这会随着每次 ajax 调用而改变,我需要在所有调用中为支持 bean 的实例保留一些独特的东西。直到 bean被摧毁了。
所以,像这样(这不起作用,但希望能说明我的需要)
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
// not real code, but this is what I'm looking for;
// get a unique identifier for just this instance of the bean that stays the same across all ajax requests
String beanId = request.getCurrentBackingBean.getInstanceId();
...
您可以通过 FacesContext
获得它,但 不能 在 ServletFilter
.ServletFilter
的 运行 上获得到 JSF 所在的 Servlet,因此在到达 de Servlet 之前无法访问 FacesContext
(您的入口点将是任何托管 bean)。
但是,如果您设法重塑业务逻辑以便能够在托管 bean 中执行您想要的操作,则可以通过以下方式获取视图 ID:
FacesContext.getCurrentInstance().getViewRoot().getViewId();
或者如果您使用的是 JSF 2.3,您可以在任何托管 bean 中注入 FacesContext
:
@Inject
FacesContext facesContext;
...
public void anyMethod() {
facesContext.getViewRoot().getViewId();
}
为了 FacesContext
的注入工作,您必须通过 CDI Bean 中的特殊注释激活 JSF 2.3 版特定功能,例如:
import javax.enterprise.context.ApplicationScoped;
import javax.faces.annotation.FacesConfig;
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
@ApplicationScoped
public class JSF23ActivationBean {
}
正如@BalusC 在评论中提到的,servlet 过滤器可能不是解决此问题的最佳位置,但我正在使用可能不允许重构的现有代码.
他的其他评论让我想到了这个解决方案:
在过滤器中:使用HttpServletRequest
,获取参数“javax.faces.ViewState”。这包含跨 Ajax 个请求的我的 (ViewScoped) 支持 bean 的视图的唯一 ID。它将为支持 bean 的每个新实例创建一个新的唯一 ID。
请注意,它似乎在第一次调用过滤器时不可用,我假设是因为尚未在新的支持 bean 上调用 @PostConstruct。我最初尝试解决这个问题是通过以下调用将其从 FacesContext(在@PostConstruct 中)中拉出来:
String viewState = FacesContext.getCurrentInstance().getApplication().getStateManager().getViewState(FacesContext.getCurrentInstance());
ThreadContext.put("viewState", viewState);
虽然这似乎获得了 viewState,但它似乎以某种方式破坏了生命周期,并且我的页面没有呈现。我想知道在页面呈现之前是否无法 'grab' viewState?
现在,Filter
中的工作代码现在看起来像这样(截断):
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
String viewState = httpRequest.getParameter("javax.faces.ViewState");
...
ThreadContext.put("viewState", viewState);
...