场景应用:客户端下订单后需要即时通知后台,弹框提示有新订单生成
解决办法:1、以前采用技术是轮询方式,浏览器以特定的时间间隔(如每隔1秒)向服务器(ajax方式)发送请求,这种方式缺点就是需要不断向服务器发送请求,耗用服务器资源;
2、采用websocket方式,浏览器和服务器只需要做个一握手动作,然后二者之间就形成了一条快速通道,这就好比说我和你握手,我如果有个什么晃动,你那儿马上也感知到了。这样的好处就是服务器不再被动接受浏览器的请求,而是只要有新数据就主动发送给浏览器,并且不用占用大量资源。
下面举个简单的例子:
第一步:浏览器端代码
function orderTips(pa1,pa2,pa3) {//pa1,pa2,pa3是建立握手之初发送服务器的参数
var webSocket = new WebSocket("ip:port/webProjectName/websocket/'+pa1+'/'+pa2+'/'+pa3);
webSocket.onerror = function(event) {
onError(event)
};
webSocket.onopen = function(event) {
onOpen(event)
};
webSocket.onmessage = function(event) {
onMessage(event)
};
//接收服务端发送过来的信息
function onMessage(event) {
var type = event.data;
if(type == '1'){
//业务1;
}else if(type == '2'){
//业务2;
}else{
//业务3
}
}
function onOpen(event) {
}
function onError(event) {
}
function start() {
return false;
}
}
第二步:服务器端,建立WebSocket类
@ServerEndpoint(value = "/websocket/{pa1}/{pa2}/{pa3}")
public class WebSocket {
//当前在线数
private static int onlineCount = 0;
//set集合保存websocket实例
private static CopyOnWriteArraySet<WebSocket> wsSet = new CopyOnWriteArraySet<WebSocket>();
private Session session;
/**
* 接收到客户端发来的消息并处理,同时也向客户端发送消息
*/
@OnMessage
public void onMessage(String message , Session session)
throws IOException, InterruptedException {
this.session = session;
System.out.println("**********客户端发来的消息**********: " + message);
System.out.println("**********websocket数量*********:" + wsSet.size());
//群发消息
for(WebSocket ws : wsSet){//循环websocket过滤权限
if() {//权限范围之内接收消息提示
ws.sendMessage(message);
}
}
}
/**
* 发送消息给客户端
* @param message
*/
public void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message);
System.out.println("****websocket发送消息****:" + message);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 客户端新建websocket时触发
* 并加入当前的set集合中
* @param session
*/
@OnOpen
public void onOpen (@PathParam("pa1") String pa1,@PathParam("pa2")String pa2,Session session) {
this.session = session;
this.setPa1(pa1);
this.setPa2(Pa2);
wsSet.add(this);//加入集合
addOnlineCount();//在线人数+1
}
/**
* 连接关闭时wsSet删除,并且连接数-1
*/
@OnClose
public void onClose () {
wsSet.remove(this); //删除
subOnlineCount(); // 在线人数-1
}
/**
* websocket错误的时候丢出一个异常
* @param session
* @param throwable
*/
@OnError
public void wsError(Session session, Throwable throwable) { throw new IllegalArgumentException(throwable);
System.out.println("onError");
}
/**
* 有新订单时触发该方法,并调用onMessage发送通知给浏览器端
* @param msg
*/
public void triggerEvent(String msg,String pa1) {
try {
this.pa1 = pa1;
onMessage(msg, session);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取当前连接数量
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 线上人数+1
*/
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
/**
* 线上人数-1
*/
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
private String pa1;
private String pa2;
public String getPa1() {
return pa1;
}
public void setPa1(String pa1) {
this.pa1 = pa1;
}
public String getPa2() {
return pa2;
}
public void setPa2(String pa2) {
this.pa2 = pa2;
}
}
第三步:客户端在下订单调用接口后起线程调用WebSocket里的triggerEvent方法
public String subOrder(){//提交订单接口
new Thread(new Websockets("参数")).start(); //起线程通知后台有新订单
}
class Websockets implements Runnable{
private String pa1;
public Websockets (String pa1){
this.pa1 = pa1;
}
@Override
public void run() {
WebSocket nn = new WebSocket();
try {
nn.triggerEvent("3",pa1); //1、2、3订单类型,pa1可能用到的参数
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结一下,上面的应用情形比较简单,也只是个人结合网上资料做的一个小例子,经过实证可以运行,有什么不对的地方还希望过往看客能够指正