如何重定向到JSF中的锚点?

时间:2011-07-06 19:09:38

标签: redirect jsf-2 accessibility anchor

假设我在JSF Managed Bean中有这个动作:

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

我的view有一个标识为msg的锚元素。我希望网址具有此锚点(用于辅助功能),例如:

view.jsf#msg

或者我的FacesServlet过滤模式。

return "view#msg?faces-redirect=true";显然无效,因为JSF(至少是mojarra)会尝试将view#msg评估为视图。

所以我的问题是如何让JSF最终重定向到#msg的网址。

2 个答案:

答案 0 :(得分:10)

  

因为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>

答案 1 :(得分:0)

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

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

不幸的是,片段被默认的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)