当前位置: 首页 > news >正文

虚拟网站建设指导网站开发软文

虚拟网站建设指导,网站开发软文,微信小程序官网开发,企业招聘广告模板文章目录 学习链接后台代码引入依赖application.ymlWebSocketConfigPrivateControllerWebSocketService WebSocketEventListenerCorsFilter 前端代码Room.vue 学习链接 WebSocket入门教程示例代码#xff0c;代码地址已fork至本地gitee#xff0c;原github代码地址#xff… 文章目录 学习链接后台代码引入依赖application.ymlWebSocketConfigPrivateControllerWebSocketService WebSocketEventListenerCorsFilter 前端代码Room.vue 学习链接 WebSocket入门教程示例代码代码地址已fork至本地gitee原github代码地址源老外的代码地址 [WebSocket入门]手把手搭建WebSocket多人在线聊天室SpringBootWebSocket[WebSocket]第二章WebSocket集群分布式改造——实现多人在线聊天室[WebSocket]使用WebSocket实现实时多人答题对战游戏 其它可参考 手把手搭建WebSocket多人在线聊天室SpringBootWebSocket这个比较详细排版看上去比较舒服 springboot集成websocket小案例 bilibili视频 SpringBootSTOMP 实现聊天室单聊多聊及群发消息详解 springbootwebsocket构建在线聊天室群聊单聊 基于STOMP协议的WebSocket spring websocket stomp 实现广播通信和一对一通信 这个用法很详细 深入使用 SpringBoot——整合WebSocket(STOMP协议) 原创 SpringBoot——整合WebSocket(基于STOMP协议) 点对点通信 补充学习 【Springboot WebSocket STOMP使用 1】Springboot最小化配置启用STOMP并实现浏览器JS通信 【Springboot WebSocket STOMP使用 2】STOMP使用SendToUser实现用户个人请求-响应 WebSocket的那些事4-Spring中的STOMP支持详解前面还有3篇 SpringBoot Websocket Stomp 实现单设备登录(顶号) ① [WebSocket]之上层协议STOMP 后续使用rabbimtmq作为消息代理实现时参考的文章 Docker容器添加映射端口的两种实现方法因为需要rabbitmq需要开启rabbitmq_web_stomp插件、rabbitmq_web_stomp_examples插件开启方式参考下面这个链接然后需要在docker和主机之间开启端口映射Rabbitmq报错Connection refused: no further information: /ip:61613使用rabbitmq作为消息代理需要让我们的服务连接到rabbitmq并且mq要开启rabbitmq_web_stomp插件、rabbitmq_web_stomp_examples插件 后台代码 引入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.timeless/groupIdartifactIdtimeless-chat-websocket/artifactIdversion1.0-SNAPSHOT/versionpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.6.4/version/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.2/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency!--dependency--!-- groupIdcom.itheima/groupId--!-- artifactIdpd-tools-swagger2/artifactId--!-- version1.0-SNAPSHOT/version--!--/dependency--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-websocket/artifactId/dependency!-- RabbitMQ Starter Dependency --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-amqp/artifactId/dependency!-- Following additional dependency is required for Full Featured STOMP Broker Relay --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-reactor-netty/artifactId/dependency/dependencies/projectapplication.yml server:port: 8888 spring:application:name: timeless-chat-websocketdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/timeless_chat_websocket?serverTimeZoneUTCusername: rootpassword: rootmvc:pathmatch:# Springboot2.6以后将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser#matching-strategy: ANT_PATH_MATCHERrabbitmq:host: ${rabbitmq.host}port: ${rabbitmq.port}username: ${rabbitmq.username}password: ${rabbitmq.password}virtual-host: ${rabbitmq.virtual-host} #pinda: # swagger: # enabled: true # title: timeless文档 # base-package: com.timeless.controller mybatis-plus:configuration:log-impl: com.timeless.utils.NoLogWebSocketConfig Configuration Slf4j EnableWebSocketMessageBroker EnableConfigurationProperties(RabbitMQProperties.class) public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {private RabbitMQProperties rabbitMQProperties;public WebSocketConfig(RabbitMQProperties rabbitMQProperties) {this.rabbitMQProperties rabbitMQProperties;log.info(连接rabbitmq, host: {}, rabbitMQProperties.getHost());}Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry// 这个和客户端创建连接时的url有关后面在客户端的代码中可以看到.addEndpoint(/ws).addInterceptors(new HandshakeInterceptor() {Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, MapString, Object attributes) throws Exception {log.info(客户端握手即将开始【开始】);if (request instanceof ServletServerHttpRequest) {ServletServerHttpRequest servletRequest (ServletServerHttpRequest) request;log.info(请求路径: {}, ((ServletServerHttpRequest) request).getServletRequest().getRequestURL());log.info(校验请求头,以验证用户身份: {}, JsonUtil.obj2Json(servletRequest.getHeaders()));HttpSession session servletRequest.getServletRequest().getSession();attributes.put(sessionId, session.getId());return true;}log.info(客户端握手结束 【失败】);return false;}Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {log.info(客户端握手结束 【成功】);}})// .setAllowedOrigins(http://localhost:8080)// 当传入*时, 使用该方法, 而不要使用setAllowedOrigins(*).setAllowedOriginPatterns(*).withSockJS();}Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {// 1. 当客户端发送消息或订阅消息时url路径开头如果是/app/xxx 时会先解析stomp协议然后路由到controller的MessageMapping(/xxx)的方法上执行。// 如果不设置客户端所有发送消息或订阅消息时、都将去匹配messageMapping。所以最好还是配置上。// 2. 这句表示客户端向服务端发送时的主题上面需要加/app作为前缀registry.setApplicationDestinationPrefixes(/app);// 1. 基于内存的消息代理// 2. 声明消息中间件Broker的主题名称当向这个主题下发送消息时js: stompclient.send(/topic/target1,{},hello)订阅当前主题的客户端都可以收到消息。// 注意js 客户端如果发送时、直接是/topic/xxx,spring收到消息会直接发送给broker中。// 点对点发送时enableSimpleBroker 中要配置 /user才可以用 template.convertAndSendToUser(zhangsan,/aaa/hello,111)否则收不到消息// 3. 这句表示在topic和user这两个域上可以向客户端发消息registry.enableSimpleBroker(/topic, /user);// 1. 点对点发送前缀// 2. 这句表示给指定用户发送一对一的主题前缀是 /userregistry.setUserDestinationPrefix(/user);// Use this for enabling a Full featured broker like RabbitMQ/*// 基于mq的消息代理registry.enableStompBrokerRelay(/topic).setVirtualHost(rabbitMQProperties.getVirtualHost()).setRelayHost(rabbitMQProperties.getHost()).setRelayPort(61613).setClientLogin(rabbitMQProperties.getUsername()).setClientPasscode(rabbitMQProperties.getPassword()).setSystemLogin(rabbitMQProperties.getUsername()).setSystemPasscode(rabbitMQProperties.getPassword()).setSystemHeartbeatSendInterval(5000).setSystemHeartbeatReceiveInterval(5000);*/} } PrivateController Slf4j RestController public class PrivateController {Autowiredprivate WebSocketService ws;// 1. 这个注解其实就是用来定义接受客户端发送消息的url(不能是topic开头如果是topic直接发送给broker了要用/app/privateChat)// 如果有返回值,则会将返回的内容转换成stomp协议格式发送给broker(主题名/topic/privateChat)。如果要换主题名可使用sendTo// SubscribeMapping注解和messageMapping差不多但不会再把内容发给broker而是直接将内容响应给客户端MessageMapping(/privateChat)public void privateChat(PrivateMessage message) {ws.sendChatMessage(message);}// 客户端向 /app/broadcastMsg 发送消息, 将会使用该方法处理,// 并且因为此方法有返回值, 所以将结果又发送到/topic/broadcastMsg, 因此订阅了/topic/broadcastMsg的客户端将会收到此消息MessageMapping(/broadcastMsg)SendTo(/topic/broadcastMsg)public BroadcastMessage broadcastMsg(Payload BroadcastMessage message,SimpMessageHeaderAccessor headerAccessor) {// 理解为会话添加属性标识headerAccessor.getSessionAttributes().put(extraInfo, message.getFromUsername());message.setContent(广播消息 message.getContent());return message;}// 客户端向 /app/userMsg 发送消息, 将会使用该方法处理,(谁请求, 则发送给谁, 不会发送给其它的用户)// 并且因为此方法有返回值, 所以将结果又发送到 /user/{username}/singleUserMsg, 其中usernameMessageMapping(/userMsg)// broadcast设置为false表示: 将消息只回给发送此消息的会话用户(1个用户可能有多个会话)SendToUser(value /singleUserMsg, broadcast false) // ?????????????????????????????????????public BroadcastMessage singleUserMsg(Payload BroadcastMessage message,SimpMessageHeaderAccessor headerAccessor) {headerAccessor.getSessionAttributes().put(username, message.getFromUsername());message.setContent(用户消息 message.getContent());return message;}Autowiredprivate SimpMessagingTemplate template;// 广播推送消息// (向此接口发送请求, 将会向所有的订阅了 /topic/broadcastMsg的客户端发送消息)RequestMapping(/sendTopicMessage)public void sendTopicMessage(String content) {template.convertAndSend(/topic/broadcastMsg, content);}// 点对点消息RequestMapping(/sendPointMessage)// (向此接口发送请求, 将会向所有的订阅了 /user/{targetUsername}/singleUserMsg 的客户端发送消息。// 这种方式调用的前提是需要registry.enableSimpleBroker(/topic, /user);// registry.setUserDestinationPrefix(/user);)// 这2个同时配置了才能使用的public void sendQueueMessage(String targetUsername, String content) {this.template.convertAndSendToUser(targetUsername, /singleUserMsg, content);}}WebSocketService Service public class WebSocketService {Autowiredprivate SimpMessagingTemplate template;Autowiredprivate PrivateMessageService privateMessageService;/*** 简单点对点聊天室*/public void sendChatMessage(PrivateMessage message) {message.setMessage(message.getFromUsername() 发送 message.getMessage());// 消息存储到数据库boolean save privateMessageService.save(message);//可以看出template最大的灵活就是我们可以获取前端传来的参数来指定订阅地址, 前面参数是订阅地址后面参数是消息信息template.convertAndSend(/topic/ServerToClient.private. message.getToUsername(), message);if(!save){throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);}}} WebSocketEventListener Component public class WebSocketEventListener {Autowiredprivate SimpMessageSendingOperations messagingTemplate;public static AtomicInteger userNumber new AtomicInteger(0);EventListenerpublic void handleWebSocketConnectListener(SessionConnectedEvent event) {userNumber.incrementAndGet();messagingTemplate.convertAndSend(/topic/ServerToClient.showUserNumber, userNumber);System.out.println(我来了哦~);}EventListenerpublic void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {userNumber.decrementAndGet();messagingTemplate.convertAndSend(/topic/ServerToClient.showUserNumber, userNumber);System.out.println(我走了哦~);} }CorsFilter WebFilter public class CorsFilter implements Filter {Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletResponse response (HttpServletResponse) res;response.setHeader(Access-Control-Allow-Origin, *); response.setHeader(Access-Control-Allow-Methods, *); response.setHeader(Access-Control-Max-Age, 3600); response.setHeader(Access-Control-Allow-Headers, *);response.setHeader(Access-Control-Allow-Credentials, true);chain.doFilter(req, res); } }前端代码 Room.vue templatedivh3 styletext-align: center当前用户{{ this.username }}/h3h3 styletext-align: center在线人数{{ this.userNumber }}/h3!-- h3 styletext-align: center在线用户--!-- div v-foruser in usernameOnlineList :keyuser{{ user }}/div--!-- /h3--div classcontainerdiv classlefth2 styletext-align: center用户列表/h2ulli v-foruser in userList :keyuser.id :class{ selected: user.selected } title点击选择用户聊天div classuser-infospan clickselectUser(user){{ user.toUsername }}/span!-- div classbutton-containerel-buttonv-ifuser.isFriend 0typeprimarysizeminiclicksendFriendRequest(user)申请加好友/el-buttonel-buttonv-ifuser.isFriend 1typesuccessclicksendMessage(user)好友/el-buttonel-button v-ifuser.isFriend 2 typedanger disabled申请中/el-button/div --/div/li/ul/divdiv classrightdiv v-ifselectedUserh2 styletext-align: center正在与{{ selectedUser.toUsername }}聊天/h2/divdiv v-ifselectedUserulli v-formessage in messageList[username selectedUser.toUsername] :keymessage.id{{ message }}/li/ul/divdiv v-ifselectedUserdiv classmessage-inputel-input v-modelselectedUserMessage.message placeholder请输入内容 keyup.enter.nativesendMsg/el-inputdiv classbutton-containerel-button typeprimary clicksendMsg发送消息/el-buttonel-button typedanger clickdeleteAllMsgs删除所有消息/el-button/div/divdiv classmessage-inputel-input v-modelbroadcastMsgContent placeholder请输入广播消息内容 keyup.enter.nativesendMsg/el-inputdiv classbutton-containerel-button typeprimary clicksendBroadcastMsg发送广播消息/el-button/div/divdiv classmessage-inputel-input v-modeluserMsgContent placeholder请输入userMsg keyup.enter.nativesendMsg/el-inputdiv classbutton-containerel-button typeprimary clicksendUserMsg发送userMsg/el-button/div/divdiv classmessage-inputel-input v-modeltoTopicMsgContent placeholder请输入ToTopicMsg keyup.enter.nativesendMsg/el-inputdiv classbutton-containerel-button typeprimary clicksendToTopicMsg发送ToTopicMsg/el-button/div/div/div/div/divdivh1 classbottom styletext-align: center好友申请/h1h2 styletext-align: center; color: rgb(57, 29, 216)功能开发中....../h2/div/div /templatescript import { getAllUsers, listPrivateMessages, deleteAllMsg } from /api; import SockJS from sockjs-client; import Stomp from stompjs; import { Message } from element-ui;export default {name: Room,data() {return {userList: [],groupList: [],selectedUser: null,message: ,stompClient: null,messageList: {}, // 使用对象来存储每个用户的聊天记录username: ,usernameOnlineList: [],userNumber: 1,selectedUserMessage: {user: null,message: ,},broadcastMsgContent: ,userMsgContent: ,toTopicMsgContent: ,};},methods: {listAllUsers() {getAllUsers(this.username).then((response) {this.userNumber response.data.userNumber;this.userList response.data.friends.filter((user) user.toUsername ! this.username);});},selectUser(user) {if (!this.messageList[this.username user.toUsername]) {console.log(2222222)this.$set(this.messageList, this.username user.toUsername, []);}// TODO 展示数据库中存在的信息也就是聊天记录listPrivateMessages(this.username, user.toUsername).then((response) {this.$set(this.messageList, this.username user.toUsername, response.data);});this.selectedUser user;this.selectedUserMessage.user user;this.selectedUserMessage.message ; // 清空输入框内容this.userList.forEach((u) {u.selected false;});user.selected true;},sendMsg() {if (this.stompClient ! null this.selectedUserMessage.message ! ) {// 发送私聊消息给服务端this.stompClient.send(/app/privateChat,{},JSON.stringify({fromUsername: this.username,message: this.selectedUserMessage.message,toUsername: this.selectedUserMessage.user.toUsername,}));this.messageList[this.username this.selectedUserMessage.user.toUsername].push(this.username 发送 this.selectedUserMessage.message);this.selectedUserMessage.message ; // 清空输入框内容} else {Message.info(请输入消息);}},sendBroadcastMsg() {if (this.stompClient ! null) {// 发送私聊消息给服务端this.stompClient.send(/app/broadcastMsg,{},JSON.stringify({fromUsername: this.username,content: this.broadcastMsgContent}));}},sendUserMsg() {if (this.stompClient ! null) {// 发送私聊消息给服务端this.stompClient.send(/app/userMsg,{},JSON.stringify({fromUsername: this.username,content: this.userMsgContent}));}},// 客户端也可以发送 /topic/xx, 这样订阅了 /topic/xx的客户端也会收到消息sendToTopicMsg() {if (this.stompClient ! null) {// 发送私聊消息给服务端this.stompClient.send(/topic/broadcastMsg,{},JSON.stringify({fromUsername: this.username,content: this.toTopicMsgContent}));}},deleteAllMsgs() {if (this.messageList[this.username this.selectedUserMessage.user.toUsername] ) {Message.error(当前没有聊天记录);return;}deleteAllMsg(this.username, this.selectedUser.toUsername).then((response) {this.messageList[this.username this.selectedUserMessage.user.toUsername] [];Message.success(删除成功);});},connect() {//建立连接对象还未发起连接const socket new SockJS(/api/ws);// 获取 STOMP 子协议的客户端对象 this.stompClient Stomp.over(socket);window.stompClient this.stompClient// 向服务器发起websocket连接并发送CONNECT帧 this.stompClient.connect({},(frame) { // 连接成功时服务器响应 CONNECTED 帧的回调方法console.log(建立连接: frame);// 订阅当前个人用户消息this.stompClient.subscribe(/user/${this.username}/singleUserMsg, (response) {console.log(收到当前点对点用户消息: , response.body);})// 订阅当前个人用户消息2this.stompClient.subscribe(/user/singleUserMsg, (response) {console.log(收到当前点对点用户消息2: , response.body);})// 订阅广播消息this.stompClient.subscribe(/topic/broadcastMsg, (response) {console.log(收到广播消息: , response.body);})// 订阅 服务端发送给客户端 的私聊消息//疑问: 订阅的范围如何限制?当前用户应该不能订阅别的用户吧?// 尝试: 每进来一个用户动态生成这个用户对应的一个标识, 然后, 这个用户订阅当前这个标识, // 其它没用如果想发消息给这个用户, 后台先查询这个用户标识, 然后发消息给这个用户,// 这样这个订阅路径就是动态的, 其它不是好友的用户就无法获取到这个动态生成的用户标识。this.stompClient.subscribe(/topic/ServerToClient.private. this.username,(result) {this.showContent(JSON.parse(result.body).message,JSON.parse(result.body).fromUsername,JSON.parse(result.body).toUsername,)});// 订阅 服务端发送给客户端删除所有聊天内容 的消息this.stompClient.subscribe(/topic/ServerToClient.deleteMsg, (result) {const res JSON.parse(result.body);this.messageList[res.toUsername res.fromUsername] [];});// 订阅 服务端发送给客户端在线用户数量 的消息this.stompClient.subscribe(/topic/ServerToClient.showUserNumber, (result) {this.userNumber result.body;});});},disconnect() {if (this.stompClient ! null) {// 断开连接this.stompClient.disconnect();}console.log(断开连接...);},showContent(body, from, to) {// 处理接收到的消息// 示例代码根据实际需求进行修改if (!this.messageList[to from]) {this.$set(this.messageList, to from, []); // 初始化选定用户的聊天记录数组}this.messageList[to from].push(body); // 将接收到的消息添加到选定用户的聊天记录数组},},created() {},mounted() {// 从sessionStorage中获取用户名this.username sessionStorage.getItem(username);console.log(username, this.username);if (!this.username) {this.$router.push(/login)return}this.connect();this.listAllUsers();// console.log(this.username);},beforeDestroy() {this.disconnect();}, }; /scriptstyle scoped .container {display: flex;justify-content: space-between;margin: 10px; }.left, .middle, .right {flex: 0.5;margin: 5px;padding: 10px;background-color: lightgray; }.right {flex: 2; }.bottom {margin-top: 20px;text-align: center; }li {cursor: pointer;transition: color 0.3s ease; }li:hover {color: blue; }li.selected {color: blue;font-weight: bold; }.send-button {display: flex;justify-content: flex-end; }.message-input {display: flex;align-items: center; }.button-container {margin-left: 10px;/* 调整间距大小 */ }.message-container {display: flex;justify-content: flex-end; }.button-container {display: flex;justify-content: flex-end; }.user-info {display: flex;align-items: center; }.button-container {margin-left: auto; } /style
http://www.dnsts.com.cn/news/18087.html

相关文章:

  • 怎么能自己创建网站触屏音乐网站源码
  • 网站开发结构图php做网站优势
  • 做网站设计公司赚钱吗淄博网站建设优化运营熊掌号
  • 网站建设企业网站制作平台河北网站推广优化
  • 法语网站建站公司网站用图怎么做文件小质量高
  • 泉州网站设计师招聘网店设计说明
  • 济南网站建设培训班邢台企业做网站找谁
  • vps 需刷新几次才能打开网站seo查询系统源码
  • 免费制作封面的网站建设网络平台交印花税
  • 服务器 多个网站广东建设安全质量协会网站
  • 网站维护一年一般多少钱网站上的二维码怎么做的
  • 太原有网站工程公司吗网络营销推广方法word
  • 外贸网站 万网flash源码网站
  • 镇江网站建设教程宁波室内设计公司排名
  • 农家乐网站建设营销方案模板网站系统
  • 内蒙古城乡建设网站网站标签名词
  • 苏州公司建设网站首页wordpress 调用qq头像
  • 大连推广网站搭建哪家好wordpress网站有哪些
  • 哈尔滨优化网站公司网站多条件筛选 html
  • 网站管理规范搜索引擎的关键词优化
  • 湖南网站推广wordpress 发布文章 自定义栏目
  • 怎样做触屏版手机网站wordpress导入xml失败
  • 云南建设投资集团网站首页看今天的新闻
  • 免费网站建站系统网站图标psd
  • 徐州做网站管理的公司wordpress工单系统
  • 建设部网站备案做网站好还是网店
  • 济南电商网站开发徐州招标投标信息网
  • it网站模板网站域名注册的相关证书证明文件
  • 网站建设 合优企业《30天网站建设实录》
  • 向客户介绍网站建设火车头wordpress4.7