mark: 记录学习使用
part1: websocek在项目中的搭建
ssm配置:
websockt依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
websocket配置类
package net.test.websocket;
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
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
public static final String endPoint = "/myapp";
public static final String service_fix = "/ws";
public static final String client_fix = "/wsclient";
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker(client_fix);
config.setApplicationDestinationPrefixes(service_fix);
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(endPoint).setAllowedOrigins("*").withSockJS();
}
}
消息发送类:
package net.test.websocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
@Component
public class WebSocketMessageUtil {
@Autowired
SimpMessagingTemplate msgTemplate;
String default_toAll = "/broadcast";// 默认广播地址
String default_toUser = "/usermsg/";// 默认发送给用户地址前缀
public void sendToAll(String msg, String dest) {
if (dest.indexOf("/") != 0) {
dest = "/" + dest;
}
msgTemplate.convertAndSend(WebSocketConfig.client_fix + dest, msg);// 发送给全部
}
public void sendToAll(String msg) {
msgTemplate.convertAndSend(WebSocketConfig.client_fix + default_toAll, msg);// 发送给全部
}
public void sendToPerson(String msg, String user) {
msgTemplate.convertAndSend(WebSocketConfig.client_fix + default_toUser + user, msg);// 发送给user
}
}
//消息发送
// 获取发送类对象
@Autowired
WebSocketMessageUtil msgUtil;
// 方法调用
msgUtil.sendToPerson(sendInfo.toString(), userid);// 发送给指定用户id
msgUtil.sendToAll(sendInfo.toString()); // 发送给全部用户
前端页面调用:
1 简单封装websocket调用的js
mysocket.js
let myws = function(config) {
this.v = '1.0.0';
this.wsClient = null;
this.endPoint = config.endPoint || "/myapp";
this.wspath = config.wspath || "/ws";
this.wsclient = config.wsclient || "/wsclient";
this.wsbroadcast = "/broadcast";
this.wsusermsg = "/usermsg/";
this.subscribe = config.subscribe || [];// 客户端订阅消息
this.usersub = config.usersub || null;
this.broadcast = config.broadcast || null;
this.error = config.error;
this.debug = config.debug || false;
this.init();
};
myws.prototype.init = function() {
var t = this;
var socket = new SockJS(t.endPoint);
t.wsClient = Stomp.over(socket);
if (!t.debug) {
t.wsClient.debug = null;// 屏蔽日志输出
}
this.wsClient.connect({}, function(frame) {// 连接成功后调用
// 订阅页面单独订阅信息
if (t.subscribe && t.subscribe.length > 0) {
$.each(t.subscribe, function(index, item) {
t.wsClient.subscribe(t.wsclient + item.path, item.handler);
});
}
// 订阅系统广播信息
if (t.broadcast != null) {
t.wsClient.subscribe(t.wsclient + t.wsbroadcast, t.broadcast);
}
// 订阅用户个人信息
if (t.usersub != null) {
var usub = t.wsclient + t.wsusermsg + t.usersub.userid;
t.wsClient.subscribe(usub, t.usersub.handler);
}
}, function(error) {// 连接失败后调用
console.info("myws连接失败")
t.destoryws();
t.error && t.error(error);
});
window.onbeforeunload = function() {
t.destoryws();
console.info("myws连接断开")
}
}
myws.prototype.destoryws = function() {
if (this.wsClient != null) {
this.wsClient.disconnect();
}
};
myws.prototype.sendMsg = function(dest, header, body) {
if (!this.usersub && !body.fromUserid) {
body.fromUserid = this.usersub.userid;
}
if (this.debug) {
console.debug("发送信息:" + JSON.stringify(body));
}
this.wsClient.send(this.wspath + dest, header, JSON.stringify(body));
}
页面调用
// 引入js文件
<script src="/resources/js/sockjs.min.js"></script>
<script src="/resources/js/stomp.min.js"></script>
<script src="/resources/js/mysocket.js"></script>
// 调用js
// 启动websocket,监听系统广播
var ws = new myws({
// debug: true,// 开启消息通讯debug
broadcast: function (res){
res.body && handlerServerMsg(JSON.parse(res.body)); // res.body为后台推送到前端的消息信息,json格式
},
usersub:{
userid:"用户id",
handler: function(res){
res.body && handlerServerMsg(JSON.parse(res.body));// res.body为后台推送到前端的消息信息,json格式
}
}
});
part2: Apache配置转发websocket到tomcat
Apache版本: 2.4.37
httpd.config 配置启用的Apache模块(有些配置可能不需要)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_express_module modules/mod_proxy_express.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
httpd-vhosts.conf 配置
<VirtualHost *:80>
ServerAdmin webmaster@test.test
DirectoryIndex index.jsp
DocumentRoot 项目路径
ServerName test.myapp.com
ServerAlias test.myapp.com
ErrorLog logs/test.domain-error_log
CustomLog logs/test.domain-access_log common
#8080为配置的tomcat的http端口
# 判断请求头的upgrade的值是否为websocket
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule .* ws://localhost:8080%{REQUEST_URI} [P]
#8080为配置的tomcat的http端口,可使用ajp转发
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>