package happ.two;
import happ.nchche.Cache;
import happ.nchche.CacheManager;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
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;
@ServerEndpoint("/websocket/{roomId}/{userId}")
public class MyWebsocket {
//装载 弹幕
private static Map<String,List> mb = new HashMap<String,List>();
// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet websocketPools = new CopyOnWriteArraySet();
// 与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
/**
* * 连接建立成功调用的方法 * @param session
* 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
// 使用map来收集session,key为roomId,value为同一个房间的用户集合
// concurrentMap的key不存在时报错,不是返回null
private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap<String, Set<Session>>();
@OnOpen
public void connect(@PathParam("roomId") String roomId,@PathParam("userId") String userId, Session session) throws Exception {
// 将session按照房间名来存储,将各个房间的用户隔离
if (!rooms.containsKey(roomId)) {
// 房间不存在时,创建房间
Set<Session> room = new HashSet<Session>();
// 添加用户
room.add(session);
System.err.println(roomId+"333333333333333"+userId);
rooms.put(roomId, room);
List<Cache> ls = new ArrayList<Cache>();
//创建房间聊天
if(!mb.containsKey(roomId)) {
mb.put(roomId,ls);
}
} else {
// 房间已存在,直接添加用户到相应的房间
rooms.get(roomId).add(session);
}
System.out.println(userId+"a client has connected!"+roomId);
}
@OnClose
public void disConnect(@PathParam("roomId") String roomId,@PathParam("userId") String userId, Session session) {
rooms.get(roomId).remove(session);
System.out.println("a client has disconnected!");
}
/**
* @param roomId 房间id
* @param userId 用户id
* @param liveid 视频id
* @param msgtime 弹幕时间
* @param msg 弹幕内容
* @param session
* @throws Exception
*/
@OnMessage
public void send(@PathParam("roomId") String roomid,@PathParam("userId") String userId,@PathParam("liveid") String liveid,@PathParam("msgtime") String msgtime,String msg, Session session) throws Exception {
// 此处应该有html过滤
// msg = userId + “:” + msg;
// System.out.println(msg);
// 接收到信息后进行广播
broadcast(roomid, msg);
//向缓存中放入封装好的弹幕信息数据
Cache cache = new Cache();
cache.setLiveid(liveid);
cache.setMsg(msg);
cache.setRoomid(roomid);
cache.setUserid(userId);
cache.setMsgtime(msgtime);
CacheManager.putCache(cache);
// 按照房间装载弹幕
mb.get(roomid).add(cache);
//弹幕输出写txt
writeTxt(roomid,"test1");
}
// 按照房间名进行广播
public static void broadcast(String roomId, String msg) throws Exception {
for (Session session : rooms.get(roomId)) {
session.getBasicRemote().sendText(msg);
}
}
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 前端调用将缓存数据写成txt文件
* @param roomid
* @param liveid
*/
public static void writeTxt(String roomid,String liveid) {
// List<>
FileOutputStream outSTr = null;
BufferedOutputStream Buff = null;
List<Cache> c = mb.get(roomid);
if(c.size()>0){
String path ="/cl-pms/barrage/"+roomid+"/"+liveid;
// 判断文件夹是否存在,不存在创建文件夹
File file = new File(path);
// 如果文件夹不存在则创建
if (!file.exists() && !file.isDirectory()){
file.mkdirs();
}
//判断文件是否存在,不存在创建文件
File filefile = new File(path+"/barrage.txt");
if (!filefile.exists())
{
try {
filefile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
outSTr = new FileOutputStream(filefile);
Buff = new BufferedOutputStream(outSTr);
for(Cache ca : c){
Buff.write(Obj2Map(ca).toString().getBytes());
}
Buff.flush();
Buff.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//主播退出,弹幕缓存信息写完之后,清空mb
// mb.get(roomid).clear();
Buff.close();
outSTr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}else{
}
}
public static void main(String[] args) {
//弹幕输出写txt
writeTxt("roomnewid","test1");
// mb.get(“roomnewid”).clear();
}
public static Map<String,Object> Obj2Map(Object obj) throws Exception{
Map<String,Object> map=new HashMap<String, Object>();
Field[] fields = obj.getClass().getDeclaredFields();
for(Field field:fields){
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
}
public Object map2Obj(Map<String,Object> map,Class<?> clz) throws Exception{
Object obj = clz.newInstance();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for(Field field:declaredFields){
int mod = field.getModifiers();
if(Modifier.isStatic(mod) || Modifier.isFinal(mod)){
continue;
}
field.setAccessible(true);
field.set(obj, map.get(field.getName()));
}
return obj;
}
}
//==========================
//前台,查到的某位同学的东西,但是他的东西有点瑕疵,我做了做修正。
<%@ page language=“java” contentType=“text/html; charset=UTF-8”
pageEncoding=“UTF-8”%>
- {
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: 0;
bottom: 0;
outline: none;
}
.dm .d_screen .d_del:hover {
background: #F00;
}
.dm .d_screen .d_mask {
width: 100%;
height: 100%;
/* background: #000; /
/ 弹幕全透明 */
background: rgba(0, 0, 0, 0);
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: 1;
}
.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/
.senddm {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
display: none;
}
.send {
width: 100%;
height: 30px;
position: absolute;
bottom: 0;
left: 0;
border: 0px 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;
bottom: 0;
left: 0;
z-index: 2;
text-align: top;
line-height: 0px;
}
.send .s_con .s_text {
width: 83%;
height: 36px;
bottom: 5px;
position: relative;
border: 0;
font-size: 20px;
border-radius: 6px 6px 6px 6px;
outline: none;
}
.send .s_con .s_submit {
width: 10%;
height: 38px;
border-radius: 6px 6px 6px 6px;
outline: none;
font-size: 14px;
color: #fff;
bottom: 5px;
position: relative;
background: #65c33d;
font-family: “微软雅黑”;
cursor: pointer;
border: 1px solid #5bba32;
}
.send .s_con .s_submit:hover {
background: #3eaf0e;
}
/end send/