jfinal整合websocket 服务器向浏览器推送通知

最近,需要公司需要写一个app下单之后,后台要接收到提醒的功能,需要服务器向浏览器推送下单提醒通知。查了好多资料,中间也是遇到了一些坑,所以在这里记录一下。第一次写博客,有不对的地方,希望大牛指正。

一、要做的准备工作:

1.将项目放在tomcat里面

2.下载一个wepsockt-api的jar包

3.新建一个websocketController

4.新建一个indexConter和一个test页面(这里因为涉及到 公司的私密,所以暂时搞了个test页面)

二、wepsockt-api.jar包下载

下载地址:https://download.csdn.net/download/zixing2000/10317413

三.websocketContrller代码

package com.mult.work.websocket;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

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;

import com.jfinal.kit.Kv;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;


@ServerEndpoint("/websocket.ws/{ids}")
public class WebSocketController {

    public static final WebSocketController me = new WebSocketController();
  //用来存放每个客户端对应的MyWebSocket对象。
    private static final Map<String, WebSocketController> WEB_SOCKET_MAP = new ConcurrentHashMap<String, WebSocketController>();
    private static final Map<String, Kv> WEB_KV = new ConcurrentHashMap<String, Kv>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    //UUID 生成的IDS
    private String ids;
    //name 昵称
    private String name;
    
    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("ids")String ids,Session session){
    	this.ids = ids;
        this.session = session;
        WEB_SOCKET_MAP.put(ids, this);
        this.name = getKvByIds(ids).getStr("name");
        
        System.out.println("session=" + session.getId());
        
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
    	WEB_SOCKET_MAP.remove(this.session);
    	System.out.println("有一连接关闭!当前在线人数为" + WEB_SOCKET_MAP.size());
    	System.out.println("session=" + session.getId());
        
        sendMessage(this.name);
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    	System.out.println("来自客户端的消息:" + message);
    	System.out.println("session=" + session.getId());
        sendMessage(message);
    }

    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        error.printStackTrace();
    }
    /**
     * 指定 发送消息
     */
    public void sendMessage(String ids, String message){
    	WebSocketController me = WEB_SOCKET_MAP.get(ids);
    	if (me != null) {
    		me.sendMessage(message);
		}
//    	else{
//			this.sendMessage("【系统消息】" + getNameByIds(ids) + " 不在线");
//		}
    }
    
    /**
     * 向客户端 发送消息
     */
    protected void sendMessage(String message){
        try {
			this.session.getBasicRemote().sendText(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
        //this.session.getAsyncRemote().sendText(message);
    }
    
    public static Kv getKvByIds(String ids){
    	Kv kv = WEB_KV.get(ids);
    	if (kv == null) {
			WEB_KV.put(ids, new Kv());
			return getKvByIds(ids);
		}
		return kv;
    }
    
    public static String getNameByIds(String ids){
    	return getKvByIds(ids).getStr("name");
    }
    
    public static String setNameByIds(String ids, String name){
    	if (StrKit.isBlank(name)) {
    		name = "匿名用户";
    	}
    	Kv kv = getKvByIds(ids);
    	if ( ! name.equals(kv.get("name"))) {
    		kv.set("name", name);
    		// 同步成员变量
    		WebSocketController me = WEB_SOCKET_MAP.get(ids);
    		if (me != null) {
				me.name = name;
			}
		}
    	return name;
    }
}

@ServerEndpoint("/websocket.ws/{ids}")因为这里没有在config里面配置,所以要在路由这里加上一个.ws的后缀,不然的话会报404的错

 四、indexController文件代码段

package com.mult.work.websocket;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.mult.common.annotation.Controller;
import com.mult.common.controller.WorkController;

/**
 * 总控制器
 * @author dufuzhong
 *
 */
@Controller(controllerKey = "/websocket/index")
public class IndexController extends WorkController {
	/***
	 * 设置昵称
	 */
	public void getwebsocket(){
		String host = getPara("host");
		String name = getPara("name");
		String ids = getPara("ids");
		
		if (StrKit.isBlank(ids)) {
			ids = StrKit.getRandomUUID();
			setCookie("websocket_ids", ids, (3 * 365 * 24 * 60 * 60), true);
		}
		
		name = WebSocketController.setNameByIds(ids, name);
		setCookie("websocket_name", encode(name), (3 * 365 * 24 * 60 * 60), true);
		
		renderJson(Ret.ok("url", "ws://" + host + "/websocket.ws/" + ids));
	}

	private String encode(String name){
		if (StrKit.notBlank(name)) {
			try {
				return URLEncoder.encode(name, "utf-8");
			} catch (UnsupportedEncodingException e) {}
		}
		return null;
	}
	
	private String decode(String name){
		if (StrKit.notBlank(name)) {
			try {
				return URLDecoder.decode(name, "utf-8");
			} catch (UnsupportedEncodingException e) {}
		}
		return null;
	}
	
}

五、test页面代码段

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- for HTML5 -->
<title>Java后端WebSocket的Tomcat实现</title>
</head>
<body>
	Welcome
	<br />
	<input id="text" type="text" />
	<button onclick="send()">发送消息</button>
	<hr />
	<button onclick="closeWebSocket()">关闭WebSocket连接</button>
	<hr />
	<div id="message"></div>
</body>
<script type="text/javascript">
	var websocket = null; //判断当前浏览器是否支持WebSocket
	var name = $("#name").val();
	var host = window.location.host;//+window.location.pathname;
	$.getJSON("/websocket/index/getwebsocket", { "name": name, "host": host,"ids":88 }, function(ret){
        if(ret.state == "ok") {
       	    newWebSocket(ret.url);
        }else{
            alert('抱歉,失败')
        }
    });
	 function newWebSocket(url){
		    if ('WebSocket' in window) {
		        websocket = new WebSocket(url);
		    } else {
		        alert('请使用火狐或谷歌浏览器')
		        return;
		    }
		    //连接发生错误的回调方法
		    websocket.onerror = function () {
		        setMessageInnerHTML("离线");
		    }

		    //连接成功建立的回调方法
		    websocket.onopen = function () {
		        setMessageInnerHTML("上线");
		    }

		    //接收到消息的回调方法
		    websocket.onmessage = function (event) {
		        setMessageInnerHTML(event.data);
		    }

		    //连接关闭的回调方法
		    websocket.onclose = function () {
		        setMessageInnerHTML("下线");
		    }

	    }

	//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
	window.onbeforeunload = function() {
		closeWebSocket();
	} 
	//将消息显示在网页上
	function setMessageInnerHTML(innerHTML) {
		document.getElementById('message').innerHTML += innerHTML + '<br/>';
	} 
	//关闭WebSocket连接
	function closeWebSocket() {
		websocket.close();
	} 
	//发送消息
	function send() {
		var message = document.getElementById('text').value;
		websocket.send(message);
	}
</script>
</html>

六、总结

1.公司服务器用的是tomcat和nginx反代理,所以在配置的时候要注意下配置nginx的配置。

参考这个连接:https://www.cnblogs.com/lxwphp/p/8206269.html

2.websocket-api.jar包在服务器环境中可以不要,但是在开发环境中需要,不然的话会报错的。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值