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

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

问题描述

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

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,其中:

  • 操作代表将重定向用户的页面.您可以将其视为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
  • 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中绑定了两个<h:inputHidden>组件.它们将用于存储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的老Blackberry用户使用).

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

技术信息

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参数设置为ForwardBeanactionactionParam属性.

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),以便可以由Navigationhandler重置它,否则,您必须在servlet容器的配置中增加响应缓冲区),在f:viewbeforePhase上调用Bean方法:

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不言自明(请注意<redirect />条目将在封面下执行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用作

<!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:

  • Hit a bean method and redirect on a GET request
  • Is there any easy way to preprocess and redirect GET requests?

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

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