如何在Filter中获取JSF ViewScoped Bean跨所有Ajax请求的唯一标识符
解决方案
可以实现该需求,但无法直接从ServletRequest中直接获取到后端Bean实例,需要结合ViewScoped Bean的特性做少量改造,具体步骤如下:
实现步骤
- 给ViewScoped Bean添加唯一标识字段
在你的@ViewScoped@NamedBean中新增只读的instanceId字段,在Bean初始化时生成唯一值即可,示例代码:
import javax.annotation.PostConstruct; import javax.faces.view.ViewScoped; import javax.inject.Named; import java.io.Serializable; import java.util.UUID; @Named @ViewScoped public class YourViewBean implements Serializable { private String instanceId; @PostConstruct public void init() { // 实例化时生成唯一ID,生命周期和Bean完全一致 this.instanceId = UUID.randomUUID().toString(); } public String getInstanceId() { return instanceId; } }
注意:ViewScoped Bean必须实现Serializable接口,否则视图序列化时会出现异常
- 前端添加隐藏字段传递标识
在页面对应的表单内添加隐藏输入框,把instanceId值存入,所有同步请求、Ajax请求都会自动携带该参数:
<h:form id="yourViewForm"> <!-- 其他页面组件 --> <h:inputHidden value="#{yourViewBean.instanceId}" id="viewBeanInstanceId"/> </h:form>
如果使用PrimeFaces等第三方JSF框架,该隐藏值会自动包含在所有Ajax请求参数中,无需额外配置。
- Filter中读取请求参数获取Bean标识
在Filter的doFilter方法中直接从请求参数读取该标识即可:
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { HttpServletRequest httpRequest = (HttpServletRequest) request; // 参数名对应 表单ID:输入框ID,若表单设置prependId="false"则直接用输入框ID即可 String beanId = httpRequest.getParameter("yourViewForm:viewBeanInstanceId"); if (beanId != null) { // 此处即可用beanId区分同一个Bean的不同实例,该值会在所有关联请求中保持不变 } chain.doFilter(request, response); } finally { // 你的清理逻辑 } }
注意事项
- 不要尝试在Filter中直接获取FacesContext实例:Filter执行时JSF上下文尚未初始化,
FacesContext.getCurrentInstance()会返回null,无法直接获取后端Bean实例,通过请求参数传递是兼容性最高、实现最简单的方案。 - 若不想修改前端页面,也可以扩展JSF的ViewHandler,将Bean标识绑定到
javax.faces.ViewState参数中,但实现复杂度较高,无特殊需求优先使用隐藏字段方案。
内容的提问来源于stack exchange,提问作者russellelbert
相关产品推荐
相关产品推荐

