二、LIFERAY中的實現(xiàn)
LIFERAY在構(gòu)建ActionRequestImpl和RenderRequestImpl時,會設(shè)置PORTLET SESSION,如下代碼所示: public RenderRequestImpl(HttpServletRequest req, Portlet portlet, ??????? CachePortlet cachePortlet, ??????? PortletContext portletCtx, ??????? WindowState windowState, PortletMode portletMode, ??????? PortletPreferences prefs, String layoutId) { ?? ... ??_req = dynamicReq; ??_portlet = portlet; ??_cachePortlet = cachePortlet; ??_portalCtx = new PortalContextImpl(); ??_portletCtx = portletCtx; ??_windowState = windowState; ??_portletMode = portletMode; ??_prefs = prefs; ??_ses = new PortletSessionImpl( ???_req.getSession(), _portletName, _portletCtx); ?? ... ?} 從蘭色的部分(? _ses = new PortletSessionImpl(_req.getSession(),_portletName, _portletCtx);? )我們可以看到,這個PORTLET SESSION其實就是PORTAL SYSTEM的 SESSION 對象。 所以無論request調(diào)用getSession()或者getPortletSession()都將獲取Portal 系統(tǒng)的SESSION 對象,而無論該PORTLET? 是或者不是屬于PORTAL SYSTEM上下文。而且即使不同PORTAL APPLICATION的PORTLET也將使用同一個SESSION 對象(PORTAL 系統(tǒng))。 也就是說,對于某一個PORTLET來說,如果有對其的SESSION進(jìn)行的操作,并沒有真正的在該APPLICATION上下文中的SESSION進(jìn)行操作,而是在PORTAL系統(tǒng)上下文的SESSION中進(jìn)行操作。
而且LIFERAY提供getPortletSession來獲取PortletSession對象,而不是getSession()方法,所以即使getPortletSession()可以獲取正確的Session對象,開發(fā)人員由于習(xí)慣問題,也因使用getSession()而得不到。
另外如果調(diào)用request.getSession(true)還可能會出現(xiàn)錯誤,因為LIFERAY在包含某一個PORTLET內(nèi)容是,調(diào)用PortletRequestDispatcherImpl.include()方法,該方法將生成PortletServletRequest 和PortletServletResponse,請見如下代碼:
PortletServletRequest portletServletReq = new PortletServletRequest( ????httpReq, reqImpl, pathInfo, queryString, requestURI, ????servletPath);
???PortletServletResponse portletServletRes = ????new PortletServletResponse( ?????resImpl.getHttpServletResponse(), resImpl); 而PortletServletRequest的構(gòu)造函數(shù)是如下定義的: public PortletServletRequest(HttpServletRequest req, ???????? RenderRequest renderRequest, String pathInfo, ???????? String queryString, String requestURI, ???????? String servletPath) {
??super(req);
??_ses = req.getSession(); ??_renderRequest = renderRequest; ??_pathInfo = pathInfo; ??_queryString = queryString; ??_requestURI = requestURI; ??_servletPath = servletPath; ?} 所以其SESSION依然是PORTAL系統(tǒng)上下文的。然后問題就出在這里,PortletServletRequest實現(xiàn)了getSession()方法,但是沒有實現(xiàn)getSession(boolen create)方法,如果用戶在此階段調(diào)用getSession(true)的話,在某些情況下就會拋出NullPointerException
原因見如下代碼(請注意我添加的注釋部分) //ApplicationHttpRequest:??
?public HttpSession getSession(boolean create) {
??????? if (crossContext) { ??????????? ??????????? // There cannot be a session if no context has been assigned yet ??????????? if (context == null) ??????????????? return (null);
??????????? // Return the current session if it exists and is valid ??????????? if (session != null) ??????????????? return (session.getSession()); ???? // 我的注釋:這里將獲取PORTAL系統(tǒng)的SESSION對象。 ??????????? HttpSession other = super.getSession(false); ??????????? if (create && (other == null)) { ??????????????? // First create a session in the first context: the problem is ??????????????? // that the top level request is the only one which can ??????????????? // create the cookie safely ??????????????? other = super.getSession(true); ??????????? } ??????????? if (other != null) { ??????????????? Session localSession = null; ??????????????? try { ??????????????????? // 我的注釋:this context did not have the session with session id. It can just be found in the Portal ??????????????????? // context. So here it will return a null value. ??????????????????? localSession = ??????????????????????? context.getManager().findSession(other.getId()); ??????????????????? localSession.access(); //我的注釋:Here, localSession is null. So it throws a NullPointException. ??????????????? } catch (IOException e) { ??????????????????? // Ignore ??????????????? } ??????????????? if (localSession == null) { ??????????????????? localSession = context.getManager().createEmptySession(); ??????????????????? localSession.setNew(true); ??????????????????? localSession.setValid(true); ??????????????????? localSession.setCreationTime(System.currentTimeMillis()); ??????????????????? localSession.setMaxInactiveInterval ??????????????????????? (context.getManager().getMaxInactiveInterval());
|