基于websocket技术的网页弹幕实现
来源:互联网 发布:java是操作系统吗 编辑:程序博客网 时间:2024/05/18 00:59
前言:本弹幕是基于websocket技术实现的网页弹幕,需要HTML5技术支持。具备如下功能:
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; 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;//判断当前浏览器是否支持WebSocketif('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(即客户端)。
- 基于websocket技术的网页弹幕实现
- 基于WebSocket的网页端即时通讯技术
- 基于WebSocket的网页端即时通讯
- 基于C#弹幕类射击游戏的实现——(七)弹幕类实现
- Android弹幕实现:基于B站弹幕开源系统(7)QQ、微信聊天气泡样式的弹幕
- Android弹幕实现:基于B站弹幕开源系统(7)QQ、微信聊天气泡样式的弹幕
- java web 弹幕技术实现
- 基于VC的网页元素操作实现技术
- 弹幕的简单实现
- Android弹幕的实现
- 基于Tomcat7的websocket的应用实现
- 基于websocket的简易聊天室的实现
- 基于Java的WebSocket的实现
- WebSocket实现网页聊天室
- 基于JQuery的弹幕APP
- 基于Tomcat7.0.29的WebSocket实现
- 基于websocket+java聊天系统的实现
- 基于mina的websocket初步实现
- 安卓开发-简单创建SQLite
- 机器学习——K-近邻(KNN)算法
- easyui 表单验证扩展
- 【JavaEE】经典JAVA EE企业应用实战-读书笔记12
- UML 九种图 炫彩
- 基于websocket技术的网页弹幕实现
- 循环时不可以修改集合元素
- js创建对象的几种模式
- Vuex 模块化与项目实例 (2.0)
- MVC 全局去除空格
- Android面试题收集
- 一致性哈希算法与Java实现
- 一种神奇的数据结构—小波树
- Nodejs Express 连接Mongodb