中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

iis搭建網(wǎng)站seo學(xué)校培訓(xùn)課程

iis搭建網(wǎng)站,seo學(xué)校培訓(xùn)課程,保定百度推廣排名,三級(jí)a一級(jí)a做爰視頻免費(fèi)網(wǎng)站目錄 后端pom.xmlConfig配置類Controller類DTO 前端安裝相關(guān)依賴websocketService.js接口javascripthtmlCSS 效果展示簡(jiǎn)單測(cè)試連接: 報(bào)錯(cuò)解決方法1、vue3 使用SockJS報(bào)錯(cuò) ReferenceError: global is not defined 功能補(bǔ)充拓展1. 安全性和身份驗(yàn)證2. 異常處理3. 消息…

目錄

    • 后端
      • pom.xml
      • Config配置類
      • Controller類
      • DTO
    • 前端
      • 安裝相關(guān)依賴
      • websocketService.js接口
      • javascript
      • html
      • CSS
    • 效果展示
      • 簡(jiǎn)單測(cè)試連接:
    • 報(bào)錯(cuò)解決方法
      • 1、vue3 使用SockJS報(bào)錯(cuò) ReferenceError: global is not defined
    • 功能補(bǔ)充拓展
      • 1. 安全性和身份驗(yàn)證
      • 2. 異常處理
      • 3. 消息廣播的功能
      • 4. 配置 WebSocket 消息緩存和負(fù)載均衡
      • 5. 客戶端連接管理
      • 6. WebSocket 消息格式和編碼
      • 總結(jié)
    • 后面將繼續(xù)完善,待更新...

后端

pom.xml

		<!-- Spring Boot WebSocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- Spring Boot 數(shù)據(jù)庫支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL 驅(qū)動(dòng) --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Thymeleaf(如果你使用了模板) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Spring Boot Web 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

Config配置類

注意:允許源根據(jù)自己項(xiàng)目修改

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;@Configuration
@EnableWebSocketMessageBroker
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/queue", "/topic","/user");config.setApplicationDestinationPrefixes("/app");}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/ws")
//        在 WebSocket 握手時(shí),我們可以通過 URL 參數(shù)或者 HTTP headers 傳遞用戶身份信息。
//                .addInterceptors(new MyHandshakeInterceptor())// 添加攔截器.setAllowedOrigins("http://127.0.0.1:8889", "http://localhost:8889", "http://localhost:8888", "http://127.0.0.1:8888", "http://localhost:8000","http://localhost:8890","http://127.0.0.1:8890").withSockJS();  // 添加 SockJS 支持}
}

Controller類

import com.tianwen.mapper.UserMessagesMapper;
import com.tianwen.user.dtos.MessageDTO;
import com.tianwen.user.pojos.Messages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import java.time.LocalDateTime;@Controller
public class ChatController {@Autowiredprivate UserMessagesMapper userMessagesMapper;@Autowiredprivate SimpMessagingTemplate messagingTemplate; // 注入消息模板,用于發(fā)送消息到指定目的地@MessageMapping("/chat.sendMessage")//這個(gè)注解用來監(jiān)聽來自前端的 WebSocket 消息,路徑是 /app/chat.sendMessage,當(dāng)前端發(fā)送消息到這個(gè)路徑時(shí),sendMessage 方法會(huì)被觸發(fā)。
//    @SendTo("/topic/messages")//這個(gè)注解表明處理完消息后,返回的消息將廣播給訂閱了 /topic/messages 路徑的所有客戶端。public MessageDTO sendMessage(MessageDTO messageDTO) throws Exception {System.out.println("接收到的message:"+messageDTO);// 1. 可以在這里進(jìn)行私信存儲(chǔ)到數(shù)據(jù)庫操作Messages messages = new Messages();messages.setSenderId(messageDTO.getSenderId());messages.setReceiverId(messageDTO.getReceiverId());messages.setContent(messageDTO.getContent());messages.setCreateTime(LocalDateTime.now());// 2. 保存私信消息(插入操作)if (userMessagesMapper.insert(messages) <= 0) {// 如果插入失敗,可以返回錯(cuò)誤或做其他處理return null;}// 3. 實(shí)時(shí)將消息轉(zhuǎn)發(fā)給接收者String receiverIdStr = String.valueOf(messageDTO.getReceiverId());  // 將 receiverId 轉(zhuǎn)換為 StringString receiverDestination = "/user/" + receiverIdStr + "/queue/messages";//通過 SimpMessagingTemplate 的 convertAndSendToUser 方法,將消息實(shí)時(shí)推送給接收者。//推送的目標(biāo)是 /user/{receiverId}/queue/messages,該路徑是給特定用戶的私有消息隊(duì)列。messagingTemplate.convertAndSendToUser(receiverIdStr, receiverDestination, messageDTO);return messageDTO;}
}

DTO

import lombok.Data;
@Data
public class MessageDTO {private Integer senderId;private Integer receiverId;private String content;
}

前端

安裝相關(guān)依賴

npm install sockjs-client@latest
npm install @stomp/stompjs sockjs-client
npm install global    
npm i --save-dev @types/sockjs-client 

websocketService.js接口

注意:服務(wù)器地址根據(jù)自己的修改(application.yml)

// websocketService.js
// Stomp.js:用于處理 STOMP 協(xié)議,它在 WebSocket 基礎(chǔ)上實(shí)現(xiàn)了消息訂閱、發(fā)送等功能。
import { Stomp } from "@stomp/stompjs";
//SockJS:是一個(gè)用于實(shí)現(xiàn) WebSocket 的庫,它為 WebSocket 提供了回退機(jī)制(例如 HTTP 長(zhǎng)輪詢等),確保在不同瀏覽器和網(wǎng)絡(luò)環(huán)境下的兼容性。
import SockJS from "sockjs-client/dist/sockjs.min.js";
export default {connect(onMessageReceived) {//使用 SockJS 和 Stomp 創(chuàng)建一個(gè) WebSocket 客戶端,連接到后端的 WebSocket 服務(wù) http://localhost:8000/ws。const socket = new SockJS("http://localhost:8000/ws"); // 使用 SockJS 連接const stompClient = Stomp.over(socket);const userId = JSON.parse(localStorage.getItem("userId"));stompClient.connect({}, () => {console.log("本人消息隊(duì)列ID:", userId);//在連接成功后,通過 stompClient.subscribe 訂閱 /topic/messages,接收從后端廣播過來的消息。// stompClient.subscribe("/topic/messages", (messageOutput) => {//   onMessageReceived(JSON.parse(messageOutput.body));// });// 訂閱當(dāng)前用戶的私有消息隊(duì)列stompClient.subscribe("/user/" + userId + "/queue/messages",(messageOutput) => {onMessageReceived(JSON.parse(messageOutput.body)); // 處理接收到的私聊消息});// 訂閱當(dāng)前用戶的私有消息隊(duì)列;// stompClient.subscribe(//   "/user/" + userId + "/queue/messages",//   function (messageOutput) {//     const message = JSON.parse(messageOutput.body);//     console.log("接收到私信:", message);//   }// );});// 連接到 WebSocket 后,訂閱用戶消息// stompClient.connect({}, function (frame) {//   // 獲取當(dāng)前用戶ID//   const userId = getCurrentUserId(); // 假設(shè)這個(gè)方法能夠獲取當(dāng)前用戶的ID//   // 訂閱接收者的消息隊(duì)列// stompClient.subscribe(//   "/user/" + userId + "/queue/messages",//   function (messageOutput) {//     const message = JSON.parse(messageOutput.body);//     console.log("接收到私信:", message);//   }// );// });},sendMessage(message) {console.log("發(fā)送消息接口1:", message);const socket = new SockJS("http://localhost:8000/ws"); // 使用 SockJS 連接const stompClient = Stomp.over(socket);stompClient.connect({}, () => {//當(dāng)用戶輸入消息時(shí),通過 stompClient.send 方法將消息發(fā)送到 /app/chat.sendMessage,這個(gè)路徑會(huì)將消息推送到后端進(jìn)行處理。stompClient.send("/app/chat.sendMessage", {}, JSON.stringify(message));});},
};

javascript

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { onBeforeUnmount, ref, shallowRef, onMounted } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import type { IToolbarConfig, IEditorConfig } from "@wangeditor/editor";
const editorRef = shallowRef();
import websocketService from "@/api/websocketService.js";
import {ref,onMounted,
} from "vue";
import websocketService from "@/api/websocketService.js";const receiverIdAnswer = ref();
const sendPrivateMessage = () => {dialogVisible.value = true;
};
const sendPrivateMessage = async (userId) => {receiverIdAnswer.value = userId;dialogVisible.value = true;const response = await getAuthorDetailsByUserId(userId);console.log("response", userId);privateMessagesUser.value = response.data;console.log("privateMessagesUser", privateMessagesUser.value);
};const dialogVisible = ref(false);interface Message {id: string;senderId: string;receiverId: string;content: string;
}const messages = ref<Message[]>([]); // 明確指定消息數(shù)組的類型const newMessage = ref("");onMounted(() => {websocketService.connect((message: Message) => {// 明確指定回調(diào)函數(shù)的參數(shù)類型messages.value.push(message);});
});const sendMessage = () => {if (newMessage.value.trim()) {const message: Message = {// 明確聲明消息類型id: Date.now().toString(), // 使用當(dāng)前時(shí)間戳作為唯一 IDsenderId: userInfo.value.id, // Example senderreceiverId: receiverIdAnswer.value, // Example receivercontent: newMessage.value,};websocketService.sendMessage(message);newMessage.value = "";}
};
const editorConfig: Partial<IEditorConfig> = {placeholder: "請(qǐng)輸入...",MENU_CONF: {},
};
const handleCreated = (editor) => {editorRef.value = editor;
};
// 排除富文本的菜單項(xiàng)
const toolbarConfigPrivateMessages: Partial<IToolbarConfig> = {// toolbar 配置excludeKeys: ["headerSelect","blockquote","|","bold","underline","italic","group-more-style", // 排除菜單組,寫菜單組 key 的值即可"color","bgColor","|","fontSize","fontFamily","lineHeight","bulletedList","numberedList","todo","group-justify","group-indent","insertLink","group-video","insertTable","codeBlock","divider","undo","redo","fullScreen",],
};
</script>

html

 <!-- 私信聊天框 --><el-dialog v-model="dialogVisible"><template #title><div style="text-align: center; font-weight: bold">{{ privateMessagesUser.username }}</div><hr class="line" /></template><div class="chat-container"><div class="messages" ref="messagesContainer"><divv-for="message in messages":key="message.id":class="{'my-message': message.senderId === userInfo.id,'other-message': message.senderId !== userInfo.id,}"><div style="display: flex; flex-direction: row"><div><el-image:src="userInfo.avatarUrl"style="width: 45px; border-radius: 50%"></el-image></div><div style="margin-top: 5px; margin-left: 10px"><div><strong>{{ userInfo.username }}</strong></div><divclass="message-bubble message-green"v-html="message.content"></div></div></div></div></div></div><div style="border: 1px solid #ccc"><Toolbarstyle="border-bottom: 1px solid #ccc":editor="editorRef":defaultConfig="toolbarConfigPrivateMessages"mode="default"/><Editorstyle="height: 200px; overflow-y: hidden"v-model="newMessage"@keyup.enter="sendMessage":defaultConfig="editorConfig"mode="default"@onCreated="handleCreated"/></div><template #footer><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="sendMessage">發(fā)送</el-button></template></el-dialog>

CSS

<style scoped>
/* 私信樣式 */
/* 標(biāo)題居中 */
/* .private-message-dialog {
} */
.line {border-top: 1px solid #ccc; /* 直線的樣式,可以修改顏色 */
}/* 聊天框滾動(dòng) */
.chat-container {display: flex;flex-direction: column;height: 300px;overflow-y: auto;box-sizing: border-box; /* 讓 padding 和 border 包含在寬度和高度內(nèi) */
}.chat-container > * {width: 100%; /* 確保所有子元素不會(huì)超出容器寬度 */box-sizing: border-box; /* 確保子元素的寬度計(jì)算不受 padding 和 border 影響 */
}/* 消息容器 */
.messages {display: flex;flex-direction: column;gap: 10px;padding: 10px;max-height: 250px;overflow-y: auto;
}/* 發(fā)送方和接收方的消息樣式 */
.my-message {/* text-align: right; */border-radius: 10px;height: auto;/* padding: 5px 10px; */
}.other-message {/* text-align: left; */border-radius: 10px;/* padding: 5px 10px; */
}.message-bubble {/* max-width: 70%; */padding: 0px 10px;border-radius: 10px;/* height: 30px; *//* margin: 0px 0px 0px 0px; *//* word-wrap: break-word; *//* line-height: 1.4; */font-size: 14px;display: flex;align-items: center;justify-content: center;
}.message-green {background-color: #57c457; /* 微信消息綠色 */color: white;align-self: flex-end; /* 讓氣泡靠右顯示 */
}
</style>

效果展示

在這里插入圖片描述

簡(jiǎn)單測(cè)試連接:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

報(bào)錯(cuò)解決方法

1、vue3 使用SockJS報(bào)錯(cuò) ReferenceError: global is not defined

解:

import SockJS from “sockjs-client”;

修改為:

import SockJS from “sockjs-client/dist/sockjs.min.js”;

并安裝依賴

npm i --save-dev @types/sockjs-client

功能補(bǔ)充拓展

以下是一些可能的補(bǔ)充和優(yōu)化,確保 WebSocket 能夠順利運(yùn)行并且高效處理消息。

1. 安全性和身份驗(yàn)證

如果你的 WebSocket 服務(wù)需要進(jìn)行身份驗(yàn)證(如用戶登錄),你可以考慮在 WebSocket 握手時(shí)驗(yàn)證用戶身份。你可以在 WebSocketConfig 中添加一個(gè) HandshakeInterceptor 來攔截握手請(qǐng)求,獲取 HTTP header 或 URL 參數(shù)中的用戶信息,確保只有經(jīng)過身份驗(yàn)證的用戶能夠連接。

例如:

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/ws").addInterceptors(new MyHandshakeInterceptor()) // 添加攔截器.setAllowedOrigins("http://localhost:8889").withSockJS();
}

其中 MyHandshakeInterceptor 可以用來在 WebSocket 握手期間傳遞用戶信息。

2. 異常處理

在 WebSocket 消息處理過程中,你可能會(huì)遇到一些異常,如數(shù)據(jù)庫操作失敗或消息傳輸失敗等。在控制器中,你可以捕獲這些異常并返回相應(yīng)的錯(cuò)誤消息,確保系統(tǒng)更加健壯。

例如:

@MessageMapping("/chat.sendMessage")
public MessageDTO sendMessage(MessageDTO messageDTO) {try {// 消息處理邏輯} catch (Exception e) {log.error("發(fā)送消息失敗", e);return new MessageDTO("error", "消息發(fā)送失敗");}
}

3. 消息廣播的功能

目前,你的代碼實(shí)現(xiàn)了將消息發(fā)送到指定用戶的功能(私信)。如果你希望實(shí)現(xiàn)群聊功能或全局廣播,可以進(jìn)一步擴(kuò)展 @SendTo 注解。這個(gè)注解的使用使得你可以將處理后的消息發(fā)送給所有訂閱某個(gè)特定主題的客戶端。

例如,廣播消息給所有訂閱 /topic/messages 的客戶端:

@MessageMapping("/chat.sendMessage")
@SendTo("/topic/messages")
public MessageDTO sendMessage(MessageDTO messageDTO) {// 處理消息邏輯return messageDTO;  // 返回的消息會(huì)廣播給所有訂閱 /topic/messages 的客戶端
}

4. 配置 WebSocket 消息緩存和負(fù)載均衡

如果你的系統(tǒng)需要處理大量的 WebSocket 連接,可能會(huì)面臨性能和可擴(kuò)展性的問題。在這種情況下,考慮使用 Redis 等消息隊(duì)列作為消息代理,可以通過 @EnableWebSocketMessageBroker 配置遠(yuǎn)程消息代理。

例如,通過 Redis 實(shí)現(xiàn)消息廣播:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {config.enableSimpleBroker("/queue", "/topic", "/user");config.setApplicationDestinationPrefixes("/app");// 使用 Redis 消息代理config.setBrokerRegistry().setApplicationDestinationPrefixes("/app").enableStompBrokerRelay("/topic", "/queue").setRelayHost("localhost").setRelayPort(61613);  // 配置Redis(如ActiveMQ)等消息中間件}
}

5. 客戶端連接管理

如果你希望在某個(gè)用戶斷開連接時(shí)進(jìn)行一些清理工作(例如清理會(huì)話、推送通知等),你可以使用 @OnDisconnect 注解來捕獲斷開連接事件。

@MessageMapping("/chat.disconnect")
public void handleDisconnect(SessionDisconnectEvent event) {// 用戶斷開連接時(shí)執(zhí)行的邏輯log.info("用戶斷開連接,sessionId: " + event.getSessionId());
}

6. WebSocket 消息格式和編碼

確保你的客戶端和服務(wù)端使用相同的消息格式。你可能需要為 WebSocket 消息提供適當(dāng)?shù)男蛄谢头葱蛄谢?#xff0c;以確保消息能夠正確地從客戶端傳輸?shù)椒?wù)端,以及從服務(wù)端傳輸回客戶端。

例如,使用 Jackson 或其他庫將 Java 對(duì)象序列化為 JSON 格式:

@MessageMapping("/chat.sendMessage")
@SendTo("/topic/messages")
public MessageDTO sendMessage(MessageDTO messageDTO) throws Exception {// 消息傳輸過程中確保使用適當(dāng)?shù)?JSON 格式return messageDTO;
}

總結(jié)

大體上,已經(jīng)完成了 WebSocket 的配置和處理消息的核心部分,剩下的步驟主要是根據(jù)具體業(yè)務(wù)需求做擴(kuò)展,如身份驗(yàn)證、消息緩存、廣播支持等。如果你的應(yīng)用規(guī)模較大,可能還需要考慮負(fù)載均衡和消息隊(duì)列等高可用性的設(shè)計(jì)。

后面將繼續(xù)完善,待更新…

http://www.risenshineclean.com/news/27331.html

相關(guān)文章:

  • 長(zhǎng)沙交互網(wǎng)站設(shè)計(jì)服務(wù)商愛站網(wǎng)seo綜合查詢
  • 網(wǎng)站怎么在百度做推廣看今天的新聞
  • 簡(jiǎn)單的手機(jī)網(wǎng)站模板下載國(guó)內(nèi)企業(yè)網(wǎng)站模板
  • 網(wǎng)頁美工設(shè)計(jì)課程谷歌優(yōu)化師
  • 網(wǎng)站500m空間夠用嗎seo快速排名源碼
  • 手機(jī)設(shè)計(jì)端點(diǎn)seo博客
  • 網(wǎng)站設(shè)計(jì)班培訓(xùn)北京seo網(wǎng)絡(luò)優(yōu)化招聘網(wǎng)
  • 聯(lián)通公司網(wǎng)站誰做的網(wǎng)絡(luò)營(yíng)銷的推廣方法有哪些
  • 網(wǎng)站建設(shè)費(fèi)計(jì)入什么科目代運(yùn)營(yíng)公司排行榜
  • 設(shè)計(jì)網(wǎng)站私單價(jià)格草根seo博客
  • 網(wǎng)站社區(qū)的建設(shè)外鏈生成
  • 商城網(wǎng)站建設(shè)好么百度貼吧怎么做推廣
  • 和一起做網(wǎng)店類似的網(wǎng)站18歲以上站長(zhǎng)統(tǒng)計(jì)
  • 論壇網(wǎng)站建設(shè)流程長(zhǎng)沙網(wǎng)站推廣工具
  • 找個(gè)免費(fèi)的網(wǎng)站這么難嗎網(wǎng)絡(luò)營(yíng)銷方式包括哪些
  • 如果給公司做網(wǎng)站搜索引擎優(yōu)化技術(shù)有哪些
  • 網(wǎng)站建設(shè)公司源碼網(wǎng)絡(luò)銷售的工作內(nèi)容
  • 帝國(guó)怎么做中英文網(wǎng)站百度seo建議
  • 佛山用戶網(wǎng)站建設(shè)廣州推廣引流公司
  • 福建省建設(shè)廳網(wǎng)站怎么推廣軟件
  • 網(wǎng)站下載下來怎么做后臺(tái)廣東網(wǎng)站營(yíng)銷seo方案
  • wordpress mohtmlseo搜索引擎優(yōu)化方案
  • 計(jì)算機(jī)網(wǎng)絡(luò)技術(shù)就業(yè)方向網(wǎng)站開發(fā)中國(guó)萬網(wǎng)域名注冊(cè)服務(wù)內(nèi)容
  • 蒲城做網(wǎng)站鄭州seo代理外包公司
  • 做外貿(mào)雨傘到什么網(wǎng)站拼多多seo 優(yōu)化軟件
  • 網(wǎng)站怎么做的支付推廣賺錢軟件
  • 網(wǎng)站建設(shè)的電話回訪關(guān)鍵詞搜索量全網(wǎng)查詢
  • 硬件開發(fā)軟件寧波seo推薦
  • 設(shè)計(jì)企業(yè)網(wǎng)絡(luò)方案的五個(gè)步驟百度排名優(yōu)化專家
  • 可以看女人不易做網(wǎng)站友情鏈接有用嗎