近來學(xué)習(xí) spring websocket 時(shí)按照 spring in action 中示例編寫代碼,運(yùn)行時(shí)瀏覽器報(bào)404 錯(cuò)誤
websocket connection to 'ws://localhost/websocket/marco' failed: error during websocket handshake: unexpected response code: 404
按照 spring in action 中步驟:
首先,繼承 abstractwebsockethandler,重載以下 3 個(gè)方法:
- handletextmessage – 處理文本類型消息
- afterconnectionestablished – 新連接建立后調(diào)用
- afterconnectionclosed – 連接關(guān)閉后調(diào)用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import org.springframework.web.socket.closestatus; import org.springframework.web.socket.textmessage; import org.springframework.web.socket.websocketsession; import org.springframework.web.socket.handler.abstractwebsockethandler; public class marcohandler extends abstractwebsockethandler { protected void handletextmessage(websocketsession session, textmessage message) throws exception { system.out.println( "received message: " + message.getpayload()); thread.sleep( 2000 ); session.sendmessage( new textmessage( "polo!" )); } @override public void afterconnectionestablished(websocketsession session) { system.out.println( "connection established!" ); } @override public void afterconnectionclosed(websocketsession session, closestatus status) { system.out.println( "connection closed. status: " + status); } } |
其次,使用 javaconfig 啟用 websocket 并映射消息處理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import org.springframework.context.annotation.bean; import org.springframework.web.socket.config.annotation.enablewebsocket; import org.springframework.web.socket.config.annotation.websocketconfigurer; import org.springframework.web.socket.config.annotation.websockethandlerregistry; @enablewebsocket public class websocketconfig implements websocketconfigurer { @override public void registerwebsockethandlers(websockethandlerregistry registry) { registry.addhandler(marcohandler(), "/marco" ); } @bean public marcohandler marcohandler() { return new marcohandler(); } } |
最后,編寫前端 js 代碼發(fā)起連接請(qǐng)求及后續(xù)消息交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
var url = 'ws://' + window.location.host + '/websocket/marco' ; var sock = new websocket(url); sock.onopen = function() { console.log( 'opening' ); sock.send( 'marco!' ); }; sock.onmessage = function(e) { console.log( 'received message: ' , e.data); settimeout(function() { saymarco() }, 2000 ); }; sock.onclose = function() { console.log( 'closing' ); }; function saymarco() { console.log( 'sending marco!' ); sock.send( 'marco!' ); } |
部署后打開瀏覽器運(yùn)行,直接報(bào) 404 錯(cuò)誤
上網(wǎng)搜索了一晚上解決方案,包括參考 stackoverflow.com 上的經(jīng)驗(yàn)都未解決該問題,直到查看到以下文章:
spring集成websocket頁面訪問404問題的解決方法
在此自己也做個(gè)記錄避免以后遺忘。
websocket 實(shí)質(zhì)上借用 http 請(qǐng)求進(jìn)行握手,啟用 spring websocket 需要在 org.springframework.web.servlet.dispatcherservlet 里配置攔截此請(qǐng)求。
以下是解決步驟:
首先,修改 websocketconfig 類定義,在類上添加 @configuration 注解,表明該類以 javaconfig 形式用作 bean 定義的源(相當(dāng)于 xml 配置中的 <beans> 元素)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.web.socket.config.annotation.enablewebsocket; import org.springframework.web.socket.config.annotation.websocketconfigurer; import org.springframework.web.socket.config.annotation.websockethandlerregistry; @configuration @enablewebsocket public class websocketconfig implements websocketconfigurer { @override public void registerwebsockethandlers(websockethandlerregistry registry) { registry.addhandler(marcohandler(), "/marco" ); } @bean public marcohandler marcohandler() { return new marcohandler(); } } |
其次,使用 javaconfig 配置 dispatcherservlet,繼承org.springframework.web.servlet.support.abstractannotationconfigdispatcherservletinitializer ,重載以下 3 個(gè)方法:
- getrootconfigclasses – 返回帶有 @configuration 注解的類將會(huì)用來配置 contextloaderlistener 創(chuàng)建的應(yīng)用上下文中的 bean
- getservletconfigclasses – 返回帶有 @configuration 注解的類將會(huì)用來定義 dispatcherservlet 應(yīng)用上下文中的 bean
- getservletmappings – 將一個(gè)或多個(gè)路徑映射到 dispatcherservlet 上
實(shí)際上,如果只需要 spring websocket 生效,則只需要在 getservletconfigclasses 方法中返回用來定義 dispatcherservlet 應(yīng)用上下文中的 bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import org.springframework.web.servlet.support.abstractannotationconfigdispatcherservletinitializer; public class websocketinitializer extends abstractannotationconfigdispatcherservletinitializer { @override protected class <?>[] getrootconfigclasses() { return null ; } @override protected class <?>[] getservletconfigclasses() { return new class <?>[] {websocketconfig. class }; } @override protected string[] getservletmappings() { return new string[] { "/" }; } } |
重新部署后代開瀏覽器運(yùn)行成功
客戶端消息
服務(wù)器消息
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://blog.csdn.net/silent_paladin/article/details/78269929