JSF 1.2 NavigationHandler 自定义导航

发布于 2024-08-23 18:11:20 字数 3927 浏览 3 评论 0原文

我正在尝试扩展 JSF 1.2 中的 NavigationHandler,并保留访问过的页面的堆栈(更准确地说,是视图 ID,以及操作和输出)。

我尝试实现一个自定义操作,例如“go_back”,它将带我返回上一页。

我当前的NavigationHandler:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import java.util.Stack;

public class NavigationManager extends NavigationHandler {

    NavigationHandler _base;
    private Stack trailPointStack;

    public NavigationManager(NavigationHandler base) {
        super();
        _base = base;
        trailPointStack = new Stack();
    }

    @Override
    public void handleNavigation(FacesContext fc, String actionMethod, String actionName) {
        NavigationPoint point;
        String currentAction = actionName;
        String currentMethod = actionMethod;

        if (actionName.equals("go_back") && (trailPointStack.size() > 0)) {
            point = (NavigationPoint) trailPointStack.pop();//better check if there is something in there
            //currentAction = null;
            //currentMethod = null;
            currentAction = point.getAction();
            currentMethod = point.getActionMethod();
            fc.getViewRoot().setViewId(point.getViewId());
        } else {
            point = new NavigationPoint(actionName, actionMethod, fc.getViewRoot().getViewId());
            trailPointStack.push(point);
        }

        //check stack size to be less than 6 items
        while (trailPointStack.size() > 5) {
            trailPointStack.removeElementAt(0);
        }

        _base.handleNavigation(fc, currentMethod, currentAction);
    }
}

NavigationPoint 只是一个带有3 个字符串的简单类,分别用于actionName、actionMethod 和ViewId。

我的导航规则,在 faces-config.xml 中:

<navigation-rule>
 <description>Index to subpages</description>
 <from-view-id>/index.jsp</from-view-id>
     <navigation-case>
        <from-outcome>i_to_1</from-outcome>
        <to-view-id>/page_a1.jsp</to-view-id>
        <redirect />
     </navigation-case>
     <navigation-case>
        <from-outcome>to_page_a2</from-outcome>
        <to-view-id>/page_a2.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

 <navigation-rule>
 <description>From page a1</description>
 <from-view-id>/page_a1.jsp</from-view-id>
     <navigation-case>
        <from-outcome>to_page_a2</from-outcome>
        <to-view-id>/page_a2.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

 <navigation-rule>
 <description>From page a2</description>
 <from-view-id>/page_a2.jsp</from-view-id>
     <navigation-case>
        <from-outcome>to_page_a1</from-outcome>
        <to-view-id>/page_a1.jsp</to-view-id>
        <redirect />
     </navigation-case>

     <navigation-case>
        <from-outcome>to_index</from-outcome>
        <to-view-id>/index.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

我只有 3 个页面,index.jsp、page_a1.jsp 和 page_a2.jsp。

您可以在导航案例中看到它们之间的联系。我想要的是能够从 page_a2.jsp“go_back”到 page_a1.jsp 或 index.jsp。

正常导航工作正常:索引 -> P1-> P2-> P1-> P2->指数;没问题。

如果我这样做:索引-> P1-> P2

我将在堆栈上:
底部
1:index.jsp/i_to_1 -> page_a1.jsp
2:page_a1.jsp/to_page_a2-> page_a2.jsp
top

当我从 P2 尝试“go_back”时,我希望它返回到第 1 页。但事实并非如此(页面刚刚重新加载)。 如果我再尝试一次,它就会起作用。

我认为这是因为在第一次尝试时,我从堆栈中弹出,并且它尝试执行“to_page_a2”操作 - 失败。 第二次,它再次从堆栈中弹出,但现在它尝试使用“i_to_1”,而这......不知何故,有效。

谁能帮我解决这个问题吗?我希望我的解释足够清楚 - 如果不是,请询问。

任何类似的想法也受到欢迎。我应该提到的是,我是在两天前开始使用 JSF 的,而且我不太清楚那里发生的一切。

谢谢你, 亚历克斯

I am trying to extend the NavigationHandler in JSF 1.2, and to keep a stack of the visited pages (more precisely, the view-ids, along with the action and the output).

I try to implement a custom action, such as "go_back", that will take me back to the previous page.

My current NavigationHandler:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import java.util.Stack;

public class NavigationManager extends NavigationHandler {

    NavigationHandler _base;
    private Stack trailPointStack;

    public NavigationManager(NavigationHandler base) {
        super();
        _base = base;
        trailPointStack = new Stack();
    }

    @Override
    public void handleNavigation(FacesContext fc, String actionMethod, String actionName) {
        NavigationPoint point;
        String currentAction = actionName;
        String currentMethod = actionMethod;

        if (actionName.equals("go_back") && (trailPointStack.size() > 0)) {
            point = (NavigationPoint) trailPointStack.pop();//better check if there is something in there
            //currentAction = null;
            //currentMethod = null;
            currentAction = point.getAction();
            currentMethod = point.getActionMethod();
            fc.getViewRoot().setViewId(point.getViewId());
        } else {
            point = new NavigationPoint(actionName, actionMethod, fc.getViewRoot().getViewId());
            trailPointStack.push(point);
        }

        //check stack size to be less than 6 items
        while (trailPointStack.size() > 5) {
            trailPointStack.removeElementAt(0);
        }

        _base.handleNavigation(fc, currentMethod, currentAction);
    }
}

The NavigationPoint is just a simple class with 3 Strings, for the actionName, actionMethod and ViewId.

My navigation rules, in faces-config.xml:

<navigation-rule>
 <description>Index to subpages</description>
 <from-view-id>/index.jsp</from-view-id>
     <navigation-case>
        <from-outcome>i_to_1</from-outcome>
        <to-view-id>/page_a1.jsp</to-view-id>
        <redirect />
     </navigation-case>
     <navigation-case>
        <from-outcome>to_page_a2</from-outcome>
        <to-view-id>/page_a2.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

 <navigation-rule>
 <description>From page a1</description>
 <from-view-id>/page_a1.jsp</from-view-id>
     <navigation-case>
        <from-outcome>to_page_a2</from-outcome>
        <to-view-id>/page_a2.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

 <navigation-rule>
 <description>From page a2</description>
 <from-view-id>/page_a2.jsp</from-view-id>
     <navigation-case>
        <from-outcome>to_page_a1</from-outcome>
        <to-view-id>/page_a1.jsp</to-view-id>
        <redirect />
     </navigation-case>

     <navigation-case>
        <from-outcome>to_index</from-outcome>
        <to-view-id>/index.jsp</to-view-id>
        <redirect />
     </navigation-case>
 </navigation-rule>

I only have 3 pages, index.jsp, page_a1.jsp and page_a2.jsp.

You can see in the navigation cases, the connections between them. What I want is to be able to "go_back" from page_a2.jsp, to either page_a1.jsp, or to index.jsp.

The normal navigation works fine: Index -> P1 -> P2 -> P1 -> P2 -> Index; no problem.

If I do: Index -> P1 -> P2

I will have on the stack:
bottom
1:index.jsp/i_to_1 -> page_a1.jsp
2:page_a1.jsp/to_page_a2 -> page_a2.jsp
top

When I try "go_back" from P2, I expect it to go back to page 1. It doesn't (the page is just reloaded).
If I try it a second time, it works.

I think it's because on the first try, I pop from the stack, and it tries with the action "to_page_a2" - fails.
The second time, it pops again from the stack, but now it tries with "i_to_1", and this.. somehow, works.

Can anyone help me with this? I hope my explanations were clear enough - if not, please ask.

Any similar idea is also welcome. I should mention that it was 2 days ago that I started using JSF, and it's not very clear to me all that happens there.

Thank you,
Alex

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久光 2024-08-30 18:11:20

好的,我找到了一个解决方案(或者,更好地说,一个补丁,因为我不确定它是否工作得很好)。

在执行“go_back”之前,我会弹出 2 个项目,而不是一个。

例如:索引 -> P1-> P2-返回;我应该去 P1 (P2 -> P1)

为了能够到达 P1,我实际上必须去“索引”点,然后尝试去 P1。 (我必须在要返回的页面之前执行一步):

堆栈:
1:弹出P1(我想访问它,所以我不能使用它;我只是将它从堆栈中删除)
2:弹出索引 - 使用索引点转到 P1(即使实际上在 P2 中)

更新的代码:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import java.util.Stack;

public class NavigationManager extends NavigationHandler {

    NavigationHandler _base;
    private Stack trailPointStack;

    public NavigationManager(NavigationHandler base) {
        super();
        _base = base;
        trailPointStack = new Stack();
    }

    @Override
    public void handleNavigation(FacesContext fc, String actionMethod, String actionName) {
        NavigationPoint point;
        String currentAction = actionName;
        String currentMethod = actionMethod;

        if (actionName.equals("go_back") && (trailPointStack.size() > 0)) {//"go_back" is the action that triggers the back move

            if (trailPointStack.size() == 1) {
                //It is the first page we visit (the second page in stack)
                point = (NavigationPoint) trailPointStack.pop();
                currentAction = null;
                currentMethod = point.getActionMethod();
            } else {
                trailPointStack.pop();//we get rid of the prev, and we go from prev-prev to prev :D
                point = (NavigationPoint) trailPointStack.pop();//actually the second one in the stack
                currentAction = point.getAction();
                currentMethod = point.getActionMethod();
            }

            fc.getViewRoot().setViewId(point.getViewId());
        } else {
            point = new NavigationPoint(actionName, actionMethod, fc.getViewRoot().getViewId());
            trailPointStack.push(point);
        }

        //check stack size to be max 10 items
        while (trailPointStack.size() > 10) {
            trailPointStack.removeElementAt(0);
        }

        _base.handleNavigation(fc, currentMethod, currentAction);
    }
}

我希望这对某人有帮助!

另外,我确信这可能不会很好地工作,我还没有进行太多测试。

欢迎任何其他想法。

谢谢
亚历克斯

Ok, I have found a solution (or, better said, a patch, because I am not sure it works too well).

I am popping 2 items, instead of one, before I do the "go_back".

Ex: Index -> P1 -> P2 - go_back; I am supposed to go to P1 (P2 -> P1)

To be able to reach P1, I actually have to go the the "Index" point, and then try to go to P1. (I have to go with one step before the page I want to go back to):

The stack:
1: pop P1 (I want to get to it, so I can't use it; I just remove it from the stack)
2: pop Index - use the Index point to go to P1 (even if am actually in P2)

The updated code:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import java.util.Stack;

public class NavigationManager extends NavigationHandler {

    NavigationHandler _base;
    private Stack trailPointStack;

    public NavigationManager(NavigationHandler base) {
        super();
        _base = base;
        trailPointStack = new Stack();
    }

    @Override
    public void handleNavigation(FacesContext fc, String actionMethod, String actionName) {
        NavigationPoint point;
        String currentAction = actionName;
        String currentMethod = actionMethod;

        if (actionName.equals("go_back") && (trailPointStack.size() > 0)) {//"go_back" is the action that triggers the back move

            if (trailPointStack.size() == 1) {
                //It is the first page we visit (the second page in stack)
                point = (NavigationPoint) trailPointStack.pop();
                currentAction = null;
                currentMethod = point.getActionMethod();
            } else {
                trailPointStack.pop();//we get rid of the prev, and we go from prev-prev to prev :D
                point = (NavigationPoint) trailPointStack.pop();//actually the second one in the stack
                currentAction = point.getAction();
                currentMethod = point.getActionMethod();
            }

            fc.getViewRoot().setViewId(point.getViewId());
        } else {
            point = new NavigationPoint(actionName, actionMethod, fc.getViewRoot().getViewId());
            trailPointStack.push(point);
        }

        //check stack size to be max 10 items
        while (trailPointStack.size() > 10) {
            trailPointStack.removeElementAt(0);
        }

        _base.handleNavigation(fc, currentMethod, currentAction);
    }
}

I hope this helps someone!

Also, I am sure this may not be working very well, I haven't tested too much yet.

Any other ideas are welcome.

Thanks
Alex

深爱不及久伴 2024-08-30 18:11:20

我已经实现了类似的东西;
我还拦截了 JavaScript 中的“退格”键,以便单击隐藏的 commandLink,该链接会触发导航到堆栈中的上一个视图(或您需要的任何组合/逻辑)。

在我的用例中,我已经扁平化了导航用例的逻辑,以便更轻松地在代码中从一个点导航到另一个点:

public static void navigate(String action, String outcome) {
    FacesContext fc = FacesContext.getCurrentInstance();
    NavigationHandler nh = fc.getApplication().getNavigationHandler();
    nh.handleNavigation(fc, action, outcome);
}

I've implemented something similar;
I've also intercepted the "backspace" key in javascript in order to click an hidden commandLink which triggers the navigation to the previous view in the stack (or any combination/logic that you need).

In my use case I've flattened the logic of the navigation cases in order to navigate more easily from point to point within the code:

public static void navigate(String action, String outcome) {
    FacesContext fc = FacesContext.getCurrentInstance();
    NavigationHandler nh = fc.getApplication().getNavigationHandler();
    nh.handleNavigation(fc, action, outcome);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文