SpringMVC整合webScoket总结

运行环境tomcat7以上

1.创建@ServerEndpoint注解类

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value="/echo",configurator=GetHttpSessionConfigurator.class)
public class EndPointServer {

    public static  List<EndPointServer>  sessionList= new ArrayList<EndPointServer>();
    public Session  session ;

     @OnOpen
     public void onOpen(Session session,EndpointConfig config) throws IOException {
         //以下代码省略...
        System.out.println("用户"+session.getId()+"链接");
        this.session = session;
        sessionList.add(this);
        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        httpSession.setAttribute("scoketSessionId", session.getId()); 
    }

     @OnMessage
     public void onMessage(Session session,String message) {
     }

     @OnError
     public void onError(Throwable t) {
         //以下代码省略...
         System.err.println("出错了");
     }

     @OnClose
     public void onClose(Session session, CloseReason reason) {
         //以下代码省略...
         sessionList.remove(this);
         System.out.println(session.getId()+"退出链接");
     } 


}

OnOpen、OnClose、OnError、OnMessage分别是前端发起链接、关闭链接、出错时、发送消息时的响应事件

configurator用于客户端建立长连接时可以获取httpsession,另外该动作还需要一个ServletRequest监听器和一个ServerEndpointConfig.Configurator子类,如果缺少则会出现httpsession空指针异常。

1)以下是ServletRequest监听器

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener
public class RequestListener implements  ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void requestInitialized(ServletRequestEvent arg0) {
         ((HttpServletRequest) arg0.getServletRequest()).getSession();

    }

}

另外web.xml配置监听器

<listener>
        <listener-class>包名路径.RequestListener</listener-class>
 </listener>

2)以下是ServerEndpointConfig.Configurator子类

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;


/**
 * scoket获取session
 * @author Administrator
 *
 */
public class GetHttpSessionConfigurator extends Configurator  {

    @Override
    public void modifyHandshake(ServerEndpointConfig sec,
            HandshakeRequest request, HandshakeResponse response) {
        // TODO Auto-generated method stub
         HttpSession httpSession=(HttpSession) request.getHttpSession();
         sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }



}

2.前端H5 发起webscoket长连接 js代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebScoketAPI</title>
</head>
<body>
<input type="text"  id='msg'/>
<button onclick='tosend()'>发送</button>
<button>退出</button>
<br>
<textarea id='mymess'></textarea>
</body>
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    var ws = new WebSocket("ws://localhost:8080/WeChatService/echo"); 
    ws.onmessage = function(evt){
         console.log(evt.data);
         $("#mymess").append(evt.data+"<br>");
     }; 

     ws.onerror = function(evt){
         console.log("WebSocketError");
     };
    /*
     ws.onopen = function(){
         ws.send(msg); 
     }; 

     ws.onclose = function(evt){
         console.log("WebSocketClosed");
     }; 
     */
     function tosend(){
         var msg=$("#msg").val();
         $("#mymess").append(msg+"<br>");
         ws.send(msg);
     }
</script>
</html>

主要创建WebSocket对象与服务器握手,握手后就会处于长链接状态,当服务器有推送的消息进来时,前端的onmessage方法就会触发

3.使用springMVC 访问URL对某个session推送消息

代码如下:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xjt.util.JsonUtil;

/**
 * 推送控制层
 * @author Administrator
 *
 */
@Controller
public class PushController {

     /**
      * 查询所有在线人员的sid
      * @param modelMap
      * @param session
      * @return
      */
     @ResponseBody
     @RequestMapping("getAllOnline")
     public String getAllOnline(ModelMap modelMap,HttpSession session){
         List<String> ids=new ArrayList<String>();
         for (EndPointServer endPointServer : EndPointServer.sessionList) {
             ids.add(endPointServer.session.getId());
         }
         modelMap.put("ids", ids);
         return JsonUtil.toJson(modelMap);
     }

     /**
      * 向用户发送消息
      * @param modelMap
      * @param session
      * @param sid
      * @param msg
      * @return
      */
     @ResponseBody
     @RequestMapping("toSendMsg")
     public String toSendMsg(ModelMap modelMap,HttpSession session,String sid,String msg){
         if (sid!=null&&sid.length()>0&&msg!=null&&msg.length()>0) {
             for (EndPointServer endPointServer : EndPointServer.sessionList) {
                 if (sid.equals(endPointServer.session.getId())) {
                     try {
                            endPointServer.session.getBasicRemote().sendText(msg);
                            modelMap.put("msg", 1);//发送成功
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            modelMap.put("msg", 0);//发送失败
                            e.printStackTrace();
                        }
                 }

            }
         }else {
             modelMap.put("msg", -1);//参数错误
        }

         return JsonUtil.toJson(modelMap);
     }


     /**
      * 广播发送消息
      * @param modelMap
      * @param session
      * @param msg
      * @return
      */
     @ResponseBody
     @RequestMapping("toBroadCastMsg")
     public String toBroadCastMsg(ModelMap modelMap,HttpSession session,String msg){
         if (msg!=null&&msg.length()>0) {
             for (EndPointServer endPointServer : EndPointServer.sessionList) {
                 try {
                        endPointServer.session.getBasicRemote().sendText(msg);
                        modelMap.put("msg", 1);//发送成功
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        modelMap.put("msg", 0);//发送失败
                        e.printStackTrace();
                    }           
            }
         }else {
             modelMap.put("msg", -1);//参数错误
        }

         return JsonUtil.toJson(modelMap);
     }

     /**
      * 查询所有sid
      * @param modelMap
      * @param session
      * @return
      */
     @ResponseBody
     @RequestMapping("getScoketSessionId")
     public String getScoketSessionId(ModelMap modelMap,HttpSession session){
         if (session.getAttribute("scoketSessionId")!=null) {
             modelMap.put("sid", session.getAttribute("scoketSessionId"));
         }else {
            modelMap.put("sid", "null");
         }
         return JsonUtil.toJson(modelMap);
     }


}

发送消息主要通过websocket.Session类的getBasicRemote().sendText()方法进行推送。

以上代码可以根据需要进行修改,比如分组等、sessionId与业务逻辑实际用户关联,因为可以获取用户的httpsession那么可以做的事情就很多了。

以上代码的汇总来自以下链接,感谢以下资料的提供者:

WebSocket实战
WebSocket之获取HttpSession
Websocket - httpSession returns null
尚学堂_高明鑫史上最易懂Websocket视频教程

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值