【问题标题】:How to redirect to an anchor in JSF?如何重定向到 JSF 中的锚点?
【发布时间】:2011-07-06 19:09:37
【问题描述】:

假设我在一个 JSF 托管 Bean 中有这个动作:

public String doSomething() {
    FacesContext.getCurrentInstance().getExternalContext().getFlash().put("msg", "Something was done successfully");
    return "view?faces-redirect=true";
}

我的view 有一个id 为msg 的锚元素。我希望 url 有这个锚点(对于可访问性问题),比如:

view.jsf#msg

或者我的 FacesServlet 过滤器模式。

return "view#msg?faces-redirect=true"; 显然不会起作用,因为 JSF(至少 mojarra)会尝试评估 view#msg 作为视图。

所以我的问题是如何让 JSF 重定向到最后带有#msg 的 URL。

【问题讨论】:

    标签: redirect jsf-2 accessibility anchor


    【解决方案1】:

    因为 JSF(至少是 mojarra)会尝试评估 view#msg 作为视图

    哦,那太恶心了。绝对值得 JSF/Mojarra 男孩提出增强请求。

    最好的办法是在 ExternalContext#redirect() 的帮助下手动发送重定向。

    public void doSomething() throws IOException {
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ec.getFlash().put("msg", "Something was done successfully");
        ec.redirect("view.xhtml#msg");
    }
    

    (假设FacesServlet 映射到*.xhtml

    或者,您可以有条件地渲染一段 JS 来代替。

    <ui:fragment rendered="#{not empty flash.msg}">
        <script>window.location.hash = 'msg';</script>
    </ui:fragment>
    

    【讨论】:

    • 那段 JS 的想法不错。此外,ExternalContext#redirect() 效果很好。再一次,一个很好的答案:)
    • 我想补充一点,如果你想跳转到同一页面上的锚点,重定向重新加载,所以 JS 是更好的选择。不要忘记将代码放在要跳转到的元素之后。
    【解决方案2】:

    您尝试构建非法 URL - 片段 (#) 始终是 URL 的最后一部分。

    return "view?faces-redirect=true#msg" 将是正确的 URL。

    不幸的是,该片段已被默认 NavigationHandler 剥离,至少在 JSF 2.2 中是这样。

    虽然BalusC 的两个选项也可以正常工作,但我还有第三个选项可以提供。用一个小补丁包裹NavigationHandlerViewHandler

    public class MyViewHandler extends ViewHandlerWrapper {
    
        public static final String REDIRECT_FRAGMENT_ATTRIBUTE = MyViewHandler.class.getSimpleName() + ".redirect.fragment";
    
        // ... Constructor and getter snipped ...
    
        public String getRedirectURL(final FacesContext context, final String viewId, final Map<String, List<String>> parameters, final boolean includeViewParams) {
            final String redirectURL = super.getRedirectURL(context, viewId, removeNulls(parameters), includeViewParams);
            final Object fragment = context.getAttributes().get(REDIRECT_FRAGMENT_ATTRIBUTE);
            return fragment == null ? redirectURL : redirectURL + fragment;
        }
    
    }
    
    public class MyNavigationHandler extends ConfigurableNavigationHandlerWrapper {
    
        // ... Constructor and getter snipped ...
    
        public void handleNavigation(final FacesContext context, final String fromAction, final String outcome) {
            super.handleNavigation(context, fromAction, 
                storeFragment(context, outcome));
        }
    
        public void handleNavigation(final FacesContext context, final String fromAction, final String outcome, final String toFlowDocumentId) {
            super.handleNavigation(context, fromAction, 
                storeFragment(context, outcome), toFlowDocumentId);
        }
    
        private static String storeFragment(final FacesContext context, final String outcome) {
            if (outcome != null) {
                final int hash = outcome.lastIndexOf('#');
                if (hash >= 0 && hash + 1 < outcome.length() && outcome.charAt(hash + 1) != '{') {
                    context.getAttributes().put(MyViewHandler.REDIRECT_FRAGMENT_ATTRIBUTE, outcome.substring(hash));
                    return outcome.substring(0, hash);
                }
            }
            return outcome;
        }
    }
    

    (我不得不为 ViewHandler 创建包装器,因为修复了 JAVASERVERFACES-3154)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2011-11-01
      相关资源
      最近更新 更多