我在我的应用程序中遇到了一个我不明白的行为。我有一个servlet( Servlet1 )接受请求,使当前会话无效,创建一个新会话,然后将请求重定向到引用@Named @SessionScoped bean的JSF页面( Bean1 )。 servlet和bean @Inject都是另一个@SessionScoped bean( SharedBean )。我第一次访问我的servlet URL时一切正常。但是,第二次访问URL时,@ Named @SessionScoped bean正在创建一个新的sharedbean实例。
所以我想要发生的是:
第一次访问我的servlet URL时会发生这种情况,但第二次调用时发生的情况是:
这对我来说似乎不是正确的行为。我知道我在这里遗漏了一些东西,我很感激有人向我解释。代码如下:
Servlet1:
@WebServlet
public class Servlet1 extends HttpServlet
{
@Inject
private SharedBean sbean;
public doGet(HttpServeltRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession();
session.invalidate();
session = request.getSession(true);
this.sbean.initialize();
response.sendRedirect(newURL);
}
}
Bean1:
@Named
@SessionScoped
public class Bean1 implements Serializable
{
@Inject
private SharedBean sbean;
public void actionMethod()
{
this.sbean.execute(); // New instance being created here on 2nd access!
}
}
SharedBean:
@SessionScoped
public class SharedBean implements Serializable
{
public void initialize() { /* do some work */ }
public void exeucte() { /* do some work */ }
}
答案 0 :(得分:1)
因为每次请求servlet时都会使会话无效。所以容器创建一个新bean或提供另一个实例。在用户或某个其他端点处于非活动状态一段时间后,您必须使会话无效。
SessionScoped 表示bean实例对多个请求有效。 但您必须确定会话对您的应用程序的意义。 在大多数情况下,会话与用户登录和注销的时间相关联。所以它由多个请求组成。 因此,会话对多个请求有效,对于不同的servlet也是如此。 会话由servlet容器(例如Tomcat)管理,会话对象的实例通过 ServletContext 实例提供。
每次请求servlet时都会创建一个新会话。这意味着容器只为该单个请求创建 ServletContext ,并始终将 SharedBean 的新bean实例绑定到该上下文实例。
由于评论而更新。
在这种情况下,我不建议让容器管理bean注入。 因为您永远不知道bean实例创建和关联的时间 一个SharedBean实例。我认为原因是你在servlet请求方法中创建一个新会话的问题。在这种情况下, SharedBean 的bean实例不能相同,因为容器会创建 SharedBean 的新实例,并使绑定到servlet的共享bean实例无效。
在这种情况下创建 SharedBean 会更好 在servlet中,将其作为参数传递给会话上下文并使用 bean中的 SessionContext 用于获取 SharedBean 实例。
由于评论而更新
注入的bean由容器管理。表示容器负责创建和销毁bean。如果创建bean的新实例,则引用(地址)或bean实例与servlet容器分离,并且不再由容器管理。因此,共享bean引用不适用于托管bean Bean1
由于评论而更新
问题的答案是,您在Servlet方法的 doGet 方法中创建的 SharedBean 实例未传递给servlet容器,因此不会可用于托管bean Bean1 。