引入:
大家都知道我們可以用Session來儲存屬性,但是Liferay PortletSession有些特殊,它可以用不同的scope來儲存不同的屬性,我們的sample代碼如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/15061KS6-0.png" title="1.png" alt="154156521.png" />
我們這裡就來研究PortletSession的細節,比如,它是如何做到吧屬性存放在不同的scope上的。
調試分析:
對於第一種情況:session.getAttribute("foo",PortletSession.PORTAL_SCOPE),它其實調用的是PortletSessionImpl的getAttribute()方法的如下分支:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/15061L3I-1.png" title="2.png" alt="154430719.png" />
其實,從宏觀上看,它依然是從httpSession()上取得一個屬性,只不過這個屬性的key不再是原來的key,而是一個封裝值,這個封裝的值是通過_getPortletScopeName(name)擷取的。我們看下這個方法的細節,它會調用_getPortletScopeName(_portletName,_plid,name)方法,也就是這個產生的key由portletName,portletLayoutId和要求的屬性的key 共同決定的:
具體,它的調用可以看出:
650) this.width=650;" src="http://img1.51cto.com/attachment/201309/154830287.png" title="3.png" alt="154830287.png" />
它會在getPortletScope(portletName,plid調用之後,後面再跟上?name 來擷取最終的key.
而getPortletScope(portletName,plid)的調用則非常簡單,如下:
650) this.width=650;" src="http://img1.51cto.com/attachment/201309/155031834.png" title="4.png" alt="155031834.png" />
它會依次附加上Portlet_SCOPE_NAMESPACE(javax.portlet.p.)和portletName,_LAYOUT_,和plid.
因為上述參數都已知,所以很容易就得出了getPortletScope(portletName,plid)的傳回值:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/15061I306-4.png" title="5.png" alt="155337795.png" />
這樣,再拼接上問號 ?和屬性的原始key,之後,很快就可以得到最終儲存在httpSession上的key了。
這個值是javax.portlet.p.logsearchportlet_WAR_logsearchportlet_LAYOUT_21601?foo
對於第二種情況,session.getAttribute("bar",PortletSession.APPLICATION_SCOPE),它其實調用的是HttpSession的getAttribute()方法的如下分支:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/15061J509-5.png" title="7.png" alt="161007833.png" />
所以直截了當,它直接是從httpSession上根據傳入的屬性key擷取對應的屬性value。
總結:
通過這個簡單的小實驗,我們可以看出以下結論:
(1)PortletSession上擷取變數在PORTLET_SCOPE和APPLICATION_SCOPE其實本質沒什麼不同,都是從HttpSession上擷取變數,只不過變數的key 不同,對於PORTLET_SCOPE,這個key在原始的key前面加了很多字串作為最終的key,而對於APPLICATION_SCOPE,則這個key就是最終的key.
(2)對於PORTLET_SCOPE,最終屬性的 key字串模式為Portlet名字空間+portletName+(_LAYOUT_)+portletLayoutId+"?"+原始keyPortlet名字空間.所以它portletName,portletLayoutId和原始key共同決定,我們也可以把這個結論進行延伸。因為不同的portlet的portletName肯定不同進而這個key肯定不同,所以PortletSession無法共用其他portlet放在PORTLET_SCOPE上的屬性,就算這些portlet位於同一個session中。因為同一個portlet如果多次部署,那麼layoutId肯定不同進而這個key肯定不同,所以PortletSession無法共用這個portlet部署多次後,在以前執行個體中存放在PORTLET_SCOPE上的屬性,就算這些portlet位於同一個session中。 但是,同一個session下的多個portlet或者單portlet的多個執行個體依然可以通過APPLICATION_SCOPE來共用屬性。
(3)正是因為PortletSession可以通過對屬性的key進行改造來區分APPLICATION_SCOPE和PORTLET_SCOPE上的屬性,所以PortletSession的如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/15061I315-6.png" title="6.png" alt="160723163.png" />
本文出自 “平行線的凝聚” 部落格,請務必保留此出處http://supercharles888.blog.51cto.com/609344/1297791