springMVC+spring+MyBatis+websocket技术整合

来源:互联网 发布:什么手机壁纸软件好 编辑:程序博客网 时间:2024/05/05 18:08
websocket是目前唯一真正实现全双工通信的服务器向客户端推的互联网技术,与长连接和轮询技术相比,websocket的优越性不言自明,长连接的连接资源(线程资源)随着连接数量的增多,必会耗尽,客户端轮询会给服务器造成很大的压力,而websocket是在物理层非网络层建立一条客户端至服务器的长连接,以此来保证服务器向客户端的即时推送,既不耗费线程资源,又不会不断向服务器轮询请求。

下面言归正传,讲一讲SSM(springMVC+spring+MyBatis)框架中集成websocket技术的曲折蛋疼直至成功喜悦之路。

1 在maven的pom.xml中加入websocket所依赖的jar包,什么,你不知道maven,快去度之或者查看撸主关于maven的博文恶补一下,spring-websocket所依赖的jar包有以下几个:

    <dependency>          <groupId>javax.servlet</groupId>          <artifactId>javax.servlet-api</artifactId>          <version>3.1.0</version>      </dependency>      <dependency>          <groupId>com.fasterxml.jackson.core</groupId>          <artifactId>jackson-core</artifactId>          <version>2.3.0</version>      </dependency>      <dependency>          <groupId>com.fasterxml.jackson.core</groupId>          <artifactId>jackson-databind</artifactId>          <version>2.3.0</version>      </dependency>      <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-websocket</artifactId>         <version>4.0.1.RELEASE</version>      </dependency>      <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-messaging</artifactId>         <version>4.0.1.RELEASE</version>      </dependency>  

2 更新web.xml中namespace.xsd的版本

<beans xmlns="http://www.springframework.org/schema/beans"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xmlns:websocket="http://www.springframework.org/schema/websocket"         xsi:schemaLocation="          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">

3 更新spring框架的jar包至4.0以上(spring-core, spring-context, spring-web and spring-webmvc)

<dependency>  <span style="white-space:pre">    </span><groupId>org.springframework</groupId>      <artifactId>spring-core</artifactId>      <version>${spring.version}</version>  </dependency>  <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-web</artifactId>      <version>${spring.version}</version>  </dependency>  <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-webmvc</artifactId>      <version>${spring.version}</version>  </dependency>  <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-context-support</artifactId>      <version>${spring.version}</version>  </dependency>

4 创建websocket处理类

package com.up.websocket.handler;    import org.springframework.web.socket.TextMessage;  import org.springframework.web.socket.WebSocketSession;  import org.springframework.web.socket.handler.TextWebSocketHandler;    public class WebsocketEndPoint extends TextWebSocketHandler {        @Override      protected void handleTextMessage(WebSocketSession session,              TextMessage message) throws Exception {          super.handleTextMessage(session, message);          TextMessage returnMessage = new TextMessage(message.getPayload()+" received at server");          session.sendMessage(returnMessage);      }  }

5 创建握手(handshake)接口

package com.up.websocket;    import java.util.Map;    import org.springframework.http.server.ServerHttpRequest;  import org.springframework.http.server.ServerHttpResponse;  import org.springframework.web.socket.WebSocketHandler;  import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;    public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{        @Override      public boolean beforeHandshake(ServerHttpRequest request,              ServerHttpResponse response, WebSocketHandler wsHandler,              Map<String, Object> attributes) throws Exception {          System.out.println("Before Handshake");          return super.beforeHandshake(request, response, wsHandler, attributes);      }        @Override      public void afterHandshake(ServerHttpRequest request,              ServerHttpResponse response, WebSocketHandler wsHandler,              Exception ex) {          System.out.println("After Handshake");          super.afterHandshake(request, response, wsHandler, ex);      }    }

6 处理类和握手协议的spring配置(applicationContext.xml文件)

<bean id="websocket" class="com.up.websocket.handler.WebsocketEndPoint"/>    <websocket:handlers>      <websocket:mapping path="/websocket" handler="websocket"/>      <websocket:handshake-interceptors>      <bean class="com.up.websocket.HandshakeInterceptor"/>      </websocket:handshake-interceptors>  </websocket:handlers>

7 客户端页面

<!DOCTYPE html>  <html>  <head>      <title>WebSocket/SockJS Echo Sample (Adapted from Tomcat's echo sample)</title>      <style type="text/css">          #connect-container {              float: left;              width: 400px          }            #connect-container div {              padding: 5px;          }            #console-container {              float: left;              margin-left: 15px;              width: 400px;          }            #console {              border: 1px solid #CCCCCC;              border-right-color: #999999;              border-bottom-color: #999999;              height: 170px;              overflow-y: scroll;              padding: 5px;              width: 100%;          }            #console p {              padding: 0;              margin: 0;          }      </style>        <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>        <script type="text/javascript">          var ws = null;          var url = null;          var transports = [];            function setConnected(connected) {              document.getElementById('connect').disabled = connected;              document.getElementById('disconnect').disabled = !connected;              document.getElementById('echo').disabled = !connected;          }            function connect() {              alert("url:"+url);              if (!url) {                  alert('Select whether to use W3C WebSocket or SockJS');                  return;              }                ws = (url.indexOf('sockjs') != -1) ?                   new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url);                ws.onopen = function () {                  setConnected(true);                  log('Info: connection opened.');              };              ws.onmessage = function (event) {                  log('Received: ' + event.data);              };              ws.onclose = function (event) {                  setConnected(false);                  log('Info: connection closed.');                  log(event);              };          }            function disconnect() {              if (ws != null) {                  ws.close();                  ws = null;              }              setConnected(false);          }            function echo() {              if (ws != null) {                  var message = document.getElementById('message').value;                  log('Sent: ' + message);                  ws.send(message);              } else {                  alert('connection not established, please connect.');              }          }            function updateUrl(urlPath) {              if (urlPath.indexOf('sockjs') != -1) {                  url = urlPath;                  document.getElementById('sockJsTransportSelect').style.visibility = 'visible';              }              else {                if (window.location.protocol == 'http:') {                    url = 'ws://' + window.location.host + urlPath;                } else {                    url = 'wss://' + window.location.host + urlPath;                }                document.getElementById('sockJsTransportSelect').style.visibility = 'hidden';              }          }            function updateTransport(transport) {              alert(transport);            transports = (transport == 'all') ?  [] : [transport];          }                    function log(message) {              var console = document.getElementById('console');              var p = document.createElement('p');              p.style.wordWrap = 'break-word';              p.appendChild(document.createTextNode(message));              console.appendChild(p);              while (console.childNodes.length > 25) {                  console.removeChild(console.firstChild);              }              console.scrollTop = console.scrollHeight;          }      </script>  </head>  <body>  <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets       rely on Javascript being enabled. Please enable      Javascript and reload this page!</h2></noscript>  <div>      <div id="connect-container">          <input id="radio1" type="radio" name="group1" onclick="updateUrl(''/spring-websocket-uptest/websocket');">              <label for="radio1">W3C WebSocket</label>          <br>          <input id="radio2" type="radio" name="group1" onclick="updateUrl('/spring-websocket-uptest/websocket');">              <label for="radio2">SockJS</label>          <div id="sockJsTransportSelect" style="visibility:hidden;">              <span>SockJS transport:</span>              <select onchange="updateTransport(this.value)">                <option value="all">all</option>                <option value="websocket">websocket</option>                <option value="xhr-polling">xhr-polling</option>                <option value="jsonp-polling">jsonp-polling</option>                <option value="xhr-streaming">xhr-streaming</option>                <option value="iframe-eventsource">iframe-eventsource</option>                <option value="iframe-htmlfile">iframe-htmlfile</option>              </select>          </div>          <div>              <button id="connect" onclick="connect();">Connect</button>              <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>          </div>          <div>              <textarea id="message" style="width: 350px">Here is a message!</textarea>          </div>          <div>              <button id="echo" onclick="echo();" disabled="disabled">Echo message</button>          </div>      </div>      <div id="console-container">          <div id="console"></div>      </div>  </div>  </body>  </html>

7 按照以上步骤搭建,根据个人开发环境不同,可能会出现各种问题

org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server

    严重: Servlet.service() for servlet [SpringMVC] in context with path [/ZHDM] threw exception [Request processing failed; nested exception is org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://125.221.225.118:8080/ZHDM/websocket; nested exception is java.lang.ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server.ServerContainer] with root cause      java.lang.ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server.ServerContainer          at org.springframework.web.socket.server.standard.AbstractStandardUpgradeStrategy.getContainer(AbstractStandardUpgradeStrategy.java:76)          at org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy.getContainer(TomcatRequestUpgradeStrategy.java:85)          at org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy.getContainer(TomcatRequestUpgradeStrategy.java:47)          at org.springframework.web.socket.server.standard.AbstractStandardUpgradeStrategy.getSupportedExtensions(AbstractStandardUpgradeStrategy.java:68)          at org.springframework.web.socket.server.support.DefaultHandshakeHandler.doHandshake(DefaultHandshakeHandler.java:206)          at org.springframework.web.socket.server.support.WebSocketHttpRequestHandler.handleRequest(WebSocketHttpRequestHandler.java:120)          at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)          at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)          at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)          at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)          at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)          at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)          at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)          at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:301)          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)          at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)          at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)          at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)          at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)          at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)          at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)          at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)          at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)          at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)          at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)          at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)          at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015)          at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652)          at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)          at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2451)          at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2440)          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)          at java.lang.Thread.run(Thread.java:744)  

解决方案:
出现这个问题的原因是,apache的websocket包和javax-servlet包冲突了,找到Apache Tomcat的webApp目录,打开你部署的项目文件夹,依次打开WEB-INF/lib,找到javaee-api-7.0.jar,删除,再重新启动项目。

原博有示例代码下载:http://download.csdn.net/detail/up19910522/9192447

转自【http://blog.csdn.net/gisredevelopment/article/details/38392629】









0 1
原创粉丝点击