0

在与 Tapestry 5 的战斗中,我创建了一些不起作用的设置,我不知道为什么。我找到了一些解决方法,但我仍然想知道为什么最初的想法失败了。

我有具有应用程序范围的身份验证过程的父抽象页面类:

public abstract class AuthPage {
    @SessionState
    protected UserAuth user;


    public Object onActivate(){
        if(user==null)
            return LoginForm.class;
        else if(user.getLoggedIn().equals(Boolean.FALSE))
            return LoginForm.class;
        else
            return null;
    }
}

然后我有索引页面类,使用 auth 类作为 aprent:

public class Index extends AuthPage
{

}

这部分工作顺利 - 当用户 SSO 被初始化时,我得到了索引内容,否则它进入 LoginForm。现在有问题的部分——索引使用了一个布局组件,它负责显示个性化的标题和菜单。它的逻辑是这样的:

public class Layout extends AuthPage
{  
    @Property
    private Boolean loggedIn;

    @Property
    private String userName;

    @SetupRender
    public boolean checkNames(){
        if(user==null){
            loggedIn = false;
            userName = "unlogged";
        }
        else if(user.getLoggedIn().equals(Boolean.FALSE)){
            loggedIn=false;
            userName = "unlogged";
        }
        else{
            loggedIn = true;
            userName = this.user.getUsername();
        }

        return true;
    }
}

这个想法很简单 - 来自 AuthPage 的会话对象用户应该在 Layout 中可用,并在 setup-render 阶段使用以获取用户名并为渲染菜单等升旗。从我的角度来看,一切都应该工作,但实际上是 Layout 类没有从会话中获取用户对象(尽管它肯定已初始化,因为 Index 呈现其内容)。

所以我的问题是 - 为什么 Layout 类看不到存储在会话中的 UserAuth 对象,而是将其设置为 null 呢?

** * ** * ** * ***小更新:

我已将布局重构为该形状:

public class Layout
{
    @SessionState
    protected UserAuth user;

    @Property
    private Boolean loggedIn;

    @Property
    private String userName;

    @SetupRender
    public boolean checkNames(){
        if(user==null){
             loggedIn = false;
             userName = "unlogged";
        }
        else if(user.getLoggedIn().equals(Boolean.FALSE)){
             loggedIn=false;
             userName = "unlogged";
        }
        else{
             loggedIn = true;
             userName = this.user.getUsername();
        }

        return true;
    }
}

它可以按我的意愿工作 - 布局(从索引页面作为组件执行)从会话中获取用户属性,执行 checkNames 并正确设置所有属性。对我来说,初始实现和第二个实现之间没有技术差异,但不知何故,当用户在父类中定义时,总是设置为 null(无论会话中存储了什么)。问题是——为什么它会这样工作?

4

3 回答 3

0

你用的是什么版本的挂毯?在 Tapestry 5.3.1 和更早的版本中,实例变量必须是私有的。只有版本 5.3.2+ 支持受保护和包私有。

http://tapestry.apache.org/page-and-component-classes-faq.html#PageAndComponentClassesFAQ-Whydomyinstancevariableshavetobeprivate%3F

于 2013-08-20T08:35:49.947 回答
0

Layout 是一个组件,而不是一个页面,并且 onActivate() 是页面事件,它不会在 Layout 组件呈现时触发。对于一个组件(Layout)来扩展一个页面(AuthPage)是没有意义的。我很惊讶 Tapestry 允许它说出真相。

另一方面,Tapestry 有很多特性(包括过滤器、类转换和混合),几乎总是不需要继承。虽然相当复杂,但您可能会发现此页面底部的图表很有用。特别是您可能对 ComponentRequestFilters 和 PageRenderRequestFilters 感兴趣。

以下是保护页面的几个选项:

  1. Howard Lewis Ship 的博客- Howard 是 Tapestry 的创造者
  2. Tynamo 挂毯安全性
于 2013-08-19T07:46:05.630 回答
0

好的,我解决了问题!答案对我来说有点出乎意料,但很好 - 现在一切似乎都很好。诀窍是我引用 AuthPage 类的用户属性的方式。我用了

this.user

从子类中引用它。事实证明,我在任何地方都将它设置为 null,即使在页面中也是如此(我的印象是它在索引页面中正常工作,但实际上它只是在 AuthPage 类中使用)。解决方案是参考:

super.user

当我突然切换到这种引用样式时,每个页面和组件都开始正常工作并从会话中获得正确的值。我会照原样接受它,但如果有人知道为什么它会以这种方式工作而不是其他方式 - 我会很感激与我分享这些知识。

于 2013-08-21T18:58:52.630 回答