基于websocket技术的网页弹幕实现
2017-02-17 17:35
197 查看
前言:本弹幕是基于websocket技术实现的网页弹幕,需要HTML5技术支持。具备如下功能:
1、打开弹幕,从数据库里读取历史弹幕;
2、一个客户端发送弹幕,所有的客户端均可以看到。
具体实现:
网页端:
index.jsp
这一段jsp代码部分借鉴了潭州学院Array老师的弹幕页面,在此表示感谢。
通过研究上面一段代码可以发现,里面设置了websocket.js的定时加载并且加载了jquery-1.11.1.min.js。后一个.js文件可以在网上下到,只要把它放在对应的路径下就可以了。下面提供websocket.js的代码。
websocket.js
观察websocket.js,可知在开始的时候实例化了一个Websocket类,构造方法中传入的参数是”ws://192.168.50.155:8080/Danmu01/websocket”,代表项目所在服务器的ip地址+端口号+项目名+websocket,其中websocket对应服务端代码中@ServerEndpoint(“/websocket”)的websocket。
服务端代码:
研究服务端代码,我们可以发现在初始的时候new了一个CopyOnWriteArraySet,通过的他的泛型可知他是保存websocket.js中新建的Websocket对象的。因为有一个客户端开始了弹幕就触发websocket.js中的onOpen方法,也就有了一个新的session,也就执行了服务端的onOpen方法,所以,在服务端的onOpen方法中,就要将新的session加入到CopyWriteArraySet中,并且在此时要读取数据库中的历史弹幕到前台。所以在onOpen中调用了onMessage方法,将数据库中的历史弹幕数据呈现到前台。这里要注意一点是读取历史弹幕数据的时候要使用this.session.getBasicRemote().sendText(msg);
onMessage方法是有新弹幕信息的时候自动调用的,这里在onOpen方法中调用他是为了让他读出历史弹幕信息。onMessage中的for循环就是用来将一个客户端发送的新消息推送到每一个session(即客户端)。
1、打开弹幕,从数据库里读取历史弹幕;
2、一个客户端发送弹幕,所有的客户端均可以看到。
具体实现:
网页端:
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html> <html> <head> <title>index.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <meta name="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> <style type="text/css"> body { background: url(images/01.jpg); no-repeat top center; font-size: 12px; font-family: "微软雅黑"; } * { margin: 0; padding: 0; } /* screen start*/ .screen { width: 300px; height: 100px; background: #669900; } .dm { width: 100%; height: 100%; position: absolute; top: 0; left: 0; display: none; } .dm .d_screen .d_del { width: 38px; height: 38px; background: #600; display: block; text-align: center; line-height: 38px; text-decoration: none; font-size: 20px; color: #fff; border-radius: 19px; border: 1px solid #fff; z-index: 2; position: absolute; right: 20px; top: 20px; outline: none; } .dm .d_screen .d_del:hover { background: #F00; } .dm .d_screen .d_mask { width: 100%; height: 100%; background: #000; position: absolute; top: 0; left: 0; opacity: 0.6; filter: alpha(opacity = 60); z-index: 1; } .dm .d_screen .d_show { position: relative; z-index: 2; } .dm .d_screen .d_show div { font-size: 26px; line-height: 36px; font-weight: 500; position: absolute; top: 76px; left: 10; color: #fff; } /*end screen*/ /*send start*/ .send { width: 100%; height: 76px; position: absolute; bottom: 0; left: 0; border: 1px solid red; } .send .s_filter { width: 100%; height: 76px; background: #000; position: absolute; bottom: 0; left: 0; opacity: 0.6; filter: alpha(opacity = 60); } .send .s_con { width: 100%; height: 76px; position: absolute; top: 0; left: 0; z-index: 2; text-align: center; line-height: 76px; } .send .s_con .s_text { width: 800px; height: 36px; border: 0; border-radius: 6px 0 0 6px; outline: none; } .send .s_con .s_submit { width: 100px; height: 36px; border-radius: 0 6px 6px 0; outline: none; font-size: 14px; color: #fff; background: #65c33d; font-family: "微软雅黑"; cursor: pointer; border: 1px solid #5bba32; } .send .s_con .s_submit:hover { background: #3eaf0e; } /*end send*/ </style> </head> <body> <form> <a href="#" id="startDm">开启弹幕</a> <!-- dm start --> <div class="dm"> <!-- d_screen start --> <div class="d_screen"> <a href="#" class="d_del">X</a> <div class="d_mask"></div> <div class="d_show"> </div> </div> <!-- end d_screen --> <!-- send start --> <div class="send"> <div class="s_filter"></div> <div class="s_con"> <input type="text" class="s_text" maxlength="30"/><input type="button" value="发表评论" class="s_submit" id="btn"/> </div> </div> <!-- end send --> </div> <!-- end dm--> </form> <!-- <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script> --> <script src="js/jquery-1.11.1.min.js" type="text/javascript" charset="utf-8"></script> <!-- <script type="text/javascript" src="websocket.js" id="websocket"> </script> --> <script type="text/javascript"> $(function() { $("#startDm").click(function() { $("#startDm,.dm").toggle(1000); window.setTimeout(function(){ // reference to <head> var head = document.getElementsByTagName('head')[0]; // a new CSS /* var css = document.createElement('link'); css.type = "text/css"; css.rel = "stylesheet"; css.href = "new.css"; */ // a new JS var js = document.createElement("script"); js.type = "text/javascript"; js.src = "websocket.js"; // preload JS and CSS /* head.appendChild(css); */ head.appendChild(js); // preload image /* new Image().src = "new.png"; */ }, 1000) ; /* window.setTimeout("document.getElementById('websocket').src='websocket + js.js'" , 1000) ; */ /* var websocket=null; var _top=80; var index=0; e36a var host=window.location.host; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket=new WebSocket("ws://192.168.50.155:8080/Danmu01/websocket"); } else{ alert("Not Support WebSocket!"); } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(){ setMessageInnerHTML("open"); } //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event); } //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ $(".d_show").append("<div id='"+index+"'>"+ innerHTML.data + "</div>"); launch(); } //发送消息 function send(){ //var message = document.getElementById('text').value; var message = $(".s_text").val(); alert(message); websocket.send(message); } */ //init_screen(); }); $(".d_del").click(function() { $("#startDm,.dm").toggle(1000); //init_screen(); }); $("#btn").click(function(){ send(); }); $(".s_text").keydown(function() { var code = window.event.keyCode; if (code == 13)//回车键按下时,输出到弹幕 { send(); } }); }); /* $("#startDm").click(function() { alert("forEach^^^") ; <c:forEach var="danmu" items="${allDanmu}"> alert("进入forEach循环" + ${danmu.danmuInfo}) ; $(".d_show").append("<div id='"+index+"'>"+ ${danmu.danmuInfo} + "</div>"); </c:forEach> }) ; */ function launch() { var _height = $(window).height(); var _left = $(window).width() - $("#"+index).width(); var time=10000; if(index%2==0) time=20000; _top+=80; if(_top>_height-100) _top=80; $("#"+index).css({ left:_left, top:_top, color:getRandomColor() }); $("#"+index).animate({ left:"-"+_left+"px"}, time, function(){}); index++; } /* //初始化弹幕 function init_screen() { var _top = 0; var _height = $(window).height(); $(".d_show").find("div").show().each(function() { var _left = $(window).width() - $(this).width(); var time=10000; if($(this).index()%2==0) time=20000; _top+=80; if(_top>_height-100) _top=80; $(this).css({ left:_left, top:_top, color:getRandomColor() }); $(this).animate({ left:"-"+_left+"px"}, time, function(){}); }); } */ //随机获取颜色值 function getRandomColor() { return '#' + (function(h) { return new Array(7 - h.length).join("0") + h })((Math.random() * 0x1000000 << 0).toString(16)) } </script> </body> </html>
这一段jsp代码部分借鉴了潭州学院Array老师的弹幕页面,在此表示感谢。
通过研究上面一段代码可以发现,里面设置了websocket.js的定时加载并且加载了jquery-1.11.1.min.js。后一个.js文件可以在网上下到,只要把它放在对应的路径下就可以了。下面提供websocket.js的代码。
websocket.js
var websocket=null; var _top=80; var index=0; var host=window.location.host; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket=new WebSocket("ws://192.168.50.155:8080/Danmu01/websocket");/*("ws://"+host+"/Danmu/websocket");*/ } else{ alert("Not Support WebSocket!"); } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(){ setMessageInnerHTML("open"); } //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event); } //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ $(".d_show").append("<div id='"+index+"'>"+ innerHTML.data + "</div>"); launch(); } /*websocket.onmessage = function(msg) { alert(msg.data); setMessageInnerHTML(msg) ; };*/ //发送消息 function send(){ //var message = document.getElementById('text').value; var message = $(".s_text").val(); /*alert($(".s_text").val("")); alert(message);*/ websocket.send(message); }
观察websocket.js,可知在开始的时候实例化了一个Websocket类,构造方法中传入的参数是”ws://192.168.50.155:8080/Danmu01/websocket”,代表项目所在服务器的ip地址+端口号+项目名+websocket,其中websocket对应服务端代码中@ServerEndpoint(“/websocket”)的websocket。
服务端代码:
package com.danmu.websocket; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet; import com.deyao.danmu.pojo.*; 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 com.deyao.danmu.factory.ServiceFactory; @ServerEndpoint("/websocket") public class MyWebsocket { private static CopyOnWriteArraySet<MyWebsocket> websocketPools=new CopyOnWriteArraySet<MyWebsocket>(); private Session session; boolean index = false ; /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ @OnOpen public void onOpen(Session session) throws Exception{ this.session=session; websocketPools.add(this); index = true ; onMessage("Welcome to DEYAO danmu ^_^" , this.session) ; } /** * 连接关闭调用的方法 */ @OnClose public void onClose(){ websocketPools.remove(this); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message,Session session) throws Exception{ if (index) { Map<String , Object> map = ServiceFactory.getIDanmuServiceInstance() .list(1, 1000, "", "userNickname") ; List<Danmu> list = (List<Danmu>) map.get("allDanmu01") ; for(int i = 0 ; i < list.size() ; i++) { String msg = list.get(i).getDanmuInfo() ; this.session.getBasicRemote().sendText(msg); System.out.println(msg); } index = false ; } else { Danmu danmu = new Danmu() ; danmu.setDanmuInfo(message); danmu.setUserId(null); danmu.setUserNickname(null); ServiceFactory.getIDanmuServiceInstance().insert(danmu); } for(MyWebsocket item:websocketPools) { try { item.send(message); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void send(String message) throws IOException{ this.session.getAsyncRemote().sendText(message); //this.session.getBasicRemote().sendText(message); } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误"); error.printStackTrace(); } }
研究服务端代码,我们可以发现在初始的时候new了一个CopyOnWriteArraySet,通过的他的泛型可知他是保存websocket.js中新建的Websocket对象的。因为有一个客户端开始了弹幕就触发websocket.js中的onOpen方法,也就有了一个新的session,也就执行了服务端的onOpen方法,所以,在服务端的onOpen方法中,就要将新的session加入到CopyWriteArraySet中,并且在此时要读取数据库中的历史弹幕到前台。所以在onOpen中调用了onMessage方法,将数据库中的历史弹幕数据呈现到前台。这里要注意一点是读取历史弹幕数据的时候要使用this.session.getBasicRemote().sendText(msg);
onMessage方法是有新弹幕信息的时候自动调用的,这里在onOpen方法中调用他是为了让他读出历史弹幕信息。onMessage中的for循环就是用来将一个客户端发送的新消息推送到每一个session(即客户端)。
相关文章推荐
- 用于网页判断的智能代理技术的简单实现------------基于python实现(网络爬虫)
- 用SVG技术实现基于Web的GIS
- 基于SIP协议的IP电话增值业务实现技术
- 基于SVG技术实现WebGIS的基本功能(2)
- 权限学习--BlueDavy之技术Blog漫谈权限系统之基于ACL的实现
- 基于Ajax技术实现的下拉数据表格组件
- 基于JavaScript与DBGRID控件的B/S结构客户端联想式录入技术的设计与实现
- 用SVG技术实现基于Web的GIS
- 基于Ajax技术实现的数据表格控件
- 基于图像的OMR技术的实现
- 基于JAVA技术的搜索引擎的研究与实现
- 基于SVG技术实现WebGIS的基本功能(1)
- 基于JAVA技术的搜索引擎的研究与实现
- 用C#实现基于查寻字符串的文件行查询器(2)-相关技术介绍
- 用SVG技术实现基于Web的GIS
- 利用Java技术实现基于XML的Web服务
- 基于SQL SERVER触发器技术的实现
- 基于JAVA技术的搜索引擎的研究与实现
- 基于MATLAB 进行混合编程的接口技术实现
- 基于C++有限状态机的实现技术(调查报告)