springMvc中websokect的应用实例

来源:互联网 发布:淘宝产品修图 编辑:程序博客网 时间:2024/05/01 11:55

1.需要用到的jar包

spring-websocket-4.0.5.RELEASE.jar

2.配置config文件:

spring-websocket.xml

内容:

<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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        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">
        
        <bean id="websocket" class="com.xiangya.web.filter.WebSocketHandler"/>

<websocket:handlers>
    <websocket:mapping path="/websocket" handler="websocket"/>
    <websocket:handshake-interceptors>
    <bean class="com.xiangya.web.filter.HandShakeInterceptor"/>
    </websocket:handshake-interceptors>
</websocket:handlers>
        <websocket:handlers>
    <websocket:mapping path="/socket" handler="websocket"/>
    <websocket:handshake-interceptors>
    <bean class="com.xiangya.web.filter.HandShakeInterceptor"/>
    </websocket:handshake-interceptors>
    <websocket:sockjs/>
</websocket:handlers>
 </beans>

3.配置web.xml

在web.xml中添加

  <servlet>  
        <servlet-name>websocket</servlet-name>  
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
         <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:/config/spring-websocket.xml</param-value>
    </init-param>
     <async-supported>true</async-supported>
    </servlet>  
    <servlet-mapping>  
        <servlet-name>websocket</servlet-name>  
        <url-pattern>/websocket</url-pattern>
        <url-pattern>/socketjs/*</url-pattern>    
    </servlet-mapping>  

另外在<filter></filter>中添加  <async-supported>true</async-supported>

4.创建握手处理的类,和消息处理的类

握手处理的类:

  public class HandShakeInterceptor extends HttpSessionHandshakeInterceptor {
@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);
           // 标记用户
           Integer id = (Integer) session.getAttribute("id");
           if(id!=null){
               attributes.put("id", id);
           }else{
               return false;
           }
       }
       return true;
}


@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
//握手后
super.afterHandshake(request, response, wsHandler, ex);

}
}

消息处理的类

public class WebSocketHandler extends TextWebSocketHandler {
public static  Map<Integer,WebSocketSession> DOCTORONLINE=new HashMap<Integer,WebSocketSession>();
@Override
protected void handleTextMessage(WebSocketSession session,TextMessage message) throws Exception {
super.handleTextMessage(session, message);
Integer userId=null;
if(message.getPayload()!=null&&message.getPayload()!=""){
userId=Integer.parseInt(message.getPayload());
}
if(DOCTORONLINE.get(userId)==null){
DOCTORONLINE.put(userId, session);
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("Websocket:" + session.getId() + "已经关闭");
        Iterator<Entry<Integer, WebSocketSession>> it = DOCTORONLINE.entrySet().iterator();
        // 移除Socket会话
        while (it.hasNext()) {
            Entry<Integer, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(session.getId())) {
            DOCTORONLINE.remove(entry.getKey());
                System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                break;
            }
        }
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// TODO Auto-generated method stub
super.afterConnectionEstablished(session);
Integer id=(Integer)session.getAttributes().get("id");
//将消息推送给这个专家
if(DOCTORONLINE.get(id)==null){
DOCTORONLINE.put(id, session);
}

}
@Override
protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
// TODO Auto-generated method stub
super.handlePongMessage(session, message);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// TODO Auto-generated method stub
super.handleTransportError(session, exception);
//信息传输时出错的处理
if (session.isOpen()) {
           session.close();
       }
       Iterator<Entry<Integer, WebSocketSession>> it = DOCTORONLINE.entrySet().iterator();
       // 移除Socket会话
       while (it.hasNext()) {
           Entry<Integer, WebSocketSession> entry = it.next();
           if (entry.getValue().getId().equals(session.getId())) {
            DOCTORONLINE.remove(entry.getKey());
               System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
               break;
           }
       }
}
@Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
//发送信息给专家
public void sendMessageToDoctor(Integer doctorId, Integer id) throws Exception{
//消息编号必须存在
if(id!=null&&id>=0){
//找到指定的专家doctorId
WebSocketSession session=DOCTORONLINE.get(doctorId);
if(session!=null&&session.isOpen()){
TextMessage textMessage=new TextMessage(String.valueOf(id));
//将消息推送给这个专家
session.sendMessage(textMessage);
}
}
  }
}

5.controller中

将id 保存在session中


在index.jsp页面 websocket的使用

 var connectCount=0;
var socketFlg=0;

function connect() {  
if (window.location.protocol == 'http:') {
                  url = 'ws://' + window.location.host+urlPath;
              } else {
                  url = 'wss://' + window.location.host + urlPath;
              }
if ('WebSocket' in window) {
  ws = new WebSocket(url);
           } else if ('MozWebSocket' in window) {
            ws  = new MozWebSocket(url);
           } else {
            ws  = new SockJS("http://"+window.location.host+urlPath1);
socketFlg=1;
           }
            ws.onopen = function () {
if(socketFlg==1){
ws.send(userId);
}
            };
            ws.onmessage = function (event) {
省略无关代码
            };
            ws.onclose = function (event) {
socketFlg=0;
            if(connectCount<20){
            setTimeout("connect()",5000);
            connectCount++;
            }else{
            window.location.href="index.html";
            }
            };
ws.onerror = function (event) {
window.location.href="index.html";
            };
 }  
var ws = null;
         var url = "";
         var urlPath="";
         var urlPath1="";
         var connectCount=0;
var socketFlg=0;
         if(window.location.pathname.indexOf("xiangya")>-1){
        urlPath="/xiangya"+"/websocket";
        urlPath1="/xiangya"+"/socketjs/socket";
         }else{
        urlPath="/websocket";
        urlPath1="/socketjs/socket";
         }
connect();





6.补充说明websokect的原理

http://blog.csdn.net/yinqingwang/article/details/52565133

http://blog.csdn.net/frank_good/article/details/50856585


原创粉丝点击