websocket 实现A操作后B提示
需求:
1 A 创建一张表单后,需要向B发送消息提示需要审核;
2 审核提示只需要B界面显示,A界面或其他用户界面不显示;
实现:
1.后端server:
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
@ServerEndpoint("/webSocketServer/{userId}")
public class WebSocketServer {
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
* @throws IOException
*/
@OnOpen
public void onOpen(@PathParam("userId") String userId, Session session) throws IOException{
this.session = session;
webSocketSet.add(this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(@PathParam("userId") String userId,Session session)throws IOException{
webSocketSet.remove(this); //从set中删除
//SocketUtils.remove(userId,session.getId());
System.out.println("Connection closed");
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
* @throws IOException
*/
@OnMessage
public void onMessage(@PathParam("userId") String userId,String message, Session session) throws IOException {
// Send the first message to the client
String response = message +",待审核";
//群发消息
for(WebSocketServer item: webSocketSet){
try {
item.sendMessage(response);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
error.printStackTrace();
}
/**
* 发送消息,实践表明,每次浏览器刷新,session会发生变化。
* @param session
* @param message
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
}
}
后端说明:
1. 我用的是websocket 1.1版本;依赖如下(也可以直接去maven仓库下):
<!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
2. 后端重点:
- onopen(): 建立连接时,需要将seesion存入set中,因为不同客户端对应不同session,所以想要实现向客户端发送消息,就需要保存这些客户端的session;
- onMessage(): 这个方法就是后端接收到前端传来的消息的地方,收到消息就可以对前端做出响应了,其中sendMessage()就是通过 this.session.getBasicRemote().sendText(message);向指定session发送消息;
- onClose(): 这个方法中需要注意的是,每次客户端关闭连接后,一定需要从set中移除session,否则会报错(因为发消息时找不到这个地址)
- onError(): 我没用上。。暂时不管
2 . 前端实现:
- 首先是A页面,我设计是在ajax请求成功后的回调函数中向后端发送一些信息,表示当前干了什么事情,这样便于后端返回信息给B页面;
- 然后B页面就只需要建立连接,接收消息就行,所以我直接写在script中就行;
A页面前端代码如下:
//建立websocket连接
var websocket =null;
if('WebSocket' in window){
var userId = ''+${user_context.userId};
// 地址格式: ws:// 后端websocket的请求地址
//PS: 就是后端对应这个注解,这个就类似mapping@ServerEndpoint("/webSocketServer/{userId}")
websocket = new WebSocket('ws://XXX/XXX/'+userId);
}else {
alert('您的浏览器不支持websocket。');
}
// websocket往后台服务器发送消息.
websocket.onopen = function (event) {
var sendmsg = "商务报价申请表更新";
// 发送至后台服务器中.
websocket.send(sendmsg);
}
A页面前端代码说明:
- 省略了ajax请求,这个是写在success()回调函数中的;
- A页面只需要onopen()方法建立连接将消息传到后端就可以了,不需要接收消息;
B页面代码:
<script type="text/javascript">
//建立websocket连接
var websocket =null;
if('WebSocket' in window){
var userId = ''+${user_context.userId};
//这个地方写的是后端websocket请求地址;
//PS: 就是后端对应这个注解,这个就类似mapping@ServerEndpoint("/webSocketServer/{userId}")
websocket = new WebSocket('ws://XXX/XXX/'+userId);
}else {
alert('您的浏览器不支持websocket。');
}
websocket.onopen = function (event) {
//alert('建立连接');
console.log(event);
}
websocket.onclose = function (event) {
alert('连接关闭');
}
websocket.onmessage = function (event) {
// 这里就是前端接收消息的地方,我做了一个判断,指定了谁可以接收到,忽略它。。。。
var userId = ${user_context.userId}
if(userId == 140){
alert('收到消息:'+event.data)
}
}
websocket.onerror = function () {
alert('websocket通信发生错误');
}
websocket.onbeforeunload = function(){
websocket.close();
}
</script>
结束!!!