2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > WEB消息提醒实现之二 实现方式-websocket实现方式

WEB消息提醒实现之二 实现方式-websocket实现方式

时间:2021-01-20 00:15:50

相关推荐

WEB消息提醒实现之二 实现方式-websocket实现方式

#websocket实现方式

##原理

websocket的原理主要是,利用websocket提供的api,客户端只需要向服务器发起一次连接即可,然后服务器就可以主动地源源不断地向客户端发送数据,只要客户端不关闭浏览器,那么这个连接就会一直保持,从而达到真正意义上的长连接和服务器推。

优点:只需要建立一次连接,服务器就可以源源不断地推送数据,资源消耗少,持久连接

缺点:需要浏览器支持websocket技术

websocket的过程如图:

可以看到,只要客户端不关闭浏览器,连接会一直存在,相对于ajax轮询,这里服务器从被动变为主动,只要服务器喜欢,随时都可以向客户端发送数据。

##实例

websocket最经典的实例就是聊天室了,而且tomcat就自带了websocket聊天室的实例,需要导入websocket-api.jar,这个jar包也可以在tomcat的lib下找到,下面是服务器代码:

package com.myj.websocket.servlet;import java.io.IOException;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import java.util.concurrent.atomic.AtomicInteger;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;//import org.apache.juli.logging.Log;//import org.apache.juli.logging.LogFactory;import util.HTMLFilter;//"/websocket/chat"为客户端发起连接的请求路径@ServerEndpoint(value = "/websocket/chat")public class ChatAnnotation {//private static final Log log = LogFactory.getLog(ChatAnnotation.class);private static final String GUEST_PREFIX = "Guest";private static final AtomicInteger connectionIds = new AtomicInteger(0);private static final Set<ChatAnnotation> connections =new CopyOnWriteArraySet<ChatAnnotation>();private final String nickname;private Session session;public ChatAnnotation() {//每个客户端都有一个昵称nickname = GUEST_PREFIX + connectionIds.getAndIncrement();}/*** 客户端发起连接请求,服务器这边会调用这个start方法,* 将该客户端的session和连接保存,然后向所有客户端广播消息* @param session*/@OnOpenpublic void start(Session session) {this.session = session;connections.add(this);String message = String.format("* %s %s", nickname, "has joined.");broadcast(message);}/*** 如果有客户端关闭浏览器,连接就会断开,服务器会调用end方法,* 将保存在connections集合中的相应客户端连接移除,向剩余的客户端广播该* 客户端下线的消息*/@OnClosepublic void end() {connections.remove(this);String message = String.format("* %s %s",nickname, "has disconnected.");broadcast(message);}/*** 客户端调用send向服务器发送消息的时候,服务器这边会调用incoming方法,* 将该客户端发送的消息向所有客户端进行广播* @param message*/@OnMessagepublic void incoming(String message) {// Never trust the clientString filteredMessage = String.format("%s: %s",nickname, HTMLFilter.filter(message.toString()));broadcast(filteredMessage);}/*** 出现异常时候会调用onError* @param t* @throws Throwable*/@OnErrorpublic void onError(Throwable t) throws Throwable {//log.error("Chat Error: " + t.toString(), t);}/*** 向所有客户端广播消息的方法* @param msg*/public static void broadcast(String msg) {//遍历所有的客户端for (ChatAnnotation client : connections) {try {synchronized (client) {//向客户端推送消息client.session.getBasicRemote().sendText(msg);}} catch (IOException e) {//如果广播的时候出现异常会将该客户端移除,并向剩余的客户端广播消息//log.debug("Chat Error: Failed to send message to client", e);connections.remove(client);try {client.session.close();} catch (IOException e1) {// Ignore}String message = String.format("* %s %s",client.nickname, "has been disconnected.");broadcast(message);}}}}

下面是客户端的代码:

<?xml version="1.0" encoding="UTF-8"?><html xmlns="/1999/xhtml" xml:lang="en"><head><title>Apache Tomcat WebSocket Examples: Chat</title><style type="text/css">input#chat {width: 410px}#console-container {width: 400px;}#console {border: 1px solid #CCCCCC;border-right-color: #999999;border-bottom-color: #999999;height: 170px;overflow-y: scroll;padding: 5px;width: 100%;}#console p {padding: 0;margin: 0;}</style><script type="application/javascript">var Chat = {};Chat.socket = null;//根据浏览器创建相应的websocket实例,并向服务器发起连接Chat.connect = (function(host) {if ('WebSocket' in window) {Chat.socket = new WebSocket(host);} else if ('MozWebSocket' in window) {Chat.socket = new MozWebSocket(host);} else {Console.log('Error: WebSocket is not supported by this browser.');return;}//客户端websocket和服务器建立连接之后会调用onopen方法Chat.socket.onopen = function () {Console.log('Info: WebSocket connection opened.');document.getElementById('chat').onkeydown = function(event) {if (event.keyCode == 13) {Chat.sendMessage();}};};//监听服务器是否关闭,服务器关闭之后会调用onclose方法Chat.socket.onclose = function () {document.getElementById('chat').onkeydown = null;Console.log('Info: WebSocket closed.');};//监听服务器消息,服务器向客户端推送消息的时候,websocket会调用onmessage 方法Chat.socket.onmessage = function (message) {Console.log(message.data);};});//传入url,创建websocket并和服务器建立连接Chat.initialize = function() {if (window.location.protocol == 'http:') {Chat.connect('ws://' + window.location.host + '/WebSocketDemo/websocket/cha t');} else {Chat.connect('wss://' + window.location.host + '/WebSocketDemo/websocket/ch at');}};//发送消息Chat.sendMessage = (function() {var message = document.getElementById('chat').value;if (message != '') {Chat.socket.send(message);document.getElementById('chat').value = '';}});var Console = {};//在消息版面显示服务器发送过来的消息Console.log = (function(message) {var console = document.getElementById('console');var p = document.createElement('p');p.style.wordWrap = 'break-word';p.innerHTML = message;console.appendChild(p);while (console.childNodes.length > 25) {console.removeChild(console.firstChild);}console.scrollTop = console.scrollHeight;});Chat.initialize();document.addEventListener("DOMContentLoaded", function() {// Remove elements with "noscript" class - <noscript> is not allowed in XHTMLvar noscripts = document.getElementsByClassName("noscript");for (var i = 0; i < noscripts.length; i++) {noscripts[i].parentNode.removeChild(noscripts[i]);}}, false);</script></head><body><div class="noscript"><h2 style="color: #ff0000">Seems your browser doesn't support Jav ascript! Websockets rely on Javascript being enabled. Please enableJavascript and reload this page!</h2></div><div><p><input type="text" placeholder="type and press enter to chat" id="chat" /></p><div id="console-container"><div id="console"/></div></div></body></html>

如果要利用websocket按照前面实现消息提醒的话,可以在后来创建一个监听器和定时器,在应用启动的时候就初始化定时器,定时在后台检测数据有没有发生变化,有变化之后随时调用websocket的方法,将数据推送给客户端。

下面是监听器和定时器的代码

监听器

package util;import java.util.Calendar;import java.util.Date;import java.util.Timer;import java.util.TimerTask;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;/*** 系统启动时的监听类 初始化系统数据* */public class InitListener implements ServletContextListener {public void contextDestroyed(ServletContextEvent arg0) {// TODO Auto-generated method stub// context销毁时,销毁初始化数据}public void contextInitialized(ServletContextEvent event) {// TODO Auto-generated method stubtry {System.out.println("初始化监听...");goTimer();System.out.println("初始化完毕");} catch (Exception e) {System.out.println("失败:" + e.getMessage());}}private void goTimer() {Timer timmerTask = new Timer();Calendar calEnviron = Calendar.getInstance();// 每天的02:00.am开始执行calEnviron.set(Calendar.HOUR_OF_DAY, 17);calEnviron.set(Calendar.MINUTE, 01);calEnviron.set(Calendar.SECOND, 00);// date为制定时间Date dateSetter = new Date();dateSetter = calEnviron.getTime();// nowDate为当前时间Date nowDateSetter = new Date();// 所得时间差为,距现在待触发时间的间隔long intervalEnviron = dateSetter.getTime() - nowDateSetter.getTime();if (intervalEnviron < 0) {calEnviron.add(Calendar.DAY_OF_MONTH, 1);dateSetter = calEnviron.getTime();intervalEnviron = dateSetter.getTime() - nowDateSetter.getTime();}//每5秒执行一次timmerTask.schedule(new UseTimer(), intervalEnviron, 5 * 1000);}}

定时器

package util;import java.util.Timer;import java.util.TimerTask;import com.myj.websocket.servlet.ChatAnnotation;/*** 被调用执行类* */public class UseTimer extends TimerTask {private int num = 0;Timer timer = new Timer();public UseTimer(){}public UseTimer(Timer timer) {this.timer = timer;}public Timer getTimer() {return timer;}public void setTimer(Timer timer) {this.timer = timer;}/** 被调用具体的方法*/public void run() {//模拟数据发生变化num++;//调用websocket的接口推送数据ChatAnnotation.broadcast("你有"+num+"条消息!");}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。