WebSocket獲取httpSession空指針異常的解決辦法
小坑:使用requestListner解決不了這個(gè)問(wèn)題!
如何獲取HttpSession
在使用webSocket實(shí)現(xiàn)p2p或者一對(duì)多聊天功能的時(shí)候我們經(jīng)常會(huì)有這樣的需求:webSocket服務(wù)端需要獲取到用戶(hù)使用數(shù)據(jù)庫(kù)的用戶(hù)信息登錄后的HttpSession獲取個(gè)人資料信息。
于是,你會(huì)使用這樣的代碼:
package com.xinyulee.ws; import javax.servlet.http.HttpSession; import javax.websocket.HandshakeResponse; import javax.websocket.server.HandshakeRequest; import javax.websocket.server.ServerEndpointConfig; import javax.websocket.server.ServerEndpointConfig.Configurator; /** * Created by zipple on 2017/11/14. * 協(xié)助server獲取http session */ public class HttpSessionWSHelper extends Configurator { @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { System.out.println("調(diào)用modifyHandshake方法..."); HttpSession session = (HttpSession) request.getHttpSession();//session有可能為空 if (session!=null){ System.out.println("獲取到session id:"+session.getId()); sec.getUserProperties().put(HttpSession.class.getName(),session); }else{ System.out.println("modifyHandshake 獲取到null session"); } } }
然后在服務(wù)端這樣配置:
@ServerEndpoint(value ="/chatRoom/{username}",configurator=HttpSessionWSHelper.class,encoders = {ServerEncoder.class}) //encoders = {ServerEncoder.class}用于指定sendObject()方法調(diào)用的解析器
RequestListner解決不了這個(gè)問(wèn)題的原因
在使用上述方法配置完成以后我滿(mǎn)懷信心的進(jìn)行測(cè)試,但是意外的發(fā)現(xiàn)了Tomcat Localhost Log下報(bào)了null pointer exception。
經(jīng)過(guò)調(diào)試,發(fā)現(xiàn)了modifyHandshake方法并不能獲取到HttpSession,在上述HttpSessionWSHelper 類(lèi)代碼中可以看到我對(duì)它進(jìn)行了判空處理。但是這樣并不能起到什么實(shí)際上的作用。我們需要弄明白為什么HandshakeRequest 獲取不到HttpSession。
一開(kāi)始,我試著去百度了一下,發(fā)現(xiàn)有這樣的代碼:
package com.xinyulee.listener; import com.xinyulee.util.Log; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpServletRequest; /** * Created by zipple on 2017/11/14. */ @WebListener public class RequestListener implements ServletRequestListener { public void requestInitialized(ServletRequestEvent sre) { //將所有request請(qǐng)求都攜帶上httpSession----這樣會(huì)創(chuàng)建新的session!導(dǎo)致重新創(chuàng)建了會(huì)話(huà) Log.info("request--:"+sre.getServletRequest().getLocalAddr()); ((HttpServletRequest) sre.getServletRequest()).getSession(); } public RequestListener() { // TODO Auto-generated constructor stub } public void requestDestroyed(ServletRequestEvent arg0) { // TODO Auto-generated method stub } }
網(wǎng)上解釋說(shuō),是因?yàn)檫M(jìn)行ws連接的時(shí)候并沒(méi)有HttpSession處于激活狀態(tài),于是便不能獲取到HttpSession。他們給出的解決辦法是對(duì)每一個(gè)request請(qǐng)求調(diào)用sre.getServletRequest()).getSession()方法。
這樣的確可以解決空指針異常的問(wèn)題,但是新問(wèn)題又出現(xiàn)了。
在沒(méi)有HttpSession激活狀態(tài)的時(shí)候,使用getSession()方法會(huì)新建一個(gè)HttpSession,也就是說(shuō)實(shí)際上這個(gè)監(jiān)聽(tīng)器是在沒(méi)有激活HttpSession的情況下不斷新建會(huì)話(huà)。
這樣已經(jīng)完全偏離了我們程序的需求:獲取同時(shí)在線的HttpSession中保存的個(gè)人信息。
那么怎么辦呢?
事實(shí)上,這個(gè)空指針異常的根源并不是出在我們后端代碼上。
localhost和127.0.0.1其實(shí)并不是同一個(gè)連接
在前端連接WebSocket的時(shí)候,我的代碼是這樣的:
loadWS("ws://127.0.0.1/chatRoom/null");
然而瀏覽器地址欄是這樣的:
http://localhost:8080/
網(wǎng)上解釋說(shuō)如果不使用同一個(gè)host,則會(huì)創(chuàng)建不同的連接請(qǐng)求。具體細(xì)節(jié)有興趣的朋友可以去了解一下。
于是我們可以這樣拼接一下:
var host = window.location.host; var url = "ws://"+host+"/chatRoom/null";
這樣便可以正常建立ws請(qǐng)求,并且能夠使用自定義的HttpSessionWSHelper 類(lèi)獲取到HttpSession了。
到此這篇關(guān)于WebSocket獲取httpSession空指針異常的解決辦法的文章就介紹到這了,更多相關(guān)WebSocket獲取httpSession空指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Java設(shè)計(jì)一個(gè)高并發(fā)的秒殺系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了如何基于Java設(shè)計(jì)一個(gè)高并發(fā)的秒殺系統(tǒng),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2023-10-10idea 安裝 Mybatis 開(kāi)發(fā)幫助插件 MyBatisCodeHelper-Pro 插件破解版的方法
MyBatisCodeHelper-Pro 插件可以幫助我們快速的開(kāi)發(fā) mybatis,這篇文章給大家介紹idea 安裝 Mybatis 開(kāi)發(fā)幫助插件 MyBatisCodeHelper-Pro 插件破解版的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2020-09-09java正則表達(dá)式簡(jiǎn)單使用和網(wǎng)頁(yè)爬蟲(chóng)的制作代碼
java正則表達(dá)式簡(jiǎn)單使用和網(wǎng)頁(yè)爬蟲(chóng)的制作代碼,需要的朋友可以參考一下2013-05-05Java正則表達(dá)式之split()方法實(shí)例詳解
這篇文章主要介紹了Java正則表達(dá)式之split()方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了split方法的功能、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-03-03Java中l(wèi)ambda表達(dá)式的基本運(yùn)用
大家好,本篇文章主要講的是Java中l(wèi)ambda表達(dá)式的基本運(yùn)用,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下2022-01-01MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動(dòng)映射)
我們可以輕松的使用 Mybaits-Flex 鏈接任何數(shù)據(jù)庫(kù),本文主要介紹了MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動(dòng)映射),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06MyBatis批量插入幾千條數(shù)據(jù)為何慎用foreach
這篇文章主要介紹了MyBatis批量插入幾千條數(shù)據(jù)為何慎用foreach問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10