問題背景
- 最近在做一個(gè)session共享的業(yè)務(wù)唁盏,接手的項(xiàng)目中是通過tomcat-redis-session-manager-master這個(gè)jar包實(shí)現(xiàn)的session共享,該jar包依賴于tomcat容器检眯。而現(xiàn)在的項(xiàng)目需求是不依賴于特定容器厘擂,對該項(xiàng)目的session共享進(jìn)行相關(guān)修改。通過查找相關(guān)資料轰传,發(fā)現(xiàn)spring session符合要求。對于spring session的相關(guān)介紹瘪撇,這里就不做闡述了获茬,看官可自行查找。
問題描述
- 接手的項(xiàng)目中通過多個(gè)web應(yīng)用的war包進(jìn)行項(xiàng)目協(xié)作倔既,然而在使用spring session進(jìn)行session共享的時(shí)候恕曲,發(fā)現(xiàn)各web都是單獨(dú)的sessionId,并且存儲在Redis中。也就是說渤涌,各web應(yīng)用之間并沒有實(shí)現(xiàn)session共享佩谣,從而也就無法實(shí)現(xiàn)單點(diǎn)登錄功能。
問題解決
- 通過查看spring session相關(guān)源碼發(fā)現(xiàn)实蓬,在包路徑
org.springframework.session.web.http
下有一個(gè)DefaultCookieSerializer
類茸俭,該類有一個(gè)方法getCookiePath(HttpServletRequest request)
,下面為源碼相關(guān)內(nèi)容安皱,其中的syso為我調(diào)試的時(shí)候自己打印的log。
private String getCookiePath(HttpServletRequest request) {
if (this.cookiePath == null) {
System.out.println("cookiePath-->" + request.getContextPath());
return request.getContextPath() + "/";
}
return this.cookiePath;
}
- 通過上面的打印log,我發(fā)現(xiàn)該方法返回的cookiePath是web項(xiàng)目的子域路徑,也就是說叛拷,如果一個(gè)項(xiàng)目為localhost:8080/abc卷员,另一個(gè)項(xiàng)目為localhost:8080/def(該端口也可以不為8080),那么spring session就會認(rèn)為兩個(gè)項(xiàng)目的cookiePath分別為/abc和/def,從而也就認(rèn)定這兩個(gè)項(xiàng)目不為同一個(gè)cookiePath居砖,最終也就導(dǎo)致問題的出現(xiàn)虹脯,無法實(shí)現(xiàn)session共享。
- 解決該問題奏候,我們可以通過修改源碼返回的cookiePath循集,使得其認(rèn)為的cookiePath路徑一致,修改后的源碼為:
private String getCookiePath(HttpServletRequest request) {
// if (this.cookiePath == null) {
// System.out.println("cookiePath-->" + request.getContextPath());
// return request.getContextPath() + "/";
// }
// return this.cookiePath;
return "/";
}
此方式為所有返回的cookiePath都為“/”蔗草,也就使得各web應(yīng)用的cookiePath一致了暇榴。當(dāng)然厚棵,具體的修改還要根據(jù)實(shí)際項(xiàng)目進(jìn)行,但是最終解決的思路是一樣的蔼紧,各web應(yīng)用返回的cookiePath一致
- 對于如何修改源碼
1.第一種比較直接暴力的就是修改spring seesion源碼婆硬,并重新打成jar包
2.第二種就是讓程序復(fù)用DefaultCookieSerializer
類,在每個(gè)web項(xiàng)目中分別新建一個(gè)類DefaultCookieSerializer
類奸例,先假如該類所在的包為com.test
彬犯,復(fù)制源碼中DefaultCookieSerializer
類的內(nèi)容放入你自己新建的DefaultCookieSerializer
類中,由于篇幅問題查吊,我就不把DefaultCookieSerializer
類的內(nèi)容放出來了谐区,只要按上面所說的將getCookiePath(HttpServletRequest request)
返回值修改就可以了。新建類中在這個(gè)地方會出現(xiàn)報(bào)錯(cuò):
private boolean isServlet3()
{
// ServletRequest.getMethod("startAsync", new Class[0]);
return true;
// NoSuchMethodException nosuchmethodexception;
// nosuchmethodexception;
// return false;
}
為了方便演示逻卖,我就直接將相關(guān)報(bào)錯(cuò)注釋掉了宋列,看官可自行斟酌。
3.第三種就是修改各個(gè)web應(yīng)用的域名评也,還是那句話炼杖,最終解決的思路是一樣的,讓spring session對各web應(yīng)用返回的cookiePath一致
4.新建好DefaultCookieSerializer
類之后盗迟,需要修改applicationContext.xml
(我的項(xiàng)目是直接在該xml中進(jìn)行spring session相關(guān)配置坤邪,看官可根據(jù)自己項(xiàng)目在相應(yīng)的xml中對spring session進(jìn)行配置),在xml中添加以下內(nèi)容:
<bean id="defaultCookieSerializer" class="com.test.DefaultCookieSerializer" />
<bean class="org.springframework.session.web.http.CookieHttpSessionStrategy">
<property name="cookieSerializer" ref="defaultCookieSerializer" />
</bean>
<bean class="org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration">
<property name="cookieSerializer" ref="defaultCookieSerializer" />
</bean>
5.至此罚缕,對于spring session多web應(yīng)用無法實(shí)現(xiàn)session共享的問題解決了艇纺。
總結(jié)
- 看官如果遇到這種問題,可以嘗試使用本文所闡述的方法進(jìn)行相關(guān)配置邮弹。如果不行的話黔衡,請繼續(xù)填坑,加油!
- 本文使用的spring session包版本為spring-session-1.2.1-RELEASE.jar腌乡,可能不同的版本包內(nèi)容上會有些不同员帮,還是那句話,最終解決的思路是一樣的导饲,讓spring session對各web應(yīng)用返回的cookiePath一致捞高,重要的事終于說了3遍了
- 小生退下了,看官您受累渣锦!