一、WebSocket 服务端配置
1.1 服务注册
服务注册分为两种模式:注解模式(推荐)、XML配置模式
1.1.1 注解配置模式
/** * * @author Goma * */ @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myhandler(), "/websocket").addInterceptors(myInterceptors()).setAllowedOrigins("*"); registry.addHandler(myhandler(), "/sockjs/websocket").addInterceptors(myInterceptors()).withSockJS(); } @Bean public WebSocketHandler myhandler() { return new WebsocketEndPoint(); } @Bean public HandshakeInterceptor myInterceptors() { return new HandshakeInterceptor(); } }
注:该类需要放在SpringMVC扫描路径下
@Configuration 指明该类为Spring 配置类
@EnableWebSocket 声明该类支持WebSocket
registry.addHandler(myhandler(), "/websocket").addInterceptors(myInterceptors()).setAllowedOrigins("*");
用来注册WebSocket Server实现类,第二个参数是访问WebSocket的地址
注:setAllowedOrigins方法用来设置来自那些域名的请求可访问,默认为localhost
registry.addHandler(myhandler(), "/sockjs/websocket").addInterceptors(myInterceptors()).withSockJS();
允许客户端使用SockJS
1.1.2 XML配置模式
更新Spring application.xml namespace,使其支持WebSocket
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:websocket="http://www.springframework.org/schema/websocket" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
namespace中添加
xmlns:websocket="http://www.springframework.org/schema/websocket" http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd"
<bean id="websocket" class="com.camelot.lrpportal.web.webapp.controller.WebsocketEndPoint"/> <websocket:handlers> <websocket:mapping path="/websocket" handler="websocket"/> <websocket:handshake-interceptors> <bean class="com.camelot.lrpportal.web.webapp.controller.HandshakeInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>
1.2 服务端编写
public class WebsocketEndPoint extends TextWebSocketHandler { private Logger logger = Logger.getLogger(getClass()); @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); logger.debug("GOMA === > WebSocketEndPoint.handlerTextMessage..."); TextMessage returnMessage = new TextMessage(message.getPayload()+" received at server"); session.sendMessage(returnMessage); } }
这个类处理来之浏览器(客户端)的WebSocket请求。在这个例子中,我们创建一个叫WebSocketEndPoint的类,并让它集成TextWebsocketHandler类。然后重写父类方法handlerTextMessage(),每当客户端发送信息过来,都会由这个函数接收并处理。
当然这里还可以重写其他方法,如afterConnectionEstablished、afterConnectionClosed、handleTransportError 等等
扩展:这里可以将登录用户保存到对象中,然后可以实现点对点消息发送、发送所有用户等功能。
1.3 握手拦截器
WebSocket握手拦截器用来拦截和处理客户端和服务器端分别在握手前和握手后的事件,我们这里添加这个拦截器是为了清晰的知道什么时候以及是否握手成功。
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { private Logger logger = Logger.getLogger(getClass()); @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { logger.debug("GOMA ===> Before Handshake"); return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { logger.debug("GOMA ===> After Handshake"); super.afterHandshake(request, response, wsHandler, ex); } }
二、WebSocket 客户端配置
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('response').innerHTML = ''; } function connect() { if ('WebSocket' in window){ console.log('Websocket supported'); socket = new WebSocket('ws://localhost:8080/lrpportal-web-webapp/websocket'); console.log('Connection attempted'); socket.onopen = function(){ console.log('Connection open!'); setConnected(true); } socket.onclose = function(){ console.log('Disconnecting connection'); } socket.onmessage = function (evt) { var received_msg = evt.data; console.log(received_msg); console.log('message received!'); showMessage(received_msg); } } else { console.log('Websocket not supported'); } } function disconnect() { setConnected(false); console.log("Disconnected"); } function sendName() { var message = document.getElementById('message').value; socket.send(JSON.stringify({ 'message': message })); } function showMessage(message) { var response = document.getElementById('response'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.appendChild(document.createTextNode(message)); response.appendChild(p); } /* 1. new WebSocket('ws://localhost:8080//websocket')尝试与服务器建立连接; 2. 握手成功并建立连接后,socket.onopen被调用 3. 当接收来自服务器的消息,socket.onmessage被调用 4. socket.send()用来发送消息至服务端 */ </script> </head> <body> <button id="connect" onclick="connect()">connect</button> <button id="disconnect" onclick="disconnect()"/>disconnect</button><br> <input id="message" value="send message"/> <button onclick="sendName()">发送消息</button> <div id="response"></div> </body> </html>
参考文档:
http://segmentfault.com/a/1190000000610456
http://blog.csdn.net/heng_ji/article/details/39007227
http://my.oschina.net/ldl123292/blog/304360?fromerr=VA5k7FnU