JSF何时创建会话&它放在会话映射中的内容是什么? [英] When does JSF creates a session & what does it puts in a session map?

查看:128
本文介绍了JSF何时创建会话&它放在会话映射中的内容是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行Mojarra 2.2.0.

I am running Mojarra 2.2.0.

  <context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
  </context-param>

托管bean操作方法是-

The managed bean action method is-

public void action() {
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
                .getExternalContext().getSession(false);
        System.out.println(session.getId()); // not null for stateful views
    }

对于stateless视图,session.getId()引发NPE

对于非无状态的视图, 触发GET请求,有JSESSIONID=340041C96D5AA446D761C3602F54A76D

For views which are not stateless- Firing a GET request, there is JSESSIONID=340041C96D5AA446D761C3602F54A76D

我在此处读了它-

对于客户端状态保存机制,JSF不会创建会话 并将视图状态存储在名称如下的隐藏输入字段中 必要时,使用表单中的javax.faces.ViewState.

For client side state saving mechanism, JSF won't create the session and will store the view state in a hidden input field with the name javax.faces.ViewState in the form whenever necessary.

此外,这里提到

JSF实际上将自动创建会话,因为JSF视图状态具有 存放在那边.如果将JSF状态保存方法设置为 客户端而不是服务器,那么它将不会存储在会话中,因此 无需创建会话

JSF will indeed autocreate the session because the JSF view state has to be stored over there. If you set the JSF state saving method to client instead of server, then it won't be stored in session and hence no session needs to be created

我认为以上内容为我带来麻烦.

I think the above line is a source for trouble for me.

如果将JSF状态保存方法设置为客户端而不是服务器, 那么它就不会存储在会话中//完全同意

If you set the JSF state saving method to client instead of server, then it won't be stored in session // FULLY AGREED

因此无需创建会话. //这令人困惑,因为 客户端保存机制,会话ID由 Servlet容器和因此,存在与 请求.

hence no session needs to be created. // This confuses because for client side saving mechanism, a session id gets generated by the servlet container & hence there is a session associated with the request.

参考我在此问题, 我创建了一个HttpSessionListener-

In reference to the discussion which I had with BalusC in this question, I created a HttpSessionListener-

@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent event) {
        Thread.dumpStack();
    }

    public void sessionDestroyed(HttpSessionEvent event) {

    }

}

请参阅以下附件的屏幕截图(这2个屏幕截图适用于2.0.3版,必须存在一个旧错误才能创建会话)-

See below attached screenshots(these 2 screenshots are for version 2.0.3, there must have been an old bug due to which the session was getting created)-

天秤座(Mojarra 2.2.0)-

Libraby (Mojarra 2.2.0)-

推荐答案

JSF何时创建会话

确定这一点的最佳方法是创建一个 HttpSessionListener ,将调试断点放在sessionCreated()方法上,并检查需要首次获取会话的调用堆栈(因此暗中需要创建该会话).

Eaiest way to naildown this is creating a HttpSessionListener, putting a debug breakpoint on sessionCreated() method and inspecting the call stack who needed to get the session for the first time (and thus implicitly needs to create it).

在下面的示例中,您将在调用堆栈中看到一系列getSession()调用.您会看到FaceletViewHandlingStrategy.renderView()方法是第一次调用它的方法.

In below example you will see a chain of getSession() calls in the call stack. You will see that FaceletViewHandlingStrategy.renderView() method is the one calling it for the first time.

在调试器的调用堆栈中单击FaceletViewHandlingStrategy.renderView()行之后,您将进入其源代码(Maven将自动加载源代码,否则需要手动附加它).

After you click on FaceletViewHandlingStrategy.renderView() line in debugger's call stack, you will get into its source code (Maven will load source code automatically, otherwise you need to manually attach it).

您看到的是,启用服务器端状态保存并且呈现的视图不是瞬态的(>< h:form>导致java.lang.IllegalStateException:提交响应后无法创建会话).

You see, when server side state saving is enabled and the view to render is not transient (stateless), then JSF will implicitly create the session, just to ensure it's created on time in order to save the view (if the session was created later, e.g. during render response phase, you would otherwise risk exceptions like this Adding <h:form> causes java.lang.IllegalStateException: Cannot create a session after the response has been committed).

您还将在源代码中立即看到,将状态保存方法设置为client时,或者如<f:view transient="true">中那样视图为无状态时,JSF将不再隐式创建会话.如您所想,较旧的JSF版本可以做到这一点,但这应视为一个错误,应在较新的版本中进行修复.

You'll in the source code also immediately see that when the state saving method is set to client, or when the view is stateless as in <f:view transient="true">, then JSF won't anymore implicitly create the session. Older JSF versions may do that as you figured, but this is to be accounted as a bug and ought to be fixed in a newer version.

如果您想确保无状态并避免意外/意外的会话创建,则可以在sessionCreated()方法内使用throw new IllegalStateException().发生这种情况时,您只需要查看负责创建会话的调用堆栈,然后修复/更改代码就可以了.

If you would like to ensure statelessness and avoid accidental/unforeseen session creation, then you could just throw new IllegalStateException() inside sessionCreated() method. When that happens, you just have to look in call stack who's responsible for creating the session and then fix/change the code to not do that anymore.

它将什么放入会话映射中?

在幕后, ExternalContext#getSessionMap() 委托给HttpSession#setAttribute()/getAttribute()/removeAttribute().您可以使用 HttpSessionAttributeListener .

Under the covers, ExternalContext#getSessionMap() delegates to HttpSession#setAttribute()/getAttribute()/removeAttribute(). You can listen on those methods using a HttpSessionAttributeListener.

在下面的示例中,您将看到ViewScopeContextManager.getContextMap()行调用SessionMap#put()方法以便将某些内容放入会话映射中.展开event参数时,将看到会话属性的名称和值,分别为com.sun.faces.application.view.activeViewContexts和空的ConcurrentHashMap.

In below example you will see that ViewScopeContextManager.getContextMap() line calls SessionMap#put() method in order to put something in the session map. When you unfold the event argument, you will see the session attribute name and value, which is com.sun.faces.application.view.activeViewContexts and an empty ConcurrentHashMap respectively.

实际上,我使用的是@Named @ViewScoped,该值在特定页面上由值表达式引用(您会在调用堆栈的更下方看到EL解析器和Weld解析器).当您单击调用堆栈中的ViewScopeContextManager.getContextMap()行时,您会看到它只是在会话范围内准备一个映射以存储视图范围的bean.

Indeed, I was using a @Named @ViewScoped which was referenced by an value expression on the particular page (you see EL resolver and Weld resolver further down in call stack). When you click ViewScopeContextManager.getContextMap() line in call stack, you'll see that it was just preparing a map in session scope in order to store view scoped beans.

那只是一个例子.会话中可以存储更多内容.以这种方式使用调试器并检查相关的源代码将告诉您很多为什么.

That's just one example. There are more things which could be stored in the session. Using a debugger this way and inspecting the associated source code will tell a lot about the Why.

这篇关于JSF何时创建会话&amp;它放在会话映射中的内容是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆