springboot整合websocket
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
66套java從入門(mén)到精通實(shí)戰(zhàn)課程分享
一、永恒第一步:導(dǎo)入pom依賴(lài)
???org.springframework.boot
???spring-boot-starter-websocket
???org.webjars
???stomp-websocket
???2.3.3
二、添加配置文件
對(duì)應(yīng)部分的說(shuō)明都寫(xiě)在了注釋里面
package?com.easy.config;
import?com.mbyte.easy.webscoket.consts.GlobalConsts;
import?org.springframework.cache.annotation.EnableCaching;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.messaging.simp.config.MessageBrokerRegistry;
import?org.springframework.web.bind.annotation.CrossOrigin;
import?org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import?org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import?org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
?*?@Author?zte
?*?@Description?Webscoket配置類(lèi)
?*?@Date?21:33?2019/5/6
?**/
@Configuration
@EnableWebSocketMessageBroker
@EnableCaching
@CrossOrigin("*")
public?class?WebSocketStompConfig?implements?WebSocketMessageBrokerConfigurer?{
????@Override
????public?void?configureMessageBroker(MessageBrokerRegistry?config)?{
????????/**
?????????*?配置消息代理
?????????*?啟動(dòng)簡(jiǎn)單Broker,消息的發(fā)送的地址符合配置的前綴來(lái)的消息才發(fā)送到這個(gè)broker
?????????*/
????????config.enableSimpleBroker(GlobalConsts.TOPICPATH,?GlobalConsts.P2PPUSHBASEPATH);
????????config.setUserDestinationPrefix(GlobalConsts.P2PPUSHBASEPATH);
????????config.setApplicationDestinationPrefixes(GlobalConsts.APP_PREFIX);
????}
????@Override
????public?void?registerStompEndpoints(StompEndpointRegistry?registry)?{
????????/**
?????????*?注冊(cè)?Stomp的端點(diǎn)
?????????*?addEndpoint:添加STOMP協(xié)議的端點(diǎn)。這個(gè)HTTP?URL是供WebSocket或SockJS客戶(hù)端訪問(wèn)的地址
?????????*?setAllowedOrigins("*")?允許跨域
?????????*?withSockJS:指定端點(diǎn)使用SockJS協(xié)議
?????????*/
????????registry.addEndpoint(GlobalConsts.ENDPOINT)
????????????????.setAllowedOrigins("*")
????????????????.withSockJS();
????}
}
如果需要跨域,則需要添加跨域設(shè)置
package?com.easy.config;
import?org.springframework.context.annotation.Configuration;
import?org.springframework.web.socket.config.annotation.EnableWebSocket;
import?org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import?org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import?javax.annotation.Resource;
/**
?*?@className:?WebSocketConfig
?*?@description:
?*?@author:?zte
?*?@create:?2020-06-09?16:17
?**/
@Configuration
@EnableWebSocket
public?class?WebSocketConfig?implements?WebSocketConfigurer?{
????@Resource
????private?MyHandShakeInterceptor?handshake;
????@Resource
????private?MyHandler?handler;
????/**
?????*?實(shí)現(xiàn)?WebSocketConfigurer?接口,重寫(xiě)?registerWebSocketHandlers?方法,這是一個(gè)核心實(shí)現(xiàn)方法,配置?websocket?入口,允許訪問(wèn)的域、注冊(cè)?Handler、SockJs?支持和攔截器。
?????*?
?????*?registry.addHandler()注冊(cè)和路由的功能,當(dāng)客戶(hù)端發(fā)起?websocket?連接,把?/path?交給對(duì)應(yīng)的?handler?處理,而不實(shí)現(xiàn)具體的業(yè)務(wù)邏輯,可以理解為收集和任務(wù)分發(fā)中心。
?????*?
?????*?addInterceptors,顧名思義就是為?handler?添加攔截器,可以在調(diào)用?handler?前后加入我們自己的邏輯代碼。
?????*?
?????*?setAllowedOrigins(String[]?domains),允許指定的域名或?IP?(含端口號(hào))建立長(zhǎng)連接,如果只允許自家域名訪問(wèn),這里輕松設(shè)置。如果不限時(shí)使用”*”號(hào),如果指定了域名,則必須要以?http?或?https?開(kāi)頭。
?????*
?????*/
????@Override
????public?void?registerWebSocketHandlers(WebSocketHandlerRegistry?registry)?{
????????//部分?支持websocket?的訪問(wèn)鏈接,允許跨域
????????registry.addHandler(handler,?"/websocket").addInterceptors(handshake).setAllowedOrigins("*");
????????//部分?不支持websocket的訪問(wèn)鏈接,允許跨域
//????????registry.addHandler(handler,?"/sockjs/echo").addInterceptors(handshake).setAllowedOrigins("*").withSockJS();
????}
}
三、WebScoket常量配置
package?com.easy.webscoket.consts;
/**
?*?@program:?easy
?*?@description:?WebScoket常量配置
?*?@author:?zte
?*?@create:?2019-05-06?10:11
?**/
public?class?GlobalConsts?{
????public?static?final?String?TOPIC?=?"/topic/greetings";
????public?static?final?String?ENDPOINT?=?"/gs-guide-websocket";
????public?static?final?String?APP_PREFIX?=?"/app";
????public?static?final?String?HELLO_MAPPING?=?"/hello";
????//點(diǎn)對(duì)點(diǎn)消息推送地址前綴
????public?static?final?String?P2PPUSHBASEPATH?=?"/user";
????//點(diǎn)對(duì)點(diǎn)消息推送地址后綴,最后的地址為/user/用戶(hù)識(shí)別碼/msg
????public?static?final?String?P2PPUSHPATH?=?"/msg";
????/**
?????*?@Description?接收消息地址
?????**/
????public?static?final?String?RECEIVE_MAPPING?=?"/receive";
????/**
?????*?@Description?訂閱消息推送地址前綴
?????**/
????public?static?final?String?TOPICPATH?=?"/group";
????/**
?????*?統(tǒng)一前綴
?????*/
????public?static?final?String?URL_PREFIX?=?"/rest/";
}
四、controller層代碼
這里包含了點(diǎn)對(duì)點(diǎn)聊天以及群聊的配置
package?com.easy.webscoket.controller;
import?com.alibaba.fastjson.JSON;
import?com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import?com.mbyte.easy.common.web.AjaxResult;
import?com.mbyte.easy.detailed_info_log.entity.DetailedInfoLog;
import?com.mbyte.easy.talk_socket.entity.Message;
import?com.mbyte.easy.talk_socket.service.IMessageService;
import?com.mbyte.easy.webscoket.consts.GlobalConsts;
import?com.mbyte.easy.webscoket.vo.ClientMessage;
import?com.mbyte.easy.webscoket.vo.ServerMessage;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.messaging.handler.annotation.MessageMapping;
import?org.springframework.messaging.handler.annotation.SendTo;
import?org.springframework.messaging.simp.SimpMessagingTemplate;
import?org.springframework.stereotype.Controller;
import?org.springframework.ui.Model;
import?org.springframework.web.bind.annotation.GetMapping;
import?org.springframework.web.bind.annotation.RequestMapping;
import?org.springframework.web.util.HtmlUtils;
import?javax.websocket.OnOpen;
import?javax.websocket.Session;
import?javax.websocket.server.PathParam;
import?java.awt.event.MouseWheelEvent;
import?java.util.List;
import?java.util.Map;
import?java.util.concurrent.ConcurrentHashMap;
/**
?*?@program:?easy
?*?@description:?webscoket測(cè)試controller
?*?@author:?zte
?*?@create:?2019-05-06?10:26
?**/
@Controller
@RequestMapping("/audience/index")
public?class?GreetingController?{
????@Autowired
????private?SimpMessagingTemplate?template;
????@Autowired
????private?IMessageService?messageService;
????/**
?????*?在線用戶(hù)的Map集合,key:用戶(hù)名,value:Session對(duì)象
?????*/
????private?static?Map?sessionMap?=?new?ConcurrentHashMap<>();
????/**
?????*?連接建立成功調(diào)用的方法
?????*/
????@OnOpen
????public?void?onOpen(Session?session,?@PathParam("username")?String?username)?{
????????//在webSocketMap新增上線用戶(hù)
????????sessionMap.put(username,?session);
????????System.out.println(username);
????}
????@RequestMapping
????public?String?index(Model?model)?{
????????return?"webscoket/greeting";
????}
????@RequestMapping("/index2")
????public?String?index2(Model?model)?{
????????return?"webscoket/greeting2";
????}
????@MessageMapping(GlobalConsts.HELLO_MAPPING)
????@SendTo(GlobalConsts.TOPIC)
????public?ServerMessage?greeting(ClientMessage?message)?throws?Exception?{
????????//?模擬延時(shí),以便測(cè)試客戶(hù)端是否在異步工作
//????????Thread.sleep(1000);
????????template.convertAndSendToUser(message.getId()?+?"",?GlobalConsts.P2PPUSHPATH,?JSON.toJSON(new?ServerMessage("Hello,?"?+?HtmlUtils.htmlEscape(message.getName())?+?"!")));
????????return?new?ServerMessage("Hello,?"?+?HtmlUtils.htmlEscape(message.getName())?+?"!");
????}
????/**
?????*?群聊
?????*
?????*?@param?message?WebMessage
?????*/
????@MessageMapping("/group")
????public?void?group(Message?message)?{
????????messageService.save(message);
????????template.convertAndSend("/group/"??+?message.getGroupPrefix(),?JSON.toJSON(message));
????}
????@GetMapping("/groupGetMessage")
????public?AjaxResult?groupGetMessage(String?groupPrefix,Integer?groupFlag)?{
????????List?messages?=?messageService.list(new?LambdaQueryWrapper().eq(Message::getGroupPrefix,groupPrefix).eq(Message::getGroupFlag,groupFlag).orderByDesc(Message::getSendTime));
????????return?AjaxResult.success(messages);
????}
}
獲取群聊消息(歷史消息)的接口
package?com.mbyte.easy.rest.message;
import?com.alibaba.fastjson.JSON;
import?com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import?com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import?com.baomidou.mybatisplus.core.metadata.IPage;
import?com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import?com.mbyte.easy.talk_socket.entity.Message;
import?com.mbyte.easy.talk_socket.service.IMessageService;
import?com.mbyte.easy.common.controller.BaseController;
import?com.mbyte.easy.common.web.AjaxResult;
import?com.mbyte.easy.util.PageInfo;
import?io.swagger.annotations.Api;
import?io.swagger.annotations.ApiImplicitParam;
import?io.swagger.annotations.ApiImplicitParams;
import?io.swagger.annotations.ApiOperation;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.messaging.handler.annotation.MessageMapping;
import?org.springframework.messaging.simp.SimpMessagingTemplate;
import?org.springframework.web.bind.annotation.RequestMethod;
import?org.springframework.web.bind.annotation.RestController;
import?org.springframework.ui.Model;
import?org.springframework.web.bind.annotation.*;
import?java.util.List;
import?java.time.LocalDate;
import?java.time.LocalDateTime;
import?java.util.HashMap;
import?java.util.Map;
/**
*?
*?前端控制器
*?
*?@author?zte
*?@since?2019-03-11
*/
@Api(tags?=?"討論聊天記錄接口")
@RestController
@RequestMapping("rest/message")
public?class?RestMessageController?extends?BaseController??{
????@Autowired
????private?IMessageService?messageService;
????/**
?????*?存儲(chǔ)聊天數(shù)據(jù)頁(yè)面
?????*?@return
?????*/
????@ApiOperation(value?=?"聊天記錄添加接口")
????@ApiImplicitParams({
????????????@ApiImplicitParam(name?=?"userId",?value?=?"發(fā)送人",?required?=?true),
????????????@ApiImplicitParam(name?=?"content",?value?=?"聊天內(nèi)容",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupPrefix",?value?=?"房間號(hào)",?required?=?true),
????????????@ApiImplicitParam(name?=?"msgType",?value?=?"消息類(lèi)型",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupFlag",?value?=?"房間類(lèi)型",?required?=?true),
????})
????@GetMapping("addSocketBefore")
????public?AjaxResult?addSocketBefore(String?userId,String?content,String?groupPrefix,Integer?msgType,Integer?groupFlag){
????????Message?message?=?new?Message();
????????message.setFromUser(userId);
????????message.setContent(content);
????????message.setGroupPrefix(groupPrefix);
????????message.setGroupFlag(groupFlag);
????????message.setMsgType(msgType);
????????return?toAjax(messageService.save(message));
????}
????@ApiOperation(value?=?"聊天歷史記錄獲取接口")
????@ApiImplicitParams({
????????????@ApiImplicitParam(name?=?"groupPrefix",?value?=?"房間號(hào)",?required?=?true),
????????????@ApiImplicitParam(name?=?"groupFlag",?value?=?"房間類(lèi)型",?required?=?true),
????})
????@GetMapping("/groupGetMessage")
????public?AjaxResult?groupGetMessage(String?groupPrefix,Integer?groupFlag)?{
????????List?messages?=?messageService.list(new?LambdaQueryWrapper().eq(Message::getGroupPrefix,groupPrefix).eq(Message::getGroupFlag,groupFlag).orderByAsc(Message::getSendTime));
????????return?AjaxResult.success(messages);
????}
五、定義實(shí)體類(lèi)
package?com.easy.talk_socket.entity;
import?com.baomidou.mybatisplus.annotation.TableName;
import?com.mbyte.easy.common.entity.BaseEntity;
import?java.time.LocalDateTime;
import?lombok.Data;
import?lombok.EqualsAndHashCode;
import?lombok.experimental.Accessors;
/**
?*?
?*?
?*?
?*
?*?@author?zte
?*?@since?2020-08-28
?*/
@Data
@EqualsAndHashCode(callSuper?=?true)
@Accessors(chain?=?true)
@TableName("t_message")
public?class?Message?extends?BaseEntity?{
????private?static?final?long?serialVersionUID?=?1L;
????/**
?????*?發(fā)送人
?????*/
????private?String?fromUser;
????/**
?????*?接收人
?????*/
????private?String?toUser;
????/**
?????*?消息內(nèi)容
?????*/
????private?String?content;
????/**
?????*?消息類(lèi)型:1?文字??;2語(yǔ)音;?3圖片;?4?視頻?5?禮物?6邀請(qǐng)入隊(duì)?默認(rèn)為1
?????*/
????private?Integer?msgType;
????/**
?????*?是否已讀,?0:未讀,?1:已讀
?????*/
????private?Integer?readFlag;
????/**
?????*??正常為?0??刪除為1
?????*/
????private?Integer?deleteFlag;
????/**
?????*?發(fā)送時(shí)間
?????*/
????private?LocalDateTime?sendTime;
????/**
?????*?語(yǔ)音時(shí)長(zhǎng)
?????*/
????private?Integer?voiceTime;
????/**
?????*?發(fā)送人昵稱(chēng)
?????*/
????private?String?fromNick;
????/**
?????*?接受人昵稱(chēng)
?????*/
????private?String?toNick;
????/**
?????*?組名稱(chēng)???如:群聊編號(hào),?直播編號(hào),?話題編號(hào)
?????*/
????private?String?groupPrefix;
????/**
?????*?組標(biāo)記,0:是私聊?1:是多人聊天;?3是臨時(shí)會(huì)話;4:是客服聊天
?????*/
????private?Integer?groupFlag;
????/**
?????*?發(fā)送人頭像
?????*/
????private?String?fromMsg;
????/**
?????*?接受人頭像
?????*/
????private?String?toMsg;
????/**
?????*?發(fā)送人的大v圖片
?????*/
????private?String?fromMsgSignV;
????/**
?????*?發(fā)送人的皇冠圖片
?????*/
????private?String?fromMsgSignAnCrown;
????/**
?????*?接受人大v圖片
?????*/
????private?String?toMsgSignV;
????/**
?????*?接受人皇冠圖片
?????*/
????private?String?toMsgSignAnCrown;
????/**
?????*?最佳吐槽???1為最佳吐槽?
?????*/
????private?Integer?bestBlowing;
????/**
?????*?用戶(hù)類(lèi)型??普通用戶(hù):1;客服?2;會(huì)員:3?;超級(jí)會(huì)員?4?;直播人:5;??
?????*/
????private?Integer?userType;
????/**
?????*?平臺(tái)標(biāo)識(shí)
?????*/
????private?String?platCode;
}
六、定義Vo類(lèi)(可選)

package?com.easy.webscoket.vo;
import?lombok.AllArgsConstructor;
import?lombok.Data;
import?lombok.NoArgsConstructor;
/**
?*?@program:?easy
?*?@description:?客戶(hù)端發(fā)過(guò)來(lái)的消息
?*?@author:?zte
?*?@create:?2019-05-06?10:22
?**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public?class?ClientMessage?{
????private?int?id;
????private?String?name;
}
package?com.easy.webscoket.vo;
import?lombok.AllArgsConstructor;
import?lombok.Data;
import?lombok.NoArgsConstructor;
/**
?*?@program:?easy
?*?@description:?服務(wù)端返回消息
?*?@author:?zte
?*?@create:?2019-05-06?10:25
?**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public?class?ServerMessage?{
????private?String?content;
}
七、點(diǎn)對(duì)點(diǎn)聊天(html)
"en">
????"UTF-8">
????Title
????
????
????
"disconnect()">
????
????????
????????
????
????"conversationDiv">
????????type="text"?id="name"?/>
????????
????????"response">
????
八、群聊(html)
"http://www.thymeleaf.org">
????群聊
????"Content-Type"?content="text/html;?charset=UTF-8"?/>
????"viewport"?content="width=device-width,?initial-scale=0.7,?user-scalable=no,?shrink-to-fit=no">
????"stylesheet"?href="/webrtc/css/bootstrap-material-design.min.css">
????
????
"width:?20%;height:?100%;align-items:?initial?!important;background:?#fff;">
????"layui-tab?layui-tab-brief"?lay-filter="docDemoTabBrief"
????????style="width:?100%;display:?block;margin:?0;">
????????"layui-tab-title"?style="display:?flex;justify-content:?center"
????????????lay-filter="queSearch">
????????????- "layui-this">簡(jiǎn)介
????????????- 討論區(qū)
????????
????????"layui-tab-content"?style="display:?block;width:?100%;">
????????????"${introduction}"?class="layui-tab-item?layui-show"
????????????????style="color:?#333;line-height:?20px;font-size:?12px;">
????????????"layui-tab-item"?style="width:?100%;">
????????????????"commentCon">
????????????????????"response">
????????????????
????????????????"inputbottom">
????????????????????type="text"?id="yourMessage"?placeholder="說(shuō)點(diǎn)兒什么"?maxlength="200">
????????????????????
????????????????
????????????????
????????????
????????
????
????
??
????
????
九、對(duì)應(yīng)sql
/*
?Navicat?Premium?Data?Transfer
?Source?Server?????????:?hfky
?Source?Server?Type????:?MySQL
?Source?Server?Version?:?50723
?Source?Host???????????:?49.233.66.170:3306
?Source?Schema?????????:?hfky
?Target?Server?Type????:?MySQL
?Target?Server?Version?:?50723
?File?Encoding?????????:?65001
?Date:?24/09/2020?17:10:39
*/
SET?NAMES?utf8mb4;
SET?FOREIGN_KEY_CHECKS?=?0;
--?----------------------------
--?Table?structure?for?t_message
--?----------------------------
DROP?TABLE?IF?EXISTS?`t_message`;
CREATE?TABLE?`t_message`??(
??`id`?bigint(20)?NOT?NULL?AUTO_INCREMENT,
??`from_user`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人',
??`to_user`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接收人',
??`content`?text?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?COMMENT?'消息內(nèi)容',
??`msg_type`?int(4)?NULL?DEFAULT?1?COMMENT?'消息類(lèi)型:1?文字??;2圖片;?默認(rèn)為1',
??`read_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'是否已讀,?0:未讀,?1:已讀',
??`delete_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'?正常為?0??刪除為1',
??`send_time`?datetime(0)?NULL?DEFAULT?CURRENT_TIMESTAMP(0)?COMMENT?'發(fā)送時(shí)間',
??`voice_time`?int(4)?NULL?DEFAULT?NULL?COMMENT?'語(yǔ)音時(shí)長(zhǎng)',
??`from_nick`?varchar(80)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人昵稱(chēng)',
??`to_nick`?varchar(80)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人昵稱(chēng)',
??`group_prefix`?varchar(20)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'組名稱(chēng)???如:群聊編號(hào),?直播編號(hào),?話題編號(hào)',
??`group_flag`?int(2)?NULL?DEFAULT?0?COMMENT?'組標(biāo)記,1:培訓(xùn)討論;2:會(huì)診直播',
??`from_msg`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人頭像',
??`to_msg`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人頭像',
??`from_msg_sign_v`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人的大v圖片',
??`from_msg_sign_an_crown`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'發(fā)送人的皇冠圖片',
??`to_msg_sign_v`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人大v圖片',
??`to_msg_sign_an_crown`?varchar(255)?CHARACTER?SET?utf8mb4?COLLATE?utf8mb4_general_ci?NULL?DEFAULT?NULL?COMMENT?'接受人皇冠圖片',
??`best_blowing`?int(11)?NULL?DEFAULT?0?COMMENT?'最佳吐槽???1為最佳吐槽?',
??`user_type`?int(11)?NULL?DEFAULT?NULL?COMMENT?'用戶(hù)類(lèi)型??普通用戶(hù):1;客服?2;會(huì)員:3?;超級(jí)會(huì)員?4?;直播人:5;??',
??`plat_code`?varchar(50)?CHARACTER?SET?utf8?COLLATE?utf8_general_ci?NULL?DEFAULT?NULL?COMMENT?'平臺(tái)標(biāo)識(shí)',
??PRIMARY?KEY?(`id`)?USING?BTREE
)?ENGINE?=?InnoDB?AUTO_INCREMENT?=?4044?CHARACTER?SET?=?utf8mb4?COLLATE?=?utf8mb4_general_ci?ROW_FORMAT?=?COMPACT;
SET?FOREIGN_KEY_CHECKS?=?1;
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。
本文鏈接:
http://blog.csdn.net/qq_44922113/article/details/108777548


??? ?
感謝點(diǎn)贊支持下哈?
