如何在 JSF 1.x 中对页面加载进行重定向 [英] How to make a redirection on page load in JSF 1.x

查看:20
本文介绍了如何在 JSF 1.x 中对页面加载进行重定向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网络应用程序,可以将用户直接发送到某些特定页面(例如他可以查看或编辑项目的页面).为了实现这一点,我们提供了一个特定的 url.这些网址位于外部当前网络应用程序(即它们可以存在于另一个网络应用程序或电子邮件中).

I have a web-application where the users can be sent directly to some specific pages (such as a page where he can view or edit an item). To achieve that, we provide a specific url. These urls are located outside the current web-application (i.e. they can be present in another web-application, or in an email).

网址看起来像http://myserver/my-app/forward.jsf?action=XXX&param=YYY,其中:

  • action 表示用户将被重定向到的页面.您可以将其视为 faces-config.xmlnavigation-case 中任何 JSF 操作的 from-outcome.
  • actionParam 是前一个动作的参数(一般是商品 ID)
  • action represents the page where the user will be redirected. You can consider this as the from-outcome of any JSF action in navigation-case in faces-config.xml.
  • actionParam is a parameter for the previous action (generally an item ID)

例如,我可以拥有以下网址:

So for example, I can have these kind of urls:

  • http://myserver/my-app/forward.jsf?action=viewItem&actionParam=1234
  • http://myserver/my-app/forward.jsf?action=editItem&actionParam=1234

当然,我有一个 Java 类(bean),它会检查一些安全约束(即是否允许用户查看/编辑相应的项目?)然后将用户重定向到正确的页面(例如 edit.xhtmlview.xhtmlaccess-denied.xhtml).

Of course, I have a Java class (bean) that will check some security constraints (i.e. is the user allowed to see / edit the corresponding item?) and then redirect the user to the correct page (such as edit.xhtml, view.xhtml or access-denied.xhtml).

当前实施

目前,我们有一个基本的方法来完成前进.当用户点击链接时,会调用以下 XHTML 页面:

Currently, we have a basic way to accomplish the forward. When the user clicks on the link, the following XHTML page is called:

<html>
    <body id="forwardForm">
        <h:inputHidden id="myAction" binding="#{forwardBean.hiddenAction}"/>
        <h:inputHidden id="myParam" binding="#{forwardBean.hiddenActionParam}"/>
        <h:commandButton id="forwardBtn" actionListener="#{forwardBean.doForward}" style="display: none;"/>
    </body>
    <script type="text/javascript">
        document.getElementById('forwardForm:forwardBtn').click();
    </script>
</html>

如您所见,我在 Java bean 中绑定了两个 组件.它们将用于存储 actionactionParam 请求参数的值(使用 FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actiontParam");).我还提供了 doForward 方法,该方法将在呈现页面时立即调用,它将(再次)将用户重定向到真实页面.方法是:

As you can see, I bind two <h:inputHidden> components in my Java bean. They will be used to store the value of both action and actionParam request parameter (using FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actiontParam");). I also provide the doForward method that which will be called immediately when the page is rendered, which will redirect (again) the user to the real page. The method is:

public void doForward(ActionEvent evt) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    String redirect = // define the navigation rule that must be used in order to redirect the user to the adequate page...
    NavigationHandler myNav = facesContext.getApplication().getNavigationHandler();
    myNav.handleNavigation(facesContext, null, redirect);
}


此解决方案有效,但我有两个问题:


This solution is working, but I have two problems with that:

  • 我不喜欢它的实施方式.我确信我可以有更简单的东西(使用 Servlet?).
  • 此解决方案使用 Javascript,我不能使用 Javascript(因为此转发可能被不支持 Javascript 的老黑莓用​​户使用).

所以我的问题是如何重构这个重定向/转发功能?

技术信息

Java 1.6、JSF 1.2、Facelets、Richfaces

Java 1.6, JSF 1.2, Facelets, Richfaces

推荐答案

faces-config.xml 中将 GET 查询参数设置为托管属性,这样您就不需要手动收集它们:

Set the GET query parameters as managed properties in faces-config.xml so that you don't need to gather them manually:

<managed-bean>
    <managed-bean-name>forward</managed-bean-name>
    <managed-bean-class>com.example.ForwardBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>action</property-name>
        <value>#{param.action}</value>
    </managed-property>
    <managed-property>
        <property-name>actionParam</property-name>
        <value>#{param.actionParam}</value>
    </managed-property>
</managed-bean>

这样请求 forward.jsf?action=outcome1&actionParam=123 会让 JSF 将 actionactionParam 参数设置为 <ForwardBean 的 code>action 和 actionParam 属性.

This way the request forward.jsf?action=outcome1&actionParam=123 will let JSF set the action and actionParam parameters as action and actionParam properties of the ForwardBean.

创建一个小视图 forward.xhtml(小到适合默认响应缓冲区(通常为 2KB),以便它可以由导航处理程序重置,否则您必须增加响应缓冲区在 servletcontainer 的配置中),它在 f:view:

Create a small view forward.xhtml (so small that it fits in default response buffer (often 2KB) so that it can be resetted by the navigationhandler, otherwise you've to increase the response buffer in the servletcontainer's configuration), which invokes a bean method on beforePhase of the f:view:

<!DOCTYPE html>
<html xmlns:f="http://java.sun.com/jsf/core">
    <f:view beforePhase="#{forward.navigate}" />
</html>

ForwardBean 看起来像这样:

public class ForwardBean {
    private String action;
    private String actionParam;

    public void navigate(PhaseEvent event) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        String outcome = action; // Do your thing?
        facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, outcome);
    }

    // Add/generate the usual boilerplate.
}

navigation-rule 不言自明(注意 条目将执行 ExternalContext#redirect() 代替ExternalContext#dispatch() 在封面下):

The navigation-rule speaks for itself (note the <redirect /> entries which would do ExternalContext#redirect() instead of ExternalContext#dispatch() under the covers):

<navigation-rule>
    <navigation-case>
        <from-outcome>outcome1</from-outcome>
        <to-view-id>/outcome1.xhtml</to-view-id>
        <redirect />
    </navigation-case>
    <navigation-case>
        <from-outcome>outcome2</from-outcome>
        <to-view-id>/outcome2.xhtml</to-view-id>
        <redirect />
    </navigation-case>
</navigation-rule>

<小时>

另一种方法是使用 forward.xhtml as

<!DOCTYPE html>
<html>#{forward}</html>

并更新要在@PostConstruct上调用的navigate()方法(将在bean的构造和所有托管属性设置后调用):

and update the navigate() method to be invoked on @PostConstruct (which will be invoked after bean's construction and all managed property setting):

@PostConstruct
public void navigate() {
    // ...
}    

它具有相同的效果,但是视图端并不是真正的自文档化.它基本上所做的就是打印 ForwardBean#toString()(如果尚未存在,则在此隐式构造 bean).

It has the same effect, however the view side is not really self-documenting. All it basically does is printing ForwardBean#toString() (and hereby implicitly constructing the bean if not present yet).

JSF2 用户请注意,有一种使用 <f:viewParam> 传递参数的更简洁的方式,以及通过 <f:event 处理重定向/导航的更健壮的方式type="preRenderView">.另请参见:

Note for the JSF2 users, there is a cleaner way of passing parameters with <f:viewParam> and more robust way of handling the redirect/navigation by <f:event type="preRenderView">. See also among others:

这篇关于如何在 JSF 1.x 中对页面加载进行重定向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆