Portal开源实现-Liferay的Portlet Session处理(

系统 1501 0
二、LIFERAY中的实现

LIFERAY在构建ActionRequestImpl和RenderRequestImpl时,会设置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调用getSession()或者getPortletSession()都将获取Portal 系统的SESSION 对象,而无论该PORTLET  是或者不是属于PORTAL SYSTEM上下文。而且即使不同PORTAL APPLICATION的PORTLET也将使用同一个SESSION 对象(PORTAL 系统)。
也就是说,对于某一个PORTLET来说,如果有对其的SESSION进行的操作,并没有真正的在该APPLICATION上下文中的SESSION进行操作,而是在PORTAL系统上下文的SESSION中进行操作。

而且LIFERAY提供getPortletSession来获取PortletSession对象,而不是getSession()方法,所以即使getPortletSession()可以获取正确的Session对象,开发人员由于习惯问题,也因使用getSession()而得不到。

另外如果调用request.getSession(true)还可能会出现错误,因为LIFERAY在包含某一个PORTLET内容是,调用PortletRequestDispatcherImpl.include()方法,该方法将生成PortletServletRequest 和PortletServletResponse,请见如下代码:

 

PortletServletRequest portletServletReq  =   new  PortletServletRequest(
    httpReq, reqImpl, pathInfo, queryString, requestURI,
    servletPath);

   PortletServletResponse portletServletRes 
=
    
new  PortletServletResponse(
     resImpl.getHttpServletResponse(), resImpl);
而PortletServletRequest的构造函数是如下定义的:
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系统上下文的。然后问题就出在这里,PortletServletRequest实现了getSession()方法,但是没有实现getSession(boolen create)方法,如果用户在此阶段调用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系统的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());
                    localSession.setId(other.getId());
                }

                session 
=  localSession;
                
return  session.getSession();
            }

            
return   null ;

        }
  else   ... {
            
return   super .getSession(create);
        }


    }


 


Portal开源实现-Liferay的Portlet Session处理(2)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论