spring4+tomcat8+jdk8应用websocket
2015-11-24 16:44
459 查看
环境 JDK8.0 + Spring4.2.3 + Tomcat8.0
websocket是html5的特性之一,现有主流的浏览器都已经支持websocket,websocket也成了为Java EE7的规范之一。目前jetty、tomcat等主流的应用服务器都支持websocket协议。tomcat自7以上支持websocket协议,tomcat7和tomcat8还是有些不同。tomcat8对websocket有了更好的支持和样例,在webapp\examples下面有websocket的样例,可以直接运行,java文件在example的WEB-INF目录下,和class放在一起,非常方便。
spring4也增加了对websocket的API支持,目前有些容器对JSR-356规范还未实现,且不同版本的容器实现方式也有不同,使用spring提供的API可以做到对websocket的开发统一。
一. JAVA API for websocket JSR-356
1. 非常简单,服务器段只需要使用@ServerEndpoint标识就可以,具体使用方法:
在需要设置为websocket服务的类上面添加@ServerEndpoint(value = 'abcd'),实现对应的方法即可。
2. 在客户端界面使用
当然复杂点也可以判断浏览器是否支持websocket之类的,可以借鉴tomcat8里面的样例。
3. 所用到的包
如果只使用JAVA API,还需要导入tomcat下面的websocket-api.jar,这比较以来与tomcat的实现,而且直接导入还不行,直接导入tomcat下面的websocket-api.jar,部署运行的话,一直报错。Error during WebSocket handshake : Unexpected response code : 404。据说这是因为jar包冲突的原因导致。
解决方法:删除原有项目中的java ee7.jar包,将tomcat里面的websocket-api.jar包单独复制到一个目录里面,起名tomcat-websocket,然后在项目上右键->properties->Java Build Path -> Libraries -> Add Library -> User Library -> User Libraries -> New -> User library name 输入tomcat-websocket,打勾下面的system library
-> ok -> 选中刚才加入的tomcat-websocket,点击Add External JARs,加入刚才复制websocket-api.jar的目录tomcat-websocket -> 勾选建好的User library -> Finish。
建好后再导入就出现了javax-websocket的包,并且可以部署到tomcat8中进行运行。
二、Spring API for WebSocket
用java的api是不是比较麻烦,但是用Spring就不用处理上述过程了。Spring从4起开始推出WebSocket API ,现在使用的是Spring4.2.3,算是较新的版本。当然上述JAVA API for websocket‘也可以在Spring工程中使用,但是还是需要注意和应用服务器jar包冲突的问题。
1. WebSocketConfig
Spring通过一个配置类来注册并且管理websoceket服务
2. Interceptor,顾名思义,拦截器,实现HandshakeInterceptor接口,处理websocket握手开始和握手结束的事件。
3. RealSocketHandler,实现WebSocketHandler接口,处理具体的websocket信息交互内容。
websocket是html5的特性之一,现有主流的浏览器都已经支持websocket,websocket也成了为Java EE7的规范之一。目前jetty、tomcat等主流的应用服务器都支持websocket协议。tomcat自7以上支持websocket协议,tomcat7和tomcat8还是有些不同。tomcat8对websocket有了更好的支持和样例,在webapp\examples下面有websocket的样例,可以直接运行,java文件在example的WEB-INF目录下,和class放在一起,非常方便。
spring4也增加了对websocket的API支持,目前有些容器对JSR-356规范还未实现,且不同版本的容器实现方式也有不同,使用spring提供的API可以做到对websocket的开发统一。
一. JAVA API for websocket JSR-356
1. 非常简单,服务器段只需要使用@ServerEndpoint标识就可以,具体使用方法:
在需要设置为websocket服务的类上面添加@ServerEndpoint(value = 'abcd'),实现对应的方法即可。
import javax.websocket.OnClose; import javax.websocket.OnOpen; import javax.websocket.server.ServerEndpoint; import org.springframework.context.annotation.Configuration; @Configuration @ServerEndpoint(value = "/abcd") public class RealEndpoint { @OnOpen public void onOpen() { System.out.println("Client connected"); } @OnClose public void onClose() { System.out.println("Connection closed"); } }
2. 在客户端界面使用
var host = 'ws://' + window.location.host + '/THSCADAWEB/collectionList'; var webSocket; if ('WebSocket' in window) { webSocket = new WebSocket(host); } else if ('MozWebSocket' in window) { webSocket = new MozWebSocket(host); } else { Ext.Msg.alert('提示', '当前浏览器不支持websocket,请更换浏览器'); return; } webSocket.onerror = function(event) { console.log('error'); }; webSocket.onopen = function(event) { console.log('open'); }; webSocket.onmessage = function(event) { var data = event.data; console.log('onmessage'); var address = data.split(';')[0]; var status = data.split(';')[1]; var collectionStore = Ext.getCmp('deployCollectionGrid').getStore(); var rec = collectionStore.findExact('remote_address', address); if(rec > -1){ unit = collectionStore.getAt(rec).set('collection_connStatus',status); }else{ collectionStore.add({ 'remote_address' : address, 'collection_connStatus' : status }); } };
当然复杂点也可以判断浏览器是否支持websocket之类的,可以借鉴tomcat8里面的样例。
3. 所用到的包
如果只使用JAVA API,还需要导入tomcat下面的websocket-api.jar,这比较以来与tomcat的实现,而且直接导入还不行,直接导入tomcat下面的websocket-api.jar,部署运行的话,一直报错。Error during WebSocket handshake : Unexpected response code : 404。据说这是因为jar包冲突的原因导致。
解决方法:删除原有项目中的java ee7.jar包,将tomcat里面的websocket-api.jar包单独复制到一个目录里面,起名tomcat-websocket,然后在项目上右键->properties->Java Build Path -> Libraries -> Add Library -> User Library -> User Libraries -> New -> User library name 输入tomcat-websocket,打勾下面的system library
-> ok -> 选中刚才加入的tomcat-websocket,点击Add External JARs,加入刚才复制websocket-api.jar的目录tomcat-websocket -> 勾选建好的User library -> Finish。
建好后再导入就出现了javax-websocket的包,并且可以部署到tomcat8中进行运行。
二、Spring API for WebSocket
用java的api是不是比较麻烦,但是用Spring就不用处理上述过程了。Spring从4起开始推出WebSocket API ,现在使用的是Spring4.2.3,算是较新的版本。当然上述JAVA API for websocket‘也可以在Spring工程中使用,但是还是需要注意和应用服务器jar包冲突的问题。
1. WebSocketConfig
Spring通过一个配置类来注册并且管理websoceket服务
package com.th.scada.websocket; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import com.th.scada.real.controller.RealSocketHandler; /** * Spring框架WebSocket配置管理类 * @author guoyankun */ @Configuration @EnableWebMvc @EnableWebSocket public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer { /** * 注册websocket */ @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { // 注册多个websocket服务,addHandler第一个参数是websocket的具体业务处理类,第二个参数collectionList相当于endpoint registry.addHandler(RealSocketHandler(), "/collectionList").addInterceptors(new WebSocketHandshakeInterceptor()); // 可以注册多个websocket的endpoint } @Bean public WebSocketHandler RealSocketHandler() { return new RealSocketHandler(); } }
2. Interceptor,顾名思义,拦截器,实现HandshakeInterceptor接口,处理websocket握手开始和握手结束的事件。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.HandshakeInterceptor; import com.th.scada.util.Constants; public class WebSocketHandshakeInterceptor implements HandshakeInterceptor { private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class); @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object > attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest.getServletRequest().getSession(false); if (session != null) { //使用userName区分WebSocketHandler,以便定向发送消息 String userName = (String) session.getAttribute(Constants.SESSION_USERNAME); if(userName != null){ attributes.put(Constants.WEBSOCKET_USERNAME,userName); } } } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } }
3. RealSocketHandler,实现WebSocketHandler接口,处理具体的websocket信息交互内容。
import java.io.IOException; import java.util.ArrayList; import org.apache.log4j.Logger; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; public class RealSocketHandler implements WebSocketHandler { private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>(); private static Logger logger = Logger.getLogger(RealSocketHandler.class); @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus arg1) throws Exception { logger.debug("websocket connection closed"); System.out.println("afterConnectionClosed"); users.remove(session); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug("connect to the websocket succcess ... ..."); System.out.println("afterConnectionEstablished"); users.add(session); } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> arg1) throws Exception { System.out.println("handleMessage"); } @Override public void handleTransportError(WebSocketSession session, Throwable arg1) throws Exception { System.out.println("handleTransportError"); logger.debug("websocket connection closed"); users.remove(session); } @Override public boolean supportsPartialMessages() { return false; } /** * 给所有在线用户发送消息 * * @param message * */ public void sendMessageToUsers(TextMessage message) { for (WebSocketSession user : users) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } /** * 给某个用户发送消息 * * @param userName * @param message */ public void sendMessageToUser(String userName, TextMessage message) { for (WebSocketSession user : users) { if (user.getAttributes().get("websocket_username").equals(userName)) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } break; } } } }4. 使用Spring API for WebSocket,就不需要tomcat里面的websocket-api.jar包了,取而代之的是spring-websocket-4.2.3.RELEASE.jar。
相关文章推荐
- TOMCAT 7优化前及优化后的性能对比
- Tomcat启动报Error listenerStart错误
- tomcat执行startup报错!
- apr-tomcat-native安装
- tomcat中仅启动指定的项目,不启动其它项目
- tomcat-部署
- tomcat如何配置环境变量
- Win7+花生壳6.0+tomcat打做自己的web服务器(搭建自己的网站)(参考)
- qingshow “不积跬步无以至千里,不积小流无以成江海”。--荀子《劝学篇》 用tomcat+花生壳搭建自己的web服务器+域名(参考)
- Target runtime Apache Tomcat v8.0 is not defined
- solr3.5整合tomcat并配置中文分词
- tomcat的安装
- 当装了两个tomcat后,如何修改tomcat端口
- 添加库时在server runtime中没有tomcat选项
- Myeclipse与tomcatplugin实现应用布署
- 实战:阿里云服务器CentOS6.5下Tomcat网马WAR入侵解决
- Win8系统 Tomcat4.1双击bin下startup.bat启动报错\"wins找不到文件-Dsun.io.use.canonCahches=false\"解决方案
- CentOS下Apache+Tomcat整合
- Eclipse安装tomcat插件详解
- JRebel + Tomcat + eclipse 实现热部署