zoukankan      html  css  js  c++  java
  • Spring之WebSocket网页聊天以及服务器推送

    Spring之WebSocket网页聊天以及服务器推送

    https://blog.csdn.net/tanga842428/article/details/77140501

    原文地址:http://www.xdemo.org/spring-websocket-comet/

    Websocket简介 摘要自百度百科

    1. WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。

    2. 轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏览器需要不断的向服务器发出请求,然而HTTP request 的header是非常长的,里面包含的有用数据可能只是一个很小的值,这样会占用很多的带宽。

    3. 比较新的技术去做轮询的效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求

    4. 在 WebSocket API,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送

    5. 在此WebSocket 协议中,为我们实现即时服务带来了两大好处:

     5.1. Header

      互相沟通的Header是很小的-大概只有 2 Bytes

     5.2. Server Push

    浏览器支持情况

    Chrome 4+
    Firefox 4+
    Internet Explorer 10+
    Opera 10+
    Safari 5+

    服务器支持

    jetty 7.0.1+
    tomcat 7.0.27+
    Nginx 1.3.13+
    resin 4+

    API

    1.  
      var ws = new WebSocket(“ws://echo.websocket.org”);
    2.  
       
    3.  
      ws.onopen = function(){ws.send(“Test!”); };
    4.  
      //当有消息时,会自动调用此方法
    5.  
      ws.onmessage = function(evt){console.log(evt.data);ws.close();};
    6.  
       
    7.  
      ws.onclose = function(evt){console.log(“WebSocketClosed!”);};
    8.  
       
    9.  
      ws.onerror = function(evt){console.log(“WebSocketError!”);};


    Demo简介

    模拟了两个用户的对话,张三和李四,然后还有发送一个广播,即张三和李四都是可以接收到的,登录的时候分别选择张三和李四即可

    Demo效果

    Maven依赖

    1.  
      <dependency>
    2.  
      <groupId>com.fasterxml.jackson.core</groupId>
    3.  
      <artifactId>jackson-annotations</artifactId>
    4.  
      <version>2.3.0</version>
    5.  
      </dependency>
    6.  
      <dependency>
    7.  
      <groupId>com.fasterxml.jackson.core</groupId>
    8.  
      <artifactId>jackson-core</artifactId>
    9.  
      <version>2.3.1</version>
    10.  
      </dependency>
    11.  
      <dependency>
    12.  
      <groupId>com.fasterxml.jackson.core</groupId>
    13.  
      <artifactId>jackson-databind</artifactId>
    14.  
      <version>2.3.3</version>
    15.  
      </dependency>
    16.  
      <dependency>
    17.  
      <groupId>org.springframework</groupId>
    18.  
      <artifactId>spring-messaging</artifactId>
    19.  
      <version>4.0.5.RELEASE</version>
    20.  
      </dependency>
    21.  
      <dependency>
    22.  
      <groupId>org.springframework</groupId>
    23.  
      <artifactId>spring-websocket</artifactId>
    24.  
      <version>4.0.5.RELEASE</version>
    25.  
      </dependency>
    26.  
      <dependency>
    27.  
      <groupId>org.springframework</groupId>
    28.  
      <artifactId>spring-webmvc</artifactId>
    29.  
      <version>4.0.5.RELEASE</version>
    30.  
      </dependency>
    31.  
      <dependency>
    32.  
      <groupId>com.google.code.gson</groupId>
    33.  
      <artifactId>gson</artifactId>
    34.  
      <version>2.3.1</version>
    35.  
      </dependency>
    36.  
      <dependency>
    37.  
      <groupId>javax.servlet</groupId>
    38.  
      <artifactId>javax.servlet-api</artifactId>
    39.  
      <version>3.1.0</version>
    40.  
      <scope>provided</scope>
    41.  
      </dependency>
    42.  
      <dependency>
    43.  
      <groupId>junit</groupId>
    44.  
      <artifactId>junit</artifactId>
    45.  
      <version>3.8.1</version>
    46.  
      <scope>test</scope>
    47.  
      </dependency>


    Web.xml,spring-mvc.xml,User.java请查看附件

    WebSocket相关的类

    WebSocketConfig,配置WebSocket的处理器(MyWebSocketHandler)和拦截器(HandShake)

    1.  
      package org.xdemo.example.websocket.websocket;
    2.  
       
    3.  
      import javax.annotation.Resource;
    4.  
       
    5.  
      import org.springframework.stereotype.Component;
    6.  
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    7.  
      import org.springframework.web.socket.config.annotation.EnableWebSocket;
    8.  
      import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    9.  
      import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    10.  
       
    11.  
      /**
    12.  
      * WebScoket配置处理器
    13.  
      * @author Goofy
    14.  
      * @Date 2015年6月11日 下午1:15:09
    15.  
      */
    16.  
      @Component
    17.  
      @EnableWebSocket
    18.  
      public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
    19.  
       
    20.  
      @Resource
    21.  
      MyWebSocketHandler handler;
    22.  
       
    23.  
      public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    24.  
      registry.addHandler(handler, "/ws").addInterceptors(new HandShake());
    25.  
       
    26.  
      registry.addHandler(handler, "/ws/sockjs").addInterceptors(new HandShake()).withSockJS();
    27.  
      }
    28.  
       
    29.  
      }

    MyWebSocketHandler

    1.  
      package org.xdemo.example.websocket.websocket;
    2.  
       
    3.  
      import java.io.IOException;
    4.  
      import java.text.SimpleDateFormat;
    5.  
      import java.util.Date;
    6.  
      import java.util.HashMap;
    7.  
      import java.util.Iterator;
    8.  
      import java.util.Map;
    9.  
      import java.util.Map.Entry;
    10.  
       
    11.  
      import org.springframework.stereotype.Component;
    12.  
      import org.springframework.web.socket.CloseStatus;
    13.  
      import org.springframework.web.socket.TextMessage;
    14.  
      import org.springframework.web.socket.WebSocketHandler;
    15.  
      import org.springframework.web.socket.WebSocketMessage;
    16.  
      import org.springframework.web.socket.WebSocketSession;
    17.  
      import org.xdemo.example.websocket.entity.Message;
    18.  
       
    19.  
      import com.google.gson.Gson;
    20.  
      import com.google.gson.GsonBuilder;
    21.  
       
    22.  
      /**
    23.  
      * Socket处理器
    24.  
      *
    25.  
      * @author Goofy
    26.  
      * @Date 2015年6月11日 下午1:19:50
    27.  
      */
    28.  
      @Component
    29.  
      public class MyWebSocketHandler implements WebSocketHandler {
    30.  
      public static final Map<Long, WebSocketSession> userSocketSessionMap;
    31.  
       
    32.  
      static {
    33.  
      userSocketSessionMap = new HashMap<Long, WebSocketSession>();
    34.  
      }
    35.  
       
    36.  
      /**
    37.  
      * 建立连接后
    38.  
      */
    39.  
      public void afterConnectionEstablished(WebSocketSession session)
    40.  
      throws Exception {
    41.  
      Long uid = (Long) session.getAttributes().get("uid");
    42.  
      if (userSocketSessionMap.get(uid) == null) {
    43.  
      userSocketSessionMap.put(uid, session);
    44.  
      }
    45.  
      }
    46.  
       
    47.  
      /**
    48.  
      * 消息处理,在客户端通过Websocket API发送的消息会经过这里,然后进行相应的处理
    49.  
      */
    50.  
      public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
    51.  
      if(message.getPayloadLength()==0)return;
    52.  
      Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
    53.  
      msg.setDate(new Date());
    54.  
      sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
    55.  
      }
    56.  
       
    57.  
      /**
    58.  
      * 消息传输错误处理
    59.  
      */
    60.  
      public void handleTransportError(WebSocketSession session,
    61.  
      Throwable exception) throws Exception {
    62.  
      if (session.isOpen()) {
    63.  
      session.close();
    64.  
      }
    65.  
      Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap
    66.  
      .entrySet().iterator();
    67.  
      // 移除Socket会话
    68.  
      while (it.hasNext()) {
    69.  
      Entry<Long, WebSocketSession> entry = it.next();
    70.  
      if (entry.getValue().getId().equals(session.getId())) {
    71.  
      userSocketSessionMap.remove(entry.getKey());
    72.  
      System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
    73.  
      break;
    74.  
      }
    75.  
      }
    76.  
      }
    77.  
       
    78.  
      /**
    79.  
      * 关闭连接后
    80.  
      */
    81.  
      public void afterConnectionClosed(WebSocketSession session,
    82.  
      CloseStatus closeStatus) throws Exception {
    83.  
      System.out.println("Websocket:" + session.getId() + "已经关闭");
    84.  
      Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap
    85.  
      .entrySet().iterator();
    86.  
      // 移除Socket会话
    87.  
      while (it.hasNext()) {
    88.  
      Entry<Long, WebSocketSession> entry = it.next();
    89.  
      if (entry.getValue().getId().equals(session.getId())) {
    90.  
      userSocketSessionMap.remove(entry.getKey());
    91.  
      System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
    92.  
      break;
    93.  
      }
    94.  
      }
    95.  
      }
    96.  
       
    97.  
      public boolean supportsPartialMessages() {
    98.  
      return false;
    99.  
      }
    100.  
       
    101.  
      /**
    102.  
      * 给所有在线用户发送消息
    103.  
      *
    104.  
      * @param message
    105.  
      * @throws IOException
    106.  
      */
    107.  
      public void broadcast(final TextMessage message) throws IOException {
    108.  
      Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap
    109.  
      .entrySet().iterator();
    110.  
       
    111.  
      // 多线程群发
    112.  
      while (it.hasNext()) {
    113.  
       
    114.  
      final Entry<Long, WebSocketSession> entry = it.next();
    115.  
       
    116.  
      if (entry.getValue().isOpen()) {
    117.  
      // entry.getValue().sendMessage(message);
    118.  
      new Thread(new Runnable() {
    119.  
       
    120.  
      public void run() {
    121.  
      try {
    122.  
      if (entry.getValue().isOpen()) {
    123.  
      entry.getValue().sendMessage(message);
    124.  
      }
    125.  
      } catch (IOException e) {
    126.  
      e.printStackTrace();
    127.  
      }
    128.  
      }
    129.  
       
    130.  
      }).start();
    131.  
      }
    132.  
       
    133.  
      }
    134.  
      }
    135.  
       
    136.  
      /**
    137.  
      * 给某个用户发送消息
    138.  
      *
    139.  
      * @param userName
    140.  
      * @param message
    141.  
      * @throws IOException
    142.  
      */
    143.  
      public void sendMessageToUser(Long uid, TextMessage message)
    144.  
      throws IOException {
    145.  
      WebSocketSession session = userSocketSessionMap.get(uid);
    146.  
      if (session != null && session.isOpen()) {
    147.  
      session.sendMessage(message);
    148.  
      }
    149.  
      }
    150.  
       
    151.  
      }



    HandShake(每次建立连接都会进行握手)

    1.  
      package org.xdemo.example.websocket.websocket;
    2.  
       
    3.  
      import java.util.Map;
    4.  
       
    5.  
      import javax.servlet.http.HttpSession;
    6.  
       
    7.  
      import org.springframework.http.server.ServerHttpRequest;
    8.  
      import org.springframework.http.server.ServerHttpResponse;
    9.  
      import org.springframework.http.server.ServletServerHttpRequest;
    10.  
      import org.springframework.web.socket.WebSocketHandler;
    11.  
      import org.springframework.web.socket.server.HandshakeInterceptor;
    12.  
       
    13.  
       
    14.  
      /**
    15.  
      * Socket建立连接(握手)和断开
    16.  
      *
    17.  
      * @author Goofy
    18.  
      * @Date 2015年6月11日 下午2:23:09
    19.  
      */
    20.  
      public class HandShake implements HandshakeInterceptor {
    21.  
       
    22.  
      public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
    23.  
      System.out.println("Websocket:用户[ID:" + ((ServletServerHttpRequest) request).getServletRequest().getSession(false).getAttribute("uid") + "]已经建立连接");
    24.  
      if (request instanceof ServletServerHttpRequest) {
    25.  
      ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
    26.  
      HttpSession session = servletRequest.getServletRequest().getSession(false);
    27.  
      // 标记用户
    28.  
      Long uid = (Long) session.getAttribute("uid");
    29.  
      if(uid!=null){
    30.  
      attributes.put("uid", uid);
    31.  
      }else{
    32.  
      return false;
    33.  
      }
    34.  
      }
    35.  
      return true;
    36.  
      }
    37.  
       
    38.  
      public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
    39.  
      }
    40.  
       
    41.  
      }


    一个Controller

    1.  
      package org.xdemo.example.websocket.controller;
    2.  
       
    3.  
      import java.io.IOException;
    4.  
      import java.util.Date;
    5.  
      import java.util.HashMap;
    6.  
      import java.util.Map;
    7.  
       
    8.  
      import javax.annotation.Resource;
    9.  
      import javax.servlet.http.HttpServletRequest;
    10.  
       
    11.  
      import org.springframework.stereotype.Controller;
    12.  
      import org.springframework.web.bind.annotation.ModelAttribute;
    13.  
      import org.springframework.web.bind.annotation.RequestMapping;
    14.  
      import org.springframework.web.bind.annotation.RequestMethod;
    15.  
      import org.springframework.web.bind.annotation.ResponseBody;
    16.  
      import org.springframework.web.servlet.ModelAndView;
    17.  
      import org.springframework.web.socket.TextMessage;
    18.  
      import org.xdemo.example.websocket.entity.Message;
    19.  
      import org.xdemo.example.websocket.entity.User;
    20.  
      import org.xdemo.example.websocket.websocket.MyWebSocketHandler;
    21.  
       
    22.  
      import com.google.gson.GsonBuilder;
    23.  
       
    24.  
      @Controller
    25.  
      @RequestMapping("/msg")
    26.  
      public class MsgController {
    27.  
       
    28.  
      @Resource
    29.  
      MyWebSocketHandler handler;
    30.  
       
    31.  
      Map<Long, User> users = new HashMap<Long, User>();
    32.  
       
    33.  
      //模拟一些数据
    34.  
      @ModelAttribute
    35.  
      public void setReqAndRes() {
    36.  
      User u1 = new User();
    37.  
      u1.setId(1L);
    38.  
      u1.setName("张三");
    39.  
      users.put(u1.getId(), u1);
    40.  
       
    41.  
      User u2 = new User();
    42.  
      u2.setId(2L);
    43.  
      u2.setName("李四");
    44.  
      users.put(u2.getId(), u2);
    45.  
       
    46.  
      }
    47.  
       
    48.  
      //用户登录
    49.  
      @RequestMapping(value="login",method=RequestMethod.POST)
    50.  
      public ModelAndView doLogin(User user,HttpServletRequest request){
    51.  
      request.getSession().setAttribute("uid", user.getId());
    52.  
      request.getSession().setAttribute("name", users.get(user.getId()).getName());
    53.  
      return new ModelAndView("redirect:talk");
    54.  
      }
    55.  
       
    56.  
      //跳转到交谈聊天页面
    57.  
      @RequestMapping(value="talk",method=RequestMethod.GET)
    58.  
      public ModelAndView talk(){
    59.  
      return new ModelAndView("talk");
    60.  
      }
    61.  
      //跳转到发布广播页面
    62.  
      @RequestMapping(value="broadcast",method=RequestMethod.GET)
    63.  
      public ModelAndView broadcast(){
    64.  
      return new ModelAndView("broadcast");
    65.  
      }
    66.  
       
    67.  
      //发布系统广播(群发)
    68.  
      @ResponseBody
    69.  
      @RequestMapping(value="broadcast",method=RequestMethod.POST)
    70.  
      public void broadcast(String text) throws IOException{
    71.  
      Message msg=new Message();
    72.  
      msg.setDate(new Date());
    73.  
      msg.setFrom(-1L);
    74.  
      msg.setFromName("系统广播");
    75.  
      msg.setTo(0L);
    76.  
      msg.setText(text);
    77.  
      handler.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
    78.  
      }
    79.  
       
    80.  
      }

    一个消息的封装的类

    1.  
      package org.xdemo.example.websocket.entity;
    2.  
       
    3.  
      import java.util.Date;
    4.  
      /**
    5.  
      * 消息类
    6.  
      * @author Goofy
    7.  
      * @Date 2015年6月12日 下午7:32:39
    8.  
      */
    9.  
      public class Message {
    10.  
       
    11.  
      //发送者
    12.  
      public Long from;
    13.  
      //发送者名称
    14.  
      public String fromName;
    15.  
      //接收者
    16.  
      public Long to;
    17.  
      //发送的文本
    18.  
      public String text;
    19.  
      //发送日期
    20.  
      public Date date;
    21.  
       
    22.  
      public Long getFrom() {
    23.  
      return from;
    24.  
      }
    25.  
       
    26.  
      public void setFrom(Long from) {
    27.  
      this.from = from;
    28.  
      }
    29.  
       
    30.  
      public Long getTo() {
    31.  
      return to;
    32.  
      }
    33.  
       
    34.  
      public void setTo(Long to) {
    35.  
      this.to = to;
    36.  
      }
    37.  
       
    38.  
      public String getText() {
    39.  
      return text;
    40.  
      }
    41.  
       
    42.  
      public void setText(String text) {
    43.  
      this.text = text;
    44.  
      }
    45.  
       
    46.  
      public String getFromName() {
    47.  
      return fromName;
    48.  
      }
    49.  
       
    50.  
      public void setFromName(String fromName) {
    51.  
      this.fromName = fromName;
    52.  
      }
    53.  
       
    54.  
      public Date getDate() {
    55.  
      return date;
    56.  
      }
    57.  
       
    58.  
      public void setDate(Date date) {
    59.  
      this.date = date;
    60.  
      }
    61.  
       
    62.  
      }


    聊天页面

    1.  
      <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    2.  
      <%
    3.  
      String path = request.getContextPath();
    4.  
      String basePath = request.getServerName() + ":"
    5.  
      + request.getServerPort() + path + "/";
    6.  
      String basePath2 = request.getScheme() + "://"
    7.  
      + request.getServerName() + ":" + request.getServerPort()
    8.  
      + path + "/";
    9.  
      %>
    10.  
      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
    11.  
      "http://www.w3.org/TR/html4/strict.dtd">
    12.  
       
    13.  
      <html xmlns="http://www.w3.org/1999/xhtml">
    14.  
      <head>
    15.  
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    16.  
      <title></title>
    17.  
      <script type="text/javascript" src="<%=basePath2%>resources/jquery.js"></script>
    18.  
      <style>
    19.  
      textarea {
    20.  
      height: 300px;
    21.  
      100%;
    22.  
      resize: none;
    23.  
      outline: none;
    24.  
      }
    25.  
       
    26.  
      input[type=button] {
    27.  
      float: right;
    28.  
      margin: 5px;
    29.  
      50px;
    30.  
      height: 35px;
    31.  
      border: none;
    32.  
      color: white;
    33.  
      font-weight: bold;
    34.  
      outline: none;
    35.  
      }
    36.  
       
    37.  
      .clear {
    38.  
      background: red;
    39.  
      }
    40.  
       
    41.  
      .send {
    42.  
      background: green;
    43.  
      }
    44.  
       
    45.  
      .clear:active {
    46.  
      background: yellow;
    47.  
      }
    48.  
       
    49.  
      .send:active {
    50.  
      background: yellow;
    51.  
      }
    52.  
       
    53.  
      .msg {
    54.  
      100%;
    55.  
      height: 25px;
    56.  
      outline: none;
    57.  
      }
    58.  
       
    59.  
      #content {
    60.  
      border: 1px solid gray;
    61.  
      100%;
    62.  
      height: 400px;
    63.  
      overflow-y: scroll;
    64.  
      }
    65.  
       
    66.  
      .from {
    67.  
      background-color: green;
    68.  
      80%;
    69.  
      border-radius: 10px;
    70.  
      height: 30px;
    71.  
      line-height: 30px;
    72.  
      margin: 5px;
    73.  
      float: left;
    74.  
      color: white;
    75.  
      padding: 5px;
    76.  
      font-size: 22px;
    77.  
      }
    78.  
       
    79.  
      .to {
    80.  
      background-color: gray;
    81.  
      80%;
    82.  
      border-radius: 10px;
    83.  
      height: 30px;
    84.  
      line-height: 30px;
    85.  
      margin: 5px;
    86.  
      float: right;
    87.  
      color: white;
    88.  
      padding: 5px;
    89.  
      font-size: 22px;
    90.  
      }
    91.  
       
    92.  
      .name {
    93.  
      color: gray;
    94.  
      font-size: 12px;
    95.  
      }
    96.  
       
    97.  
      .tmsg_text {
    98.  
      color: white;
    99.  
      background-color: rgb(47, 47, 47);
    100.  
      font-size: 18px;
    101.  
      border-radius: 5px;
    102.  
      padding: 2px;
    103.  
      }
    104.  
       
    105.  
      .fmsg_text {
    106.  
      color: white;
    107.  
      background-color: rgb(66, 138, 140);
    108.  
      font-size: 18px;
    109.  
      border-radius: 5px;
    110.  
      padding: 2px;
    111.  
      }
    112.  
       
    113.  
      .sfmsg_text {
    114.  
      color: white;
    115.  
      background-color: rgb(148, 16, 16);
    116.  
      font-size: 18px;
    117.  
      border-radius: 5px;
    118.  
      padding: 2px;
    119.  
      }
    120.  
       
    121.  
      .tmsg {
    122.  
      clear: both;
    123.  
      float: right;
    124.  
      80%;
    125.  
      text-align: right;
    126.  
      }
    127.  
       
    128.  
      .fmsg {
    129.  
      clear: both;
    130.  
      float: left;
    131.  
      80%;
    132.  
      }
    133.  
      </style>
    134.  
      <script>
    135.  
      var path = '<%=basePath%>';
    136.  
      var uid=${uid eq null?-1:uid};
    137.  
      if(uid==-1){
    138.  
      location.href="<%=basePath2%>";
    139.  
      }
    140.  
      var from=uid;
    141.  
      var fromName='${name}';
    142.  
      var to=uid==1?2:1;
    143.  
       
    144.  
      var websocket;
    145.  
      if ('WebSocket' in window) {
    146.  
      websocket = new WebSocket("ws://" + path + "/ws?uid="+uid);
    147.  
      } else if ('MozWebSocket' in window) {
    148.  
      websocket = new MozWebSocket("ws://" + path + "/ws"+uid);
    149.  
      } else {
    150.  
      websocket = new SockJS("http://" + path + "/ws/sockjs"+uid);
    151.  
      }
    152.  
      websocket.onopen = function(event) {
    153.  
      console.log("WebSocket:已连接");
    154.  
      console.log(event);
    155.  
      };
    156.  
      websocket.onmessage = function(event) {
    157.  
      var data=JSON.parse(event.data);
    158.  
      console.log("WebSocket:收到一条消息",data);
    159.  
      var textCss=data.from==-1?"sfmsg_text":"fmsg_text";
    160.  
      $("#content").append("<div><label>"+data.fromName+" "+data.date+"</label><div class='"+textCss+"'>"+data.text+"</div></div>");
    161.  
      scrollToBottom();
    162.  
      };
    163.  
      websocket.onerror = function(event) {
    164.  
      console.log("WebSocket:发生错误 ");
    165.  
      console.log(event);
    166.  
      };
    167.  
      websocket.onclose = function(event) {
    168.  
      console.log("WebSocket:已关闭");
    169.  
      console.log(event);
    170.  
      }
    171.  
      function sendMsg(){
    172.  
      var v=$("#msg").val();
    173.  
      if(v==""){
    174.  
      return;
    175.  
      }else{
    176.  
      var data={};
    177.  
      data["from"]=from;
    178.  
      data["fromName"]=fromName;
    179.  
      data["to"]=to;
    180.  
      data["text"]=v;
    181.  
      websocket.send(JSON.stringify(data));
    182.  
      $("#content").append("<div><label>我 "+new Date().Format("yyyy-MM-dd hh:mm:ss")+"</label><div>"+data.text+"</div></div>");
    183.  
      scrollToBottom();
    184.  
      $("#msg").val("");
    185.  
      }
    186.  
      }
    187.  
       
    188.  
      function scrollToBottom(){
    189.  
      var div = document.getElementById('content');
    190.  
      div.scrollTop = div.scrollHeight;
    191.  
      }
    192.  
       
    193.  
      Date.prototype.Format = function (fmt) { //author: meizz
    194.  
      var o = {
    195.  
      "M+": this.getMonth() + 1, //月份
    196.  
      "d+": this.getDate(), //日
    197.  
      "h+": this.getHours(), //小时
    198.  
      "m+": this.getMinutes(), //分
    199.  
      "s+": this.getSeconds(), //秒
    200.  
      "q+": Math.floor((this.getMonth() + 3) / 3), //季度
    201.  
      "S": this.getMilliseconds() //毫秒
    202.  
      };
    203.  
      if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    204.  
      for (var k in o)
    205.  
      if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    206.  
      return fmt;
    207.  
      }
    208.  
       
    209.  
      function send(event){
    210.  
      var code;
    211.  
      if(window.event){
    212.  
      code = window.event.keyCode; // IE
    213.  
      }else{
    214.  
      code = e.which; // Firefox
    215.  
      }
    216.  
      if(code==13){
    217.  
      sendMsg();
    218.  
      }
    219.  
      }
    220.  
       
    221.  
      function clearAll(){
    222.  
      $("#content").empty();
    223.  
      }
    224.  
      </script>
    225.  
      </head>
    226.  
      <body>
    227.  
      欢迎:${sessionScope.name }
    228.  
      <div id="content"></div>
    229.  
      <input type="text" placeholder="请输入要发送的信息" id="msg" onkeydown="send(event)">
    230.  
      <input type="button" value="发送" onclick="sendMsg()" >
    231.  
      <input type="button" value="清空" onclick="clearAll()">
    232.  
      </body>
    233.  
      </html>


    发布广播的页面

    1.  
      <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    2.  
      <%
    3.  
      String path = request.getContextPath();
    4.  
      String basePath= request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
    5.  
      %>
    6.  
      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
    7.  
      "http://www.w3.org/TR/html4/strict.dtd">
    8.  
       
    9.  
      <html xmlns="http://www.w3.org/1999/xhtml">
    10.  
      <head>
    11.  
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    12.  
      <title></title>
    13.  
      <script type="text/javascript" src="<%=basePath%>resources/jquery.js"></script>
    14.  
      <script type="text/javascript">
    15.  
      var path='<%=basePath%>';
    16.  
      function broadcast(){
    17.  
      $.ajax({
    18.  
      url:path+'msg/broadcast',
    19.  
      type:"post",
    20.  
      data:{text:$("#msg").val()},
    21.  
      dataType:"json",
    22.  
      success:function(data){
    23.  
      alert("发送成功");
    24.  
      }
    25.  
      });
    26.  
      }
    27.  
      </script>
    28.  
      </head>
    29.  
      <body>
    30.  
      发送广播
    31.  
      <textarea style="100%;height:300px;" id="msg" ></textarea>
    32.  
      <input type="button" value="发送" onclick="broadcast()">
    33.  
      </body>
    34.  
      </html>

    Chrome的控制台网络信息

    Type:websocket

    Time:Pending

    表示这是一个websocket请求,请求一直没有结束,可以通过此通道进行双向通信,即双工,实现了服务器推送的效果,也减少了网络流量。

    Chrome控制台信息

    Demo下载

    GitHub:https://github.com/yangchunjian/websocket

  • 相关阅读:
    关于 Delphi 中流的使用(2) 用 TFileStream(文件流) 读写
    今日工作心得:asp.net中使用javascript进行验证的注意点
    今日工作心得:能够引起FileUpload控件的PostedFile总是为null的一个原因
    完美解决office 2007安装失败(Office.ZhCN/...)
    关于FCKeditor,上传文件时提示invalid request
    今日学习:关于C#多线程之一——异步委托
    今日工作心得:关于C#读取Excel的一些资料
    c# webBrowser读取gb2312 中文变方框的问题
    C#中HashTable的用法
    今日工作心得——javascript结合jquery使图片适应窗口大小
  • 原文地址:https://www.cnblogs.com/handsome1013/p/9378883.html
Copyright © 2011-2022 走看看