1

编辑:这是一个史诗般的手掌情况。SessionScoped 的导入错误。昨晚检查它时太累了,我确定我正在使用企业会话范围导入,而我仍在使用面部会话范围导入。我把它留下来帮助像我这样的笨蛋。:)


这是该项目的早期阶段。在使用托管 bean 实现这一点之后,我将托管 bean 更改为 CDI bean,因为这似乎是关于最佳处理方式的最新共识,但这破坏了以前的工作代码。我终其一生都无法弄清楚为什么。帮助和建议表示赞赏。

快乐的道路(摘要......代码摘录下面的详细信息)

如果用户未登录,则显示登录或注册链接。
如果用户登录显示用户首选项或注销链接。

现在 CDI 的糟糕路径(我不怪 CDI)

如果用户未登录,则显示登录或注册链接。
如果用户登录仍然看到登录或注册链接。(糟糕,糟糕的应用程序)

涉及的对象是

  1. 一个 facelet 菜单面板(带有一个 primefaces 登录对话框......我认为这与它没有任何关系,但为了完整性而包括在内)如果登录或未登录,则带有渲染属性,
  2. 会话范围的用户 bean,
  3. 一个请求范围的身份验证 bean,用于登录和注销用户。

下面列出了使用的对象。实现为 CDI bean。

小面

<h:panelGroup id="loginPanel" rendered="#{!user.loggedIn}">
    Show login buttons and stuff
</h:panelGroup>

 <h:panelGroup id="logoutPanel" rendered="#{user.loggedIn}">
    Show logout buttons and stuff
</h:panelGroup

身份验证 bean

@Named(value = "webAuthenticationBean") //formerly managedbean
@RequestScoped
public class WebAuthenticationBean implements Serializable {

    @Inject private UserBean user; //formerly a managed property which worked
...
request.login(uername, password);
user.setuserdata(username); // sessionscoped user state here used to check login state among other things later.
...
return(true) // they are now logged in

用户 bean

@Named(value = "user") //formerly managedbean
@SessionScoped
public class UserBean implements Serializable {

    @EJB
    private UserService userService; //stateless session bean
    private userInfo = new UserInfo(); // keeps user state and can be used as a DTO/VO

@PostConstruct
    public void init() {
    //sets default state to "guest user". This is NOT a logged in state
    }

public void setuserdata(String username){
     userInfo = userService.getUserInfo(username);
    // method called from WebAuthenticationBean 
    // sets the user state to a non-guest user (they're logged in).
    // I can see in debug mode that this is being called and retrieving
   //  the user data from the database and setting "userInfo"
}

public void isLoggedIn() throws InvalidUserException{
    // checks state to see if they are logged in, basically a bit more than are they still a guest or not
   returns (true) if logged in 
    returns (false) if not logged in
    // this worked with managed beans
}
...

所以这是我在调试模式下观看时的实际用例:

Happy Path(更改为 CDI bean 之前)

1) 用户导航到欢迎页面
2) 查询用户 bean 以查看他们是否已登录(facelet 中的 user.loggedIn)。
3) userbean 检查登录状态。如果他们仍然是访客,则未登录。
4) 他们被标识为访客,因此 isLoggedIn() 返回 false。
5) 显示登录按钮。
6) 用户请求登录
7) 认证bean 开始登录过程:request.login 返回成功
8) authenticationbean 设置用户数据:user.setuserdata(username) 返回成功。
9)身份验证bean loginMethod返回(他们在服务器上记录了userprincipal)

此处的备用(蹩脚)路径分支(快乐路径继续)

10) 菜单重新检查登录状态 (user.loggedIn)
11) userbean 检查适当的状态并确定它们是有效的非访客用户
12) userbean 返回 (true) 他们已登录
13) 菜单显示注销按钮

糟糕的路径(我将这些更改为 CDI bean 后会发生什么)

10) 菜单重新检查登录状态 (user.loggedIn)
11) userbean 检查适当的状态并看到他们是访客 //更新的用户状态似乎在此会话中从该用户中消失了。
12) userbean 返回 (false) 他们没有登录 // 但他们是
13) 菜单显示登录按钮 // 他们无论如何都无法登录,因为服务器已经看到他们登录,在这个会话中 (ServletException: Attempt to re -在用户身份已经存在时登录)。

为什么使用 managedbeans 可以看到 userbean 在会话范围内维护其数据,但使用 cdi bean 却不能?我难住了。如果必须,我会切换回托管 bean,这不是一个大问题,但我想找出我搞砸了。




我在 UserBean 的 init 方法中添加了一些调试代码,看起来好像系统将 SessionScoped UserBean 视为 RequestScoped。那就是它在每次调用时都进行初始化。

@PostConstruct
public void init() {
    if (userInfo == null) {
        userInfo = new UserInfoDTO();
        userInfo.setUserName("Guest");
        List<String> guestGroup = Arrays.asList(CoreUserGroupType.GUEST.toString());
        userInfo.setUserGroups(guestGroup);
        System.out.println("UserBean.init INSIDE Init If Statement");
    }
    System.out.println("UserBean.init OUTSIDE Init If Statement");
}

如果它真的像 SessionScoped 一样,那么 userInfo 对象就不会每次都为空,并且不会每次都执行“if”语句。但它会在每次调用 UserBean 时执行。所以这是问题的症结所在。事实上,如果它的行为就像在会话范围内,它不会在每次调用时都命中 init 方法,因为它仍然会被初始化。

我没有正确创建会话范围的 bean 吗?看起来是这样,但我不知道如何。如前所述,此代码在定义为 managedbean 时运行良好。

4

1 回答 1

2

更改为正确的 sessionscoped 导入,一切都很好。没有什么伤害我的骄傲。

于 2012-08-20T22:08:32.550 回答