【问题标题】:Using session objects from parent class in component在组件中使用来自父类的会话对象
【发布时间】:2013-08-18 20:28:29
【问题描述】:

在与 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 类没有从 session 中获取 user 对象(尽管它肯定被初始化了,因为 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(无论会话中存储了什么)。问题是 - 为什么它会这样工作?

【问题讨论】:

    标签: session object components tapestry


    【解决方案1】:

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

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

    这里有几个保护页面的选项:

    1. Howard Lewis Ship's blog - Howard 是 Tapestry 的创造者
    2. Tynamo tapestry security

    【讨论】:

    • 不是那样的。我知道布局不是页面,我不指望它从 AuthPage 运行 onActivate 方法。我只希望它有 UserAuth 会话对象(作为 AuthPage 的扩展应该有)。 Layout 应该做的所有事情都包含在 Layout.checkNames() 中,但它的工作方式就像父类中的用户属性与会话分离一样。其他方式,例如当 UserAuth 对象在 Layout 类中显式定义(并注释为 SSO)时,它会从会话中正确初始化。我只是不明白为什么在父类中定义 UserAuth 对象时它不起作用。
    • basepackage.pages.* 包中是否包含 AuthPage?如果是这样,它可能会混淆挂毯。组件不应该扩展页面。
    • 不是那个问题。我已经将 AuthPage 到处移动(到项目的根包,将其打包到页面和组件的外部,甚至我已经将它放在与 Layout 相同的包中)但结果是相同的 - 来自 AuthPage 的会话对象已为索引页面正确初始化和布局组件为 null。
    • 您说您将其放入组件中并放入同一包中的布局。布局在什么包中?我假设它在组件(或组件的子包)中。
    • 是的。关于结构,我的项目简单而正确(工作,等等)。索引页面在页面中,组件中的布局组件和页面中的 AuthPage 超类(但也在其他包中并且也不起作用)。我相信整个问题更多是关于通过组件处理父类属性(至少关于会话存储)而不是项目结构。
    【解决方案2】:

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

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

    【讨论】:

    • 我有 Tapestry 5.3.2,所以不应该这样。
    【解决方案3】:

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

    this.user
    

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

    super.user
    

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

    【讨论】:

    • 只有“this.user”失败吗?还是“用户”也失败了? Tapestry 使用字节码操作将所有实例字段引用切换到 getter。看起来它可能错过了这个
    • “this.user”和“user”都失败了。
    • 您可以尝试将tapestry.production-mode 设置为false 并重试吗?我认为它应该在开发模式下工作。如果我们了解问题,它有助于提交更好的 jira 问题。
    • 好的,我会在不久的将来尝试测试它,如果我发现了什么,会发布结果。
    猜你喜欢
    • 2017-12-23
    • 2015-12-15
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2021-09-09
    • 2021-12-11
    相关资源
    最近更新 更多