使用组件中父类的会话对象

时间:2013-08-18 20:28:30

标签: session object components tapestry

在我与tapestry 5的战斗中,我创建了一些不起作用的设置,我不知道为什么。我发现很少有解决办法,但我仍然想知道为什么最初的想法失败了。

我有一个带有应用程序范围的auth过程的父抽象页面类:

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时,我获得了Index内容,否则它将转到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类看不到存储在会话中的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(无论会话中存储什么)。问题是 - 为什么它会这样运作?

3 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

您使用的是哪种版本的挂毯?在tapestry 5.3.1及更早版本中,实例变量必须是私有的。只有版本5.3.2+支持protected和package private。

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

答案 2 :(得分:0)

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

this.user

从子类中引用它。原来我在任何地方都得到它,即使在页面中(我的印象是它在Index页面中正常工作,但事实上它只是在AuthPage类中使用)。解决方案是参考:

super.user

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