gpt4 book ai didi

jakarta-ee - JSF 请求范围的 bean 不断在每个请求上重新创建新的有状态 session bean?

转载 作者:行者123 更新时间:2023-12-03 08:46:44 28 4
gpt4 key购买 nike

我正在使用 JSF、PrimeFaces、Glassfish 和 Netbeans 构建我的第一个 Java EE 应用程序。因为我是新手,所以我可能错误地处理了核心问题。

核心问题:我想安全地维护用户的信息。关于是否应该在 JSF session bean 或有状态 session EJB 中维护它似乎存在冲突的想法。我正在尝试使用有状态 session EJB,因为这样更安全。

问题是我的应用程序似乎正在创建该 bean 的多个实例,而我希望它创建一个并重新使用它。如果我刷新页面,它会运行 @PostConstruct@PostActivate 3 次,它们都具有不同的实例。然后,当我重新部署应用程序时,它们都会被销毁。

我是否误解了它应该如何工作或配置错误?

我将尝试展示一个精简的代码示例:
basic.xhtml :

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
<c:if test="#{loginController.authenticated}">
Authenticated
</c:if>
</h:body>
</html>
LoginController :
@Named(value = "loginController")
@RequestScoped
public class LoginController implements Serializable {

@EJB
private UserBeanLocal userBean;

public boolean isAuthenticated() {
return userBean.isAuthenticated();
}

}
UserBean (不包括 UserBeanLocal接口(interface))
@Stateful
public class UserBean implements UserBeanLocal, Serializable {

boolean authenticated = false;

@PostConstruct
@PostActivate
public void setup(){
System.out.println("##### Create user Bean: "+this.toString());
}

@Override
public boolean isAuthenticated() {
System.out.println("########## Authentication test is automatically passing.");
authenticated = true;//hard coded for simplicity.
return authenticated;
}

@PrePassivate
@PreDestroy
public void cleanup(){
System.out.println("##### Destroy user Bean");
}

}

最后,这是刷新 3 次后的 Glassfish 输出:

INFO: ##### Create user Bean: boundary._UserBean_Serializable@2e644784
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ##### Create user Bean: boundary._UserBean_Serializable@691ae9e7
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ##### Create user Bean: boundary._UserBean_Serializable@391115ac
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.
INFO: ########## Authentication test is automatically passing.

最佳答案

有状态 session bean (SFSB) 并非您所想的那样。您似乎认为它们的行为类似于 session 范围的 JSF 托管 bean。这是不真实的。 EJB 中的术语“ session ”与您所想到的 HTTP session 具有完全不同的含义。
EJB 中的“ session ”必须在事务上下文中解释。只要客户端存在,事务(基本上是数据库 session )就存在于 SFSB 的情况下。 SFSB 的客户在您的特定示例中是 不是 webbrowser,但 JSF 托管 bean 实例本身,正是 SFSB 被注入(inject)的地方。由于您已将 JSF 托管 bean 放在请求范围内,SFSB 将与 JSF 托管 bean 一起在每个 HTTP 请求上重新创建。
例如,尝试将 JSF 托管 bean 放在 View 范围内。例如, View 范围对于同一页面上的多步骤表单很有用。每当 View 回发到自身时,相同的 JSF 托管 bean 实例将被重用,并且该实例使您可以访问 相同创建 bean 时的 SFSB 实例,即 不是 在别处共享。只要客户端( View 范围的 JSF 托管 bean)存在,SFSB 事务就会存在。
无状态 session bean (SLSB) 可以在其他地方共享,但这无关紧要,因为无论如何它都打算被视为无状态。这个“特性”节省了容器创建和存储它们的时间和内存。容器可以只有一个池。更重要的是,注入(inject)到 View 、 session 或应用程序范围的 JSF 托管 bean 中的 SLSB 实例不一定需要在每个 HTTP 请求上引用与创建 JSF 托管 bean 期间完全相同的实例。它甚至可以是完全不同的实例,具体取决于容器池中的可用实例。只要 SLSB 上的单个方法调用,事务就会存在(默认情况下)。
也就是说,SFSB 不适合您“记住登录用户”的特定情况。它“更安全”真的没有意义。只需将 JSF 托管 bean 放在 session 范围内,让它自己记住登录用户,并使用 SLSB 执行任何业务操作(例如与 DB 交互),并且仅在需要真正有状态时才使用 SFSB session bean(我假设您现在了解它们到底是什么:))。
也可以看看:

  • When is it necessary or convenient to use Spring or EJB3 or all of them together?
  • Why Stateless session beans?
  • JSF Service Layer
  • 关于jakarta-ee - JSF 请求范围的 bean 不断在每个请求上重新创建新的有状态 session bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8887140/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com