WebSocket+spring 예제 demo 자세히 보기(sockJs 라이브러리 사용)

17341 단어 springWebSocket
1. 소개
차세대 웹 표준으로서 HTML5는 많은 사람들의 주목을 끄는 새로운 기능을 가지고 있다. 예를 들어 Canvas, 로컬 저장소, 멀티미디어 프로그래밍 인터페이스, WebSocket 등이다.이 중'웹의 TCP'라고 불리는 웹소켓은 특히 개발자들의 주의를 끈다.WebSocket의 등장으로 브라우저가 Socket에 대한 지원을 제공할 수 있게 되었고 브라우저와 서버 사이에 TCP 연결을 기반으로 하는 양방향 채널을 제공했다.웹 개발자는 웹 소켓을 이용하여 실시간 웹 응용 프로그램을 구축하는 데 매우 편리하게 사용할 수 있고 개발자의 손에는 이때부터 또 하나의 신병기가 생겼다.
웹 응용 프로그램의 정보 상호작용 과정은 일반적으로 클라이언트가 브라우저를 통해 요청을 보내고 서버 측이 요청을 접수하고 심사한 후에 처리하고 결과를 클라이언트에게 되돌려 주는 것이다. 그리고 클라이언트 브라우저는 정보를 나타낸다. 이런 메커니즘은 정보 변화가 특별히 빈번한 응용에 대해 안전하지 않다. 그러나 실시간 요구가 비교적 높은 응용에 있어 예를 들어 온라인 게임, 온라인 증권,장치 모니터링, 뉴스 온라인 방송, RSS 구독 푸시 등, 클라이언트 브라우저가 이러한 정보를 보여줄 준비를 할 때 이러한 정보는 서버에서 이미 유행이 지났을 수 있다.
따라서 클라이언트와 서버 측의 정보 동기화를 유지하는 것은 실시간 웹 응용의 관건적인 요소로 웹 개발자에게도 어려운 문제이다.WebSocket 규범이 나오기 전에 개발자들이 이러한 실시간 웹 응용을 실현하려면 절충된 방안을 채택해야 한다. 그 중에서 가장 자주 사용하는 것이 바로 폴링(Polling)과 Comet 기술이다. Comet 기술은 사실상 폴링 기술의 개선이고 두 가지 실제 방식으로 세분화할 수 있다. 하나는 긴 폴링 메커니즘이고 하나는 흐름 기술이라고 한다.
Html5 WebSocket이 디자인한 목적은 윤문과Comet 기술을 대체하여 클라이언트 브라우저가 C/S 구조의 데스크톱 시스템과 같은 실시간 통신 능력을 갖추도록 하는 것이다.브라우저는 JavaScript를 통해 서버에 WebSocket 연결을 요청합니다. 연결이 이루어지면 클라이언트와 서버 측은 TCP 연결을 통해 직접 데이터를 교환할 수 있습니다.WebSocket 연결은 본질적으로 하나의 TCP 연결이기 때문에 데이터 전송의 안정성과 데이터 전송량의 크기에 있어 윤문과Comet 기술과 비교하면 매우 큰 성능 우위를 가진다.
그러나 웹 socket이 브라우저에 대한 요구가 비교적 높다는 것을 감안하여 이 문제를 해결하기 위해 sockJS를 출시했습니다. SockJS는 자바스크립트 라이브러리로 크로스 브라우저javascript의 API를 제공하고 낮은 지연, 완전 이중화된 브라우저와 웹 서버 간의 통신 채널을 만들었습니다.
2. 관련 환경 요구 사항
Spring4.0.6(4.0+ 선택 가능), tomcat7.0.55 버전, JDK1.7
3. 구체적인 코드
(아래 코드 직접 측정 가능!)
(1)web.xml:

<?xmlversionxmlversion="1.0"encoding="UTF-8"?> 
<web-app version="3.1" 
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> 
 <description> WebSocket </description> 
 <distributable/> 
 <filter> 
  <filter-name>encodingFilter</filter-name> 
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
  <async-supported>true</async-supported> 
  <init-param> 
   <param-name>encoding</param-name> 
   <param-value>UTF-8</param-value> 
  </init-param> 
  <init-param> 
   <param-name>forceEncoding</param-name> 
   <param-value>true</param-value> 
  </init-param>  
 </filter> 
 <filter-mapping> 
  <filter-name>encodingFilter</filter-name> 
  <url-pattern>/*</url-pattern> 
 </filter-mapping> 
 <listener> 
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
 </listener> 
 <!-- Spring  Introspector  --> 
 <listener> 
  <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> 
 </listener> 
 <servlet> 
  <servlet-name>dispatcher</servlet-name> 
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  <init-param> 
  <param-name>contextConfigLocation</param-name> 
  <param-value>classpath:dispatcher-servlet.xml</param-value> 
  </init-param> 
  <load-on-startup>1</load-on-startup> 
  <async-supported>true</async-supported> 
 </servlet> 
 <servlet-mapping> 
  <servlet-name>dispatcher</servlet-name> 
  <url-pattern>/</url-pattern> 
 </servlet-mapping> 
 <session-config> 
  <session-timeout> 
   30 
  </session-timeout> 
 </session-config> 
 <welcome-file-list> 
  <welcome-file>testSocket.jsp</welcome-file> 
 </welcome-file-list> 
</web-app> 

(2) dispatcher-servlet.xml

<?xmlversionxmlversion="1.0"encoding="UTF-8"?> 
<beans:beansxmlnsbeans:beansxmlns="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
 <annotation-driven/> 
 <!--   --> 
 <context:component-scanbase-packagecontext:component-scanbase-package="zyy.sockjs.config"></context:component-scan> 
</beans:beans> 

(3)HandshakeInterceptor.java

package zyy.sockjs.config; 
import java.util.Map; 
import org.springframework.http.server.ServerHttpRequest; 
import org.springframework.http.server.ServerHttpResponse; 
import org.springframework.stereotype.Component; 
import org.springframework.web.socket.WebSocketHandler; 
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; 
 
@Component 
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); 
} 
} 

(4)InfoSocketEndPoint.Java

package zyy.sockjs.config; 
import org.springframework.stereotype.Component; 
import org.springframework.web.socket.TextMessage; 
import org.springframework.web.socket.WebSocketSession; 
import org.springframework.web.socket.handler.TextWebSocketHandler; 
 
@Component 
public class InfoSocketEndPoint extends TextWebSocketHandler { 
public InfoSocketEndPoint() { 
} 
 
@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)SystemWebSocketHandler.java

package zyy.sockjs.config; 
import org.springframework.stereotype.Component; 
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; 
/** 
* 
* @author dayu 
*/ 
 
@Component 
public class SystemWebSocketHandler implements WebSocketHandler { 
 @Override 
 public void afterConnectionEstablished(WebSocketSession session) throws Exception { 
  System.out.println("connect to the websocket success......"); 
  session.sendMessage(new TextMessage("Server:connected OK!")); 
 } 
 
 @Override 
 public void handleMessage(WebSocketSession wss, WebSocketMessage<?> wsm) throws Exception { 
  TextMessage returnMessage = new TextMessage(wsm.getPayload() 
  + " received at server"); 
  wss.sendMessage(returnMessage); 
 } 
 
 @Override 
 public void handleTransportError(WebSocketSession wss, Throwable thrwbl) throws Exception { 
  if(wss.isOpen()){ 
   wss.close(); 
  } 
  System.out.println("websocket connection closed......"); 
 } 
 
 @Override 
 public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception { 
  System.out.println("websocket connection closed......"); 
 } 
 
 @Override 
 public boolean supportsPartialMessages() { 
  return false; 
 } 
} 

(6)WebSocketConfig.java

package zyy.sockjs.config; 
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; 
 
@Configuration 
@EnableWebMvc 
@EnableWebSocket 
public class WebSocketConfig extends WebMvcConfigurerAdapter implements 
  WebSocketConfigurer { 
 public WebSocketConfig() { 
 } 
 
 @Override 
 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 
  registry.addHandler(systemWebSocketHandler(), "/websck").addInterceptors(new HandshakeInterceptor()); 
  System.out.println("registed!"); 
  registry.addHandler(systemWebSocketHandler(), "/sockjs/websck/info").addInterceptors(new HandshakeInterceptor()) 
    .withSockJS(); 
 } 
 
 @Bean 
 public WebSocketHandler systemWebSocketHandler() { 
  return new SystemWebSocketHandler(); 
 } 
} 

(7)testSocket.jsp

<%@ page language="java"contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> 
<!DOCTYPE htmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type"content="text/html; charset=ISO-8859-1"> 
<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:#33333333; 
   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() { 
   if (!url) {    
   log('Select whether to use W3C WebSocket or SockJS');    
    return; 
   } 
   //ws = (url.indexOf('sockjs') != -1) ?new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url); 
   if ('WebSocket'in window) { 
    ws= new WebSocket("ws://localhost:8080/SpringSocketJs/websck"); 
   }else { 
    ws = new SockJS("http://localhost:8080/SpringSocketJs/sockjs/websck/info"); 
   } 
   //websocket = new SockJS("http://localhost:8084/SpringWebSocketPush/sockjs/websck"); 
   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) { 
   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 supportJavascript!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('/SpringSocketJs/websocket');"> 
   <label for="radio1">W3C WebSocket</label> 
  <br> 
  <input id="radio2"type="radio"name="group1"onclick="updateUrl('/SpringSocketJs/sockjs/websocket');"> 
   <label for="radio2">SockJS</label> 
  <div id="sockJsTransportSelect" style="visibility:hidden;"> 
   SockJS transport: 
   <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> 
이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.

좋은 웹페이지 즐겨찾기