为了让用户能够在浏览器中实时更新消息,所以引入了消息推送。
以下是两种解决方案:
1. 使用spring + websocke
2. 使用Active MQ
下面将介绍这两种的用法
1. 方案1 spring +websocket
1.1 maven的引入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
1.2 编写处理类
public class SockMessage {
private String type;
private String text;
private String date;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
}
/---------------------------------------------------------------------/
public class MyWebSocketHandler implements WebSocketHandler {
//用于存放登录用户信息
private static Map<String,Object> userMap=new HashMap<String,Object>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String id=session.getId();
System.out.println("新增用户:"+id);
userMap.put(id, session);
System.out.println("id:"+id);
int code=session.hashCode();
System.out.println("code="+code);
//客户端链接
}
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
System.out.println(message.getPayload().toString());
String text=message.getPayload().toString();
TextMessage messages=new TextMessage(message.getPayload().toString());
Collection<Object> collect=userMap.values();
for(Object obj:collect) {
WebSocketSession msession=(WebSocketSession)(obj);
msession.sendMessage(messages);
}
}
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("handleTransportError");
}
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
//客户端关闭
String id=session.getId();
int code=session.hashCode();
System.out.println("code="+code);
userMap.remove(id);
System.out.println("删除用户:"+id);
}
@Override
public boolean supportsPartialMessages() {
System.err.println("supportsPartialMessages");
return false;
}
/**
* 供外部接口调用
* @param text
* @return
*/
public static boolean sendMessage(String text){
try {
TextMessage messages=new TextMessage(text);
Collection<Object> collect=userMap.values();
for(Object obj:collect) {
WebSocketSession msession=(WebSocketSession)(obj);
msession.sendMessage(messages);
}
}catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
/--------------------------------------------------------------------------/
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("afterHandshake");
super.afterHandshake(request, response, wsHandler, ex);
}
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("beforeHandshake");
return super.beforeHandshake(request, response, wsHandler, attributes);
}
}
1.3 spring配置文件注册bean
spring-socket.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<!-- websocket处理类 -->
<bean id="myHandler" class="com.sargeraswang.csmframework.websock.MyWebSocketHandler"/>
<!-- 握手接口/拦截器 -->
<bean id="myInterceptor" class="com.sargeraswang.csmframework.websock.HandshakeInterceptor"/>
<websocket:handlers >
<websocket:mapping path="/websocket" handler="myHandler"/>
<websocket:handshake-interceptors>
<ref bean="myInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
<!-- 注册 sockJS -->
<websocket:handlers>
<websocket:mapping path="/sockjs/websocket" handler="myHandler"/>
<websocket:handshake-interceptors>
<ref bean="myInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs />
</websocket:handlers>
</beans>
1.4 前台js编写
引入sockjs-0.3.4.min.js
<script>
var sendMessage=null;
$(function() {
var websocket;
// 首先判断是否 支持 WebSocket
if ('WebSocket' in window) {
console.log("ws://localhost:89/Nbiot/websocket");
websocket = new WebSocket("ws://localhost:89/Nbiot/websocket");
} else if ('MozWebSocket' in window) {
console.log("ws://localhost:89/Nbiot/websocket");
websocket = new MozWebSocket("ws://localhost:89/Nbiot/websocket");
} else {
console.log("http://localhost:89/Nbiot/sockjs/websocket");
websocket = new SockJS("http://localhost:89/Nbiot/sockjs/websocket");
}
// 打开时
websocket.onopen = function(evnt) {
console.log("websocket.onopen");
};
// 处理消息时
websocket.onmessage = function(evnt) {
var text=JSON.parse(evnt.data);
tipMsg(text.text);
//tipAlert(text.text);
//bootbox.alert(text.text);
};
websocket.onerror = function(evnt) {
console.log("websocket.onerror");
};
websocket.onclose = function(evnt) {
console.log(" websocket.onclose ");
};
sendMessage=function(text) {
var msg = {
text : text,
type : 1,
date : new Date().getTime()
};
// 发送消息
websocket.send(JSON.stringify(msg));
};
});
</script>
2. 方案2 使用 activeMQ
2.1 下载activeMQ然后解压运行
2.2编写在activeMQ目录中有一个examples\mqtt\websocket目录下面有一个js/mqttws31.js拷贝到项目中
3. 编写前台js页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="js/jquery-1.7.2.min.js" ></script>
<script type="text/javascript" src="js/mqttws31.js" ></script>
</head>
<body>
<textarea cols="100" rows="5" id="value"></textarea>
<input type="button" id="send" value="发送"/>
<div class="text" style="border: 1px solid #f00;"></div>
</body>
<script>
$(document).ready(function(){
var client;
//需要订阅的消息
var destination="abc";
var host="localhost";
var port=61614;
var clientId="aggg"+Math.floor(Math.random() * 100000);
var user='zhangsan';
var password='123456';
if(!window.WebSocket) {
alert("浏览器不支持websocket");
}else{
//建立连接
client = new Messaging.Client(host, port, clientId);
client.onConnect = onConnect;
client.onMessageArrived = onMessageArrived;
client.onConnectionLost = onConnectionLost;
client.connect({
userName:user,
password:password,
onSuccess:onConnect,
onFailure:onFailure
});
//这个是关闭函数
//client.disconnect();
//这个是发送信息
/*var message = new Messaging.Message("text");
message.destinationName = "123";
client.send(message);*/
$("#send").click(function(){
var value=$("#value").val();
if(value==""){
alert("输入不能为空");
return 0;
}
var message = new Messaging.Message(value);
message.destinationName = destination;
client.send(message);
});
}
function onConnect(frame){
$(".text").append("<p>连接成功</p>")
//当建立连接后需要订阅消息
client.subscribe(destination);
}
});
var onFailure=function(failure){
console.log("连接失败");
console.log(failure);
$(".text").append("<p>连接失败</p>")
}
var onMessageArrived = function(message){
var text=message.payloadString;
$(".text").append("<p>接收到消息:"+text+"</p>")
}
var onConnectionLost=function(responseObject){
$(".text").append("<p>断开连接</p>")
}
</script>
</html>
总结:
使用websocket配置起来要麻烦一些,但是对于但服务器来说,还是可以的,而集群起来比较麻烦。
使用activeMQ配置比较简单,同时也很容易集成到项目中,而且activeMQ的功能也比较强大,也适合使用集群,但是需要额外不是一个activeMQ服务。