赞
踩
目录
3.在config创建WebSocketConfig配置类来开启WebSocket支持:
我们都知道,JavaWeb项目通常是在服务器端部署的。一般我们在开发时候会用到 C / S 架构,也就是客户端 / 服务器。客户端是指用户的设备,比如个人电脑、手机或平板等,它们运行的是浏览器软件,通过HTTP协议向服务器发送请求并接收响应。服务器端则是专门用于处理这些请求的服务器,如Tomcat、Jetty或IIS这样的Web服务器,它们负责运行Java应用程序并执行业务逻辑。
当用户打开浏览器,输入URL访问JavaWeb应用时,浏览器会发起一个HTTP GET或POST请求到服务器的特定地址(即应用的URL)。服务器接收到这个请求后,解析其内容,调用相应的JavaServlet或JSP(Java Server Pages),执行预定义的业务逻辑,并生成HTML响应。然后,服务器将响应返回给客户端,客户端再呈现给用户。
我们看下面的图:
学过 Javaweb 都会了解 Http 协议, Http 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。所以这个时候我们就需要一个协议来解决这个问题,而这时候就要介绍 WebSocket 协议。
WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。根据上图,图的右侧黄色框,其代表的是连接的生命周期,很容易发现 Http 的连接的声明周期断断续续,代表如果通过 Http 协议多次访问,就需要连接多次,这就叫做短链接,而 WebSocket 协议可以持久性的连接,也叫做长连接。还有就是 Http 协议的通信是单向的,基于请求响应模式,而 WebSocket 支持双向通信。
下面表格为上面的总结:
Http协议 | WebSocket协议 |
---|---|
短连接 | 长连接 |
单向通信 | 双向通信 |
视频弹幕,网页聊天,体育实况更新......
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-websocket</artifactId>
- </dependency>
在WebSocket包下导入 WebSocketServer( WebSocket 的服务端组件),用于与客户端通信:
- /**
- * WebSocket服务
- */
- @Component
- @ServerEndpoint("/ws/{sid}")//根据路径匹配,以此请求服务端的组件
- public class WebSocketServer {
-
- //存放会话对象
- private static Map<String, Session> sessionMap = new HashMap();
-
- /**
- * 连接建立成功调用的方法
- */
- @OnOpen
- public void onOpen(Session session, @PathParam("sid") String sid) {
- System.out.println("客户端:" + sid + "建立连接");
- sessionMap.put(sid, session);
- }
-
- /**
- * 收到客户端消息后调用的方法
- *
- * @param message 客户端发送过来的消息
- */
- @OnMessage
- public void onMessage(String message, @PathParam("sid") String sid) {
- System.out.println("收到来自客户端:" + sid + "的信息:" + message);
- }
-
- /**
- * 连接关闭调用的方法
- *
- * @param sid
- */
- @OnClose
- public void onClose(@PathParam("sid") String sid) {
- System.out.println("连接断开:" + sid);
- sessionMap.remove(sid);
- }
-
- /**
- * 群发
- *
- * @param message
- */
- public void sendToAllClient(String message) {
- Collection<Session> sessions = sessionMap.values();
- for (Session session : sessions) {
- try {
- //服务器向客户端发送消息
- session.getBasicRemote().sendText(message);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
- /**
- * 开启WebSocket支持
- */
- @Configuration
- public class WebSocketConfig {
-
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
-
- }
为了方便查看我们使用效果,我们创建一个定时任务类(用了SpringTask框架):
- import com.sky.Websocket.WebSocketServer;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
-
- @Component
- public class WebSocketTask {
- @Autowired
- private WebSocketServer webSocketServer;
-
- /**
- * 通过WebSocket每隔5秒向客户端发送消息
- */
- @Scheduled(cron = "0/5 * * * * ?")
- public void sendMessageToClient() {
- webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
- }
- }
随后,我们启动这个项目,在前段页面会每隔五秒输出内容。
上面是我们服务端给客户端发消息,同样我们基于 WebSocket 协议也可以通过客户端给服务端发消息。
当然我们下面看一下前端的代码展示:
- <!DOCTYPE HTML>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>WebSocket Demo</title>
- </head>
- <body>
- <input id="text" type="text" />
- <button onclick="send()">发送消息</button>
- <button onclick="closeWebSocket()">关闭连接</button>
- <div id="message">
- </div>
- </body>
- <script type="text/javascript">
- var websocket = null;
- var clientId = Math.random().toString(36).substr(2);
-
- //判断当前浏览器是否支持WebSocket
- if('WebSocket' in window){
- //连接WebSocket节点
- websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);
- }
- else{
- alert('Not support websocket')
- }
-
- //连接发生错误的回调方法
- websocket.onerror = function(){
- setMessageInnerHTML("error");
- };
-
- //连接成功建立的回调方法
- websocket.onopen = function(){
- setMessageInnerHTML("连接成功");
- }
-
- //接收到消息的回调方法
- websocket.onmessage = function(event){
- setMessageInnerHTML(event.data);
- }
-
- //连接关闭的回调方法
- websocket.onclose = function(){
- setMessageInnerHTML("close");
- }
-
- //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
- window.onbeforeunload = function(){
- websocket.close();
- }
-
- //将消息显示在网页上
- function setMessageInnerHTML(innerHTML){
- document.getElementById('message').innerHTML += innerHTML + '<br/>';
- }
-
- //发送消息
- function send(){
- var message = document.getElementById('text').value;
- websocket.send(message);
- }
-
- //关闭连接
- function closeWebSocket() {
- websocket.close();
- }
- </script>
- </html>
这组前端与后端的代码一起使用,就是我们 WebSocket 协议的使用方式。
而我们在使用 WebSocket 协议的时候,实际上跟 Http 协议一样,都会需要经过 nginx 转发,然后才可以转发到我们的后端,所以我们在使用WebSocket协议还需要我们提前再 nginx.conf 配置好这个路径。
我们在 server{} 内加入下面代码:
- # WebSocket
- location /ws/ {
- proxy_pass http://webservers/ws/;
- proxy_http_version 1.1;
- proxy_read_timeout 3600s;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "$connection_upgrade";
- }
通过上面的代码就可以将我们的请求转发到webservers,而webservers在我们上面同样声明其路径是本地路径ip与端口号。
- upstream webservers{
- server 127.0.0.1:8080 weight=90 ;
- #server 127.0.0.1:8088 weight=10 ;
- }
当然这个最上级的目录肯定是http{}内写的,所以这个请求就是基于nginx的反向代理,然后将请求转发过来。随后我们基于调用群发方法就可以把消息推送到客户端页面。
推送消息的格式可用当今主流的json格式,随后我们看一下代码案例:
我们想将信息推送过去,可以将信息封装map集合,然后调用JSON.toJSONString()方法就可以将map集合转成json串,并调用群发方法发送至客户端。
- //通过WebSocket向客户端浏览器推送消息type orderId content
- Map map = new HashMap();
- map.put("type",1);
- map.put("orderId",ordersDB.getId());
- map.put("content","订单号:" + outTradeNo);
- String json = JSON.toJSONString(map);
- //推送
- webSocketServer.sendToAllClient(json);
好了,今天的内容就到这里,Javaweb内容持续编辑中,感谢收看!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。