如何用JSP实现WebSocket双向通信
admin
2023-02-13 02:20:03
0

  简介

  JSP(JavaServer Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。JSP技术有点类似ASP技术,它是在传统的网页HTML文件(*.htm,*.html)中插入Java程序段(Scriptlet)和JSP标记(tag),从而形成JSP文件(*.jsp)。

  WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。  WebSocket API也被W3C定为标准。

  重点

  1、JAVA内的WebSocket是在Java jar7.0之后才能使用的。

  2、需要在JavaServer项目lib目录下引入 javaee-api-7.0 包

  |前端代码

  |后端JAVA代码

  package websocketPro;

  import javax.websocket.OnClose;

  import javax.websocket.OnMessage;

  import javax.websocket.OnOpen;

  import javax.websocket.Session;

  import javax.websocket.server.PathParam;

  import javax.websocket.server.ServerEndpoint;

  import java.util.HashSet;

  import java.util.Set;

  import java.util.Map;

  import java.util.concurrent.ConcurrentHashMap;

  import java.util.concurrent.CopyOnWriteArraySet;

  /**

  * writer: holien Time: 2017-08-01 13:00 Intent: webSocket服务器

  */

  @ServerEndpoint("/webSocket/ChatRoom/{roomName}")//这里是你请求的生成的房间服务器路径 roomName是前端发来的 roomName名字

  public class ChatRoom {

  private static final Map> rooms = new ConcurrentHashMap();

  @OnOpen //session 是可选的参数,session为与某个客户端的连接会话,需要通过它来给客户端发送数据

  public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {

  if (!rooms.containsKey(roomName)) {

  Set room = new HashSet<>();

  room.add(session);

  rooms.put(roomName, room);

  } else {

  rooms.get(roomName).add(session);

  }

  System.out.println("建立连接 !");

  }

  @OnClose

  public void disConnect(@PathParam("roomName") String roomName, Session session) {

  rooms.get(roomName).remove(session);

  System.out.println("断开连接!");

  }

  @OnMessage

  public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {

  System.out.println(msg);

  broadcast(roomName, msg);

  }

  // 按照房间名进行广播

  public static void broadcast(String roomName, String msg) throws Exception {

  for (Session session : rooms.get(roomName)) {

  session.getAsyncRemote().sendText(msg);

  }

  }

  }

  |JAVA服务器目录结构

  Tip:下面简单的解释一下每个函数及其方法的含义和关联。

  所有WebSocket项目双向通信的建立,都需要前端先发送给后端一个请求,并且握手成功之后才能进行通信 就和打电话一个道理。

  webSocket = new WebSocket(url);

  上面这个就是前端JS创建一个WebSocket对象 并且发送给后端(URL地址的服务器)一个通信请求 你正在向一个人打电话,并且等他接电话

  @ServerEndpoint("/webSocket/ChatRoom/{roomName}")

  var url = "ws://172.16.245.232:8080/WebsocketPro/webSocket/mainBlock/" + roomName;

  后端java这个注释标记了当前这个Java文件的服务器访问地址和前端的请求的地址是一致的。

  前端定义 roomName 的名称会被后端的 {roomName} 读取到

  之前 前端的roomName定义为 MainBlock

  所以在请求之后后端注释内的访问路径就变成了

  /webSocket/ChatRoom/MainBlock

  private static final Map> rooms = new ConcurrentHashMap();

  @OnOpen

  public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {

  if (!rooms.containsKey(roomName)) {

  Set room = new HashSet<>(); //创建Hash数组 的数理化对象

  room.add(session); //把session对象 即用户对象 添加到Hash对象里

  rooms.put(roomName, room); //并且根据房间名添加用户组成的 Hash对象 这里就获取了一个用户集

  } else {

  rooms.get(roomName).add(session); //获取对应房间的 用户集

  }

  System.out.println("建立连接 !");

  }

  关于 ConcurrentHashMap 参考ConcurrentHashMap

  此时在申请之后会被后端的 @OnOpen注释下的方法接收到

  这个时候底层WebSocket会进行和前端的握手协议 我们是看不到的

  诺访问正常并且握手成功,则服务器会自动调用这个连接方法

  此时底层会向服务器发送成功握手的协议

  并且前端也会调用下面这个定义的的方法

  webSocket.onopen = function () {

  console.log("和服务器的握手连接建立...(握手)")

  };

  到这里为止 前端和后端建立了一个理论上永久的通信协议,只要其中一方不要断开连接。 你成功和他打通了电话

  |开始交流

  webSocket.send(msg);

  我们前端调用了WebSocket对象的 send() 方法 传入要发送给后台的消息

  封装要发送到服务端的数据一般来说JSON比较好

  @OnMessage

  public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {

  System.out.println(msg);

  broadcast(roomName, msg);

  }

  传入的消息就会被后台的 @OnMessage 标记的方法接收

  @PathParam(“roomName”) String roomName

  这句话的意思就是之前标记的 /webSocket/ChatRoom/{roomName} 里的 roomName 的值

  String msg

  这个参数就是前台发送的消息。 Session session 这个参数在代码中说明了就不重复解释

  在接收到消息之后就调用这个这个函数内的一个完美自定义的方法 broadcast()

  public static void broadcast(String roomName, String msg) throws Exception {

  for (Session session : rooms.get(roomName)) {

  session.getAsyncRemote().sendText(msg);

  }

  }

  这个方法调用了 session 对象里的 getAsyncRemote() 方法的 sendText(msg)

  用来向之前封装的所有对象( rooms )广播消息

  webSocket.onmessage = function (evt) {

  var Data = JSON.parse(evt.data)

  };

  接收到广播消息之后,前端调用了 WebSocket对象的 onmessage 方法

  这里的 evt 参数就是广播的消息 但是后端传过来的是一个对象

  我们要调用这个对象的 evt.data 方法 如果是Json数据 就把它转换成我们js能识别的对象

  到这里为止来就完成了消息的交流。

  要断开请求的话,就调用 webSocket.close() 方法 ,这个时候

  后台就会自动调用 下面这个方法

  @OnClose

  public void disConnect(@PathParam("roomName") String roomName, Session session) {

  System.out.println("断开连接!");

  }

  同时响应到前端 ,调用下面这个方法

  webSocket.onclose = function () {

  console.log("和服务器的握手连接已关闭...(分手)")

  webSocket = null;

  };

  到这里来位置完成了WebSocket 完整的双向通信。

相关内容

热门资讯

活力中国调研行丨一束“光”的故... 它被称为“最快的刀”“最准的尺”“最亮的光”。从一束“光”到一颗“芯”,再到规模千亿的产业集群,今天...
携手前沿技术 共创智能未来 携手前沿技术 共创智能未来 ——来自2026年世界互联网大会数字丝路发展论坛的声音 夏日长安,秦岭叠...
上海浩劢取得桌面式轻型悬臂吊专... 国家知识产权局信息显示,上海浩劢工业科技有限公司取得一项名为“桌面式轻型悬臂吊”的专利,授权公告号C...
毒油风暴未歇民进党却急着上架,... 海峡导报综合报道 岛内毒油食安风暴持续延烧,台北市长蒋万安持续号召民众7·25上凯道,但“食药署”2...
WAIC挤满“卖铲人”,但算力... 2026年的WAIC,机器人依然抢占了绝大多数镜头。但展馆里数量增长最快的,是自称“AI Infra...
对话芯展速许玮:“内存墙”下,... Token经济时代,衡量AI价值的标准,正从模型能力转向Token生产效率。AI因此从工具演变为新的...
菲尔兹奖得主邓煜写过这些诗词 邓煜 李少君 徐俪成 | 澎湃新闻记者 徐萧 整理北京时间7月23日晚,中国数学家王虹、邓煜获颁菲尔...
中国海警局新闻发言人就菲位南海... 中国海警局新闻发言人姜略表示,7月24日,菲律宾组织7艘公务船、3艘海警舰、1艘运鱼船,并唆使大量渔...
外交部回应美国对数十国加征关税 7月24日,外交部发言人林剑主持例行记者会。有记者问:美国新一轮关税措施将于今天生效,外交部能否就此...
台湾岛以东相关海域治理进入经济... 为全面了解我国管辖海域渔业资源状况,7月17日至23日,农业农村部中国水产科学研究院东海水产研究所,...