网站短链接怎么做,怎么把wordpress的博客变成题目,wordpress页面立体效果,推广关键词排名方法一 WebSocket理论
1.1 什么是http请求
http链接分为短链接、长链接#xff0c;短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接#xff08;但是是单向的#xff0c;只能从客户端向服务端发消息#x…一 WebSocket理论
1.1 什么是http请求
http链接分为短链接、长链接短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接但是是单向的只能从客户端向服务端发消息然后服务端才能响应数据给客户端服务端不可以主动给客户端发消息。保持TCP连接不断开。客户端与服务器通信必须要有客户端发起然后服务器返回结果。客户端是主动的服务器是被动的。
1.2 WebSocket
WebSocket他是为了解决客户端发起多个http请求到服务器资源浏览器必须要经过长时间的轮训问题而生的他实现了多路复用他是全双工通信。在webSocket协议下客服端和浏览器可以同时发送信息。
建立了WebSocket之后服务器不必在浏览器发送request请求之后才能发送信息到浏览器。这时的服务器已有主动权想什么时候发就可以随时发送信息到浏览器。而且信息当中不必在带有head的部分信息了与http的长链接通信来对比这种方式不仅能降低服务器的压力。而且信息当中也减少了部分多余的信息。
1.3 WebSocket与http关系 相同点
都是基于tcp的都是可靠性传输协议都是应用层协议
不同点
WebSocket是双向通信协议模拟Socket协议可以双向发送或接受信息HTTP是单向的WebSocket是需要浏览器和服务器握手进行建立连接的而http是浏览器发起向服务器的连接服务器预先并不知道这个连接
联系 WebSocket在建立握手时数据是通过HTTP传输的。但是建立之后在真正传输时候是不需要HTTP协议的
http存在的问题
http是一种无状态协议每当一次会话完成后服务端都不知道下一次的客户端是谁需要每次知道对方是谁才进行相应的响应因此本身对于实时通讯就是一种极大的障碍http协议采用一次请求一次响应每次请求和响应就携带有大量的header头对于实时通讯来说解析请求头也是需要一定的时间因此效率也更低下最重要的是需要客户端主动发服务端被动发也就是一次请求一次响应不能实现主动发送 二 代码实战
SpringBoot集成WebSocket实战
引入相关依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId
/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId
/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.71/version
/dependencyWebSocket配置类
/*** Author:sgw* Date:2023/7/13* Description:WebSocket配置类*/
Configuration
public class WebSocketConfig {/*** 注入ServerEndpointExporter* 这个bean会自动注册使用了ServerEndpoint注解声明的Websocket endpoint*/Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}websocket处理消息核心代码
package com.ws.websocket.demos.service;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;/*** Author:sgw* Date:2023/7/13* Description: 实现websocket处理消息*/
Component
//userId是项目每次启动时都要与服务端的websocket建立长连接的userid值建立长连接后服务端就可以随时给指定的用户推送消息了
ServerEndpoint(/ws/asset/{userId})
public class MyWebSocket {//与某个客户端的连接会话需要通过它来给客户端发送数据private Session session;//concurrent包的线程安全Set用来存放每个客户端对应的MyWebSocket对象。//虽然Component默认是单例模式的但springboot还是会为每个websocket连接初始化一个bean所以可以用一个静态set保存起来。// 注底下WebSocket是当前类名private static CopyOnWriteArraySetMyWebSocket webSockets new CopyOnWriteArraySet();// 用来存在线连接数private static MapString, Session sessionPool new HashMapString, Session();private static Logger log LoggerFactory.getLogger(MyWebSocket.class);/*** 链接成功调用的方法*/OnOpenpublic void onOpen(Session session, PathParam(value userId) String userId) {try {this.session session;webSockets.add(this);sessionPool.put(userId, session);log.info(sessionId值: session.getId());log.info(【websocket消息】有新的连接总数为: webSockets.size());sendMessage(session, 连接成功);} catch (Exception e) {}}/*** 发送消息实践表明每次浏览器刷新session会发生变化。** param session* param message*/public static void sendMessage(Session session, String message) {try {session.getBasicRemote().sendText(String.format(%s (From ServerSession ID%s), message, session.getId()));} catch (IOException e) {log.error(发送消息出错{}, e.getMessage());e.printStackTrace();}}/*** 链接关闭调用的方法*/OnClosepublic void onClose() {try {webSockets.remove(this);log.info(【websocket消息】连接断开总数为: webSockets.size());} catch (Exception e) {}}/*** 收到客户端消息后调用的方法** param message*/OnMessagepublic void onMessage(String message) {log.info(【websocket消息】收到客户端消息: message);}/*** 发送错误时的处理** param session* param error*/OnErrorpublic void onError(Session session, Throwable error) {log.info(用户错误,原因: error.getMessage());error.printStackTrace();}// 此为广播消息public void sendAllMessage(String message) {log.info(【websocket消息】广播消息: message);for (MyWebSocket webSocket : webSockets) {try {if (webSocket.session.isOpen()) {webSocket.session.getAsyncRemote().sendText(message);}} catch (Exception e) {e.printStackTrace();}}}// 此为单点消息public void sendOneMessage(String userId, String message) {Session session sessionPool.get(userId);if (session ! null session.isOpen()) {try {log.info(【websocket消息】 单点消息: message);//session.getAsyncRemote().sendText(message);session.getAsyncRemote().sendText(String.format(%s (From ServerSession ID%s), message, session.getId()));} catch (Exception e) {e.printStackTrace();}}else {log.info(没找到目前已经建立连接的用户即要推送给的用户目前没登录);}}// 此为单点消息(多人)public void sendMoreMessage(String[] userIds, String message) {for (String userId : userIds) {Session session sessionPool.get(userId);if (session ! null session.isOpen()) {try {log.info(【websocket消息】 单点消息: message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}
}Controller入口类
package com.ws.websocket.demos.web;import com.alibaba.fastjson.JSONObject;
import com.ws.websocket.demos.service.MyWebSocket;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;/*** Author:sgw* Date:2023/7/13* Description: websocket入口类*/RequestMapping(/api/ws)
RestController
public class BasicController {Resourceprivate MyWebSocket myWebSocket;/*** 发送给单个用户websocket消息** param userId 用户的id* param message 消息体* return*/RequestMapping(/wsTest)public String websocket(String userId, String message) {JSONObject obj new JSONObject();obj.put(cmd, topic);//业务类型obj.put(msgId, 987654321);//消息idobj.put(msgTxt, message);//消息内容//单个用户发送 (userId为用户id)myWebSocket.sendOneMessage(userId, obj.toJSONString());return index.html;}/*** 发送给所有用户websocket消息** param message 消息体* return*/RequestMapping(/wsTest2)public String websocket2(String message) {JSONObject obj new JSONObject();obj.put(cmd, topic);//业务类型obj.put(msgId, 987654321);//消息idobj.put(msgTxt, message);//消息内容//全体发送myWebSocket.sendAllMessage(obj.toJSONString());return index.html;}/*** 发送给多个指定用户websocket消息** param message 消息体* return*/RequestMapping(/wsTest3)public String websocket3(String message) {JSONObject obj new JSONObject();obj.put(cmd, topic);//业务类型obj.put(msgId, 987654321);//消息idobj.put(msgTxt, message);//消息内容//给多个用户发送 (userIds为多个用户id逗号‘,’分隔)String[] userIds {euoiqhfljsak, jowiqnfdnas};myWebSocket.sendMoreMessage(userIds, obj.toJSONString());return index.html;}
}前端代码
这里的前端代码以最简单的html来进行编写
!DOCTYPE html
html
headmeta charsetUTF-8titlewebsocket测试/titlestyle typetext/cssh3, h4 {text-align: center;}/style
/head
bodyh3WebSocket测试在span stylecolor:red控制台/span查看测试信息输出/h3
h4[url/api/ws/wsTest?message单发消息内容userIdnone]单发消息链接[/url]br[url/api/ws/wsTest1?message群发给所有用户消息内容]群发消息链接[/url]br[url/api/ws/wsTest2?message指定多个用户发消息内容]群发消息链接[/url]
/h4script typetext/javascriptvar socket;if (typeof (WebSocket) undefined) {console.log(遗憾您的浏览器不支持WebSocket);} else {console.log(恭喜您的浏览器支持WebSocket);//实际业务中这里需要从系统里获取当前当前登录的用户idvar userId 54321;/*实现化WebSocket对象指定要连接的服务器地址与端口建立连接注意ws、wss使用不同的端口。我使用自签名的证书测试无法使用wss浏览器打开WebSocket时报错ws对应http、wss对应https。*/socket new WebSocket(ws://localhost:8080/ws/asset/ userId);//连接打开事件socket.onopen function () {console.log(Socket 已打开);socket.send(消息发送测试);};//收到消息事件socket.onmessage function (msg) {console.log(msg.data);};//连接关闭事件socket.onclose function () {console.log(Socket已关闭);};//发生了错误事件socket.onerror function () {alert(Socket发生了错误);}//窗口关闭时关闭连接window.unload function () {socket.close();};}
/script/body
/html这里模拟登录用户的id是54321实际业务中这个id是要从系统里进行获取的项目启动时就会加载这段代码把54321这个用户的前端与后端的websocket服务端进行长连接
三 测试
访问前端首页http://localhost:8080/打开f12控制台可以看到连接成功 使用postman调接口给用户id是54321的用户发送消息看看浏览器这里能不能接收到websocket消息 发现浏览器接收到消息了如下 如果使用postman发给其他用户还没登录的用户浏览器接收不到消息
浏览器没有新消息 后端日志 查看websocket发送与接收的消息