微信小程序整合WebScoket部署上线
在部署的服务器 中安装nginx,并作出如下配置:
思路:
此处监听的是外部的443端口和xcxapi.wfeifei.com域名,当通过该域名和端口号进行访问时,Nginx就会反向代理到,自己项目的端口和服务器上,所以此处项目使用的端口是8081,不可与Nginx监听的端口一样,否则就会冲突
server
{
listen 443 ssl;#监听外部访问的443
server_name xcxapi.wfeifei.com;#监听外部访问的域名
#此处的SSL证书使用的是Nginx的配置方式,使用这种方式,就可以不使用tomacat的配置了
#在nginx的目录下创建,cert文件夹,将对应证书文件放过来,这一步不会的可以百度:Nginx配置SSL证书,或者参考阿里云官网
ssl_certificate /usr/local/nginx/cert/5769555_xcxapi.wfeifei.com.pem;
ssl_certificate_key /usr/local/nginx/cert/5769555_xcxapi.wfeifei.com.key;
#上面两项需要替换为自己的SSL证书
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
#wss协议跳转ws
#注:这里我的webscoket的接口地址会附在下面,可作为参考
location /websocket/ {
proxy_pass http://xcxapi.wfeifei.com:8081/websocket/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 600s; #后端服务器处理请求的时间,即webscoket多久会自动断开连接
}
#反向代理接口API
#这里配置的就是项目所有的接口,将接口反向代理出去
location / {
proxy_pass http://xcxapi.wfeifei.com:8081;
proxy_set_header Host $host:$server_port;
}
}
webscokst 服务端代码:
import com.hk.frame.dao.model.JyftMessageLogging;
import com.hk.frame.service.IMService;
import com.hk.frame.util.EmojiFilter;
import com.hk.frame.util.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.apache.commons.lang3.StringUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author:wf
* @Date 2021/5/14 13:55
* 消息收发
**/
@Controller
@ServerEndpoint(value = "/websocket/{senderID}")
public class ChatWebSocket {
/**处理消息的业务类,这个是自己编写的*/
private static IMService imService;
@Autowired
public void setChatService(IMService imService) {
ChatWebSocket.imService = imService;
}
/** 当前在线连接数。应该把它设计成线程安全的 */
private static int onlineCount = 0;
/** 存放每个客户端对应的MyWebSocket对象。实现服务端与单一客户端通信的话,其中Key可以为用户标识 */
private static ConcurrentHashMap<String, ChatWebSocket> webSocketSet = new ConcurrentHashMap<String, ChatWebSocket>();
/** 与某个客户端的连接会话,需要通过它来给客户端发送数据 */
private Session WebSocketsession;
/** 当前发消息的人员编号 */
private String senderID = "";
/**
* 连接建立成功调用的方法
* @param param 发送者ID,是由谁发送的
* @param WebSocketsession 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam(value = "senderID") String param, Session WebSocketsession) {
System.out.println("人员编号:"+param+":加入聊天");
//接收到发送消息的人员编号
senderID = param;
System.out.println("senderID:"+senderID);
this.WebSocketsession = WebSocketsession;
//加入map中,绑定当前用户和socket
webSocketSet.put(param, this);
//在线数加1
addOnlineCount();
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
if (StringUtils.isNotBlank(senderID)) {
//从set中删除
webSocketSet.remove(senderID);
//在线数减1
subOnlineCount();
}
}
/**
* 收到客户端消息后调用的方法
*
* @param content 客户端发送过来的消息
* @param session 可选的参数
*/
@SuppressWarnings("unused")
@OnMessage
public void onMessage(String content, Session session) {
//给指定的人发消息
//这里的JsonUtil和JyftMessageLogging都是自己类,目的在于,将数据反序列化成对象
sendToUser(JsonUtil.fromJson(content,JyftMessageLogging.class),content);
//群发消息
//sendAll(message);
}
/**
* 给指定的人发送消息
*
* @param chatMsg 消息对象
*/
public void sendToUser(JyftMessageLogging chatMsg,String msgContent) {
//获取接收者ID
String recipientId = chatMsg.getRecipientId();
//获取消息内容
String messageContent = chatMsg.getMessageContent();
try {
if (webSocketSet.get(recipientId) != null) {
//这里,我将消息添加至我自己的缓存,避免发送一条存储一条,消耗性能
imService.setMsgCache(chatMsg);
webSocketSet.get(recipientId).sendMessage(msgContent);
}else{
//设置读取状态为未读
chatMsg.setReadStatus("0");
//这里,我将消息添加至我自己的缓存,避免发送一条存储一条,消耗性能
imService.setMsgCache(chatMsg);
//用户不在线时先将这条消息存到数据库
Map<String,Object> param=new HashMap<>();
param.put("friendRelationshipID",chatMsg.getFriendRelationshipID());
imService.addChatLogService(param);
webSocketSet.get(senderID).sendMessage("0"+"|"+"当前用户不在线");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 给所有人发消息
*
* @param message 消息内容
*/
private void sendAll(String message) {
String sendMessage = message.split("[|]")[1];
//遍历HashMap
for (String key : webSocketSet.keySet()) {
try {
//判断接收用户是否是当前发消息的用户
if (!senderID.equals(key)) {
webSocketSet.get(key).sendMessage(sendMessage);
System.out.println("key = " + key);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
/**
* 为指定用户发送消息
*
* @param message 消息内容
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
//加同步锁,解决多线程下发送消息异常关闭
synchronized (this.WebSocketsession){
this.WebSocketsession.getBasicRemote().sendText(message);
}
}
/**
* 获取当前在线人数
* @return 返回当前在线人数
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 增加当前在线人数
*/
public static synchronized void addOnlineCount() {
ChatWebSocket.onlineCount++;
}
/**
* 减少当前在线人数
*/
public static synchronized void subOnlineCount() {
ChatWebSocket.onlineCount--;
}
}
springboot中配置webscoket
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @Author:wf
* @Date 2021/5/14 13:50
**/
@Configuration
@EnableWebSocket
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
前端连接:
//此处的id为用户ID
wx.connectSocket({
url: 'wss://xcxapi.wfeifei.com/websocket/' + id,//线上地址
//如需本地测试,就使用如下配置,注意是ws协议,不是wss,因为小程序要求使用wss,等同于要求使用https是一个道理,所以本地开发需要使用ws,上线后换成wss
//url: `ws://本地IP:本地端口号/websocket/` + id, //本地
success: function () {
console.log('websocket连接成功~')
},
fail: function () {
console.log('websocket连接失败~')
},
})
自此,就成功了。希望对大家有帮助