如何在JSF的Bean类中获取PrimeFaces转发页面的目标URL?
解决PrimeFaces转发时获取逻辑视图ID(/hello)的问题
嘿,我明白你的困扰——明明配置的转发目标是逻辑视图ID /hello,但Bean里拿到的却是物理路径 /hi.xhtml。这是因为JSF(PrimeFaces基于它)会把逻辑视图ID通过导航规则解析成实际的物理页面路径,直接拿的话自然是解析后的结果。下面给你几个靠谱的解决办法:
方法一:从导航事件上下文抓原始逻辑视图ID
当触发导航转发时,JSF会触发PreNavigateEvent和PostNavigateEvent,这些事件里就藏着原始的逻辑视图ID。你可以在Bean里直接获取,或者注册一个监听器来捕获:import javax.faces.context.FacesContext; import javax.faces.event.PreNavigateEvent; // 在需要获取的Bean方法里直接拿 public String getTargetLogicalViewId() { FacesContext facesContext = FacesContext.getCurrentInstance(); // 从请求映射里获取导航事件实例 PreNavigateEvent navigateEvent = (PreNavigateEvent) facesContext.getExternalContext() .getRequestMap().get("javax.faces.event.PreNavigateEvent"); if (navigateEvent != null) { return navigateEvent.getToViewId(); // 这里拿到的就是/hello } return null; } // 或者注册一个全局监听器来捕获导航事件 public class NavigationListener implements javax.faces.event.SystemEventListener { @Override public void processEvent(javax.faces.event.SystemEvent event) { if (event instanceof PreNavigateEvent) { PreNavigateEvent preEvent = (PreNavigateEvent) event; String logicalViewId = preEvent.getToViewId(); // 可以把这个ID存到Bean属性里,或者直接使用 } } @Override public boolean isListenerForSource(Object source) { return true; } }方法二:手动维护映射表(简单直接)
如果你的导航规则不多且固定,不如直接在Bean里存一个逻辑视图和物理路径的映射,拿到物理路径后反向查找:import java.util.HashMap; import java.util.Map; public class YourBean { private static final Map<String, String> VIEW_MAP = new HashMap<>(); static { VIEW_MAP.put("/hi.xhtml", "/hello"); // 其他导航规则的映射也可以添加在这里 } public String getLogicalViewId(String physicalPath) { return VIEW_MAP.get(physicalPath); } }这种方法简单粗暴,缺点是如果后续导航规则修改了,你得同步更新这个映射表。
方法三:从FacesConfig动态解析导航规则
要是你的导航规则比较多或者可能动态变化,那就用JSF API直接读取faces-config.xml里的导航规则,动态匹配:import javax.faces.application.Application; import javax.faces.application.NavigationCase; import javax.faces.context.FacesContext; public String getLogicalViewFromConfig(String physicalViewId) { FacesContext facesContext = FacesContext.getCurrentInstance(); Application app = facesContext.getApplication(); // 遍历所有导航规则,找到对应物理视图的逻辑ID for (NavigationCase navCase : app.getNavigationHandler().getNavigationCases(null, null)) { if (physicalViewId.equals(navCase.getToViewId(facesContext))) { return navCase.getFromViewId(); // 根据你的导航规则结构调整,可能需要修改此处 } } return null; }这种方法更灵活,不用手动维护映射,但得注意导航规则的结构,确保匹配逻辑正确。
顺便解释下为什么你现在拿到的是/hi.xhtml:PrimeFaces依赖JSF的导航机制,当你用逻辑视图ID转发时,JSF会先通过导航规则把它转换成实际的物理页面路径,所以直接从请求上下文拿到的都是解析后的物理路径,得用上面的方法去抓取原始的逻辑ID才行。
内容的提问来源于stack exchange,提问作者A.R
相关产品推荐
相关产品推荐

