springboot整合tomcat自带的websocket实现在线聊天及象棋网页对战功能 - Go语言中文社区

springboot整合tomcat自带的websocket实现在线聊天及象棋网页对战功能


以前用flex做过中国象棋对战版CS架构的,没用到websocket,消息推送使用定时刷新不断请求服务器,比较耗资源,现在刚接触websocket,闲来无事就重写个小项目消遣下.本人前端菜鸟,Ext也是刚接触,画的界面比较丑,勿喷.

先上截图~


登陆界面,没有用户可以注册一个,用的是sqlite数据库



聊天主界面,可以选择跟在线的人聊天,也可以点群消息,广播消息给所有人



游戏大厅及游戏主界面.右边显示系统提示信息 也可以在这里跟对手聊天~


部分代码:

导入springboot所用jar:pom文件如下:

4.0.0com.donggemyweb0.0.1-SNAPSHOTorg.springframework.bootspring-boot-starter-parentpom1.5.3.RELEASEimportorg.springframework.bootspring-boot-starter-weborg.mybatis.spring.bootmybatis-spring-boot-starter1.3.0org.springframework.bootspring-boot-starter-securityorg.springframework.bootspring-boot-starter-websocketorg.xerialsqlite-jdbcorg.apache.maven.pluginsmaven-compiler-plugin1.71.7org.springframework.bootspring-boot-maven-pluginZIPcom.dongge.Applicationrepackage

websocket配置:

/**
 * @author 东哥 2017年6月1日
 *
 */
@Configuration
public class WebSocketConfig {

	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}

}
/**
 * @author 东哥 2017年6月1日
 *
 */
@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class, encoders = {
		MsgEncoder.class }, decoders = { MsgDecoder.class })
@Component
public class ChatController {
	public static Set<ChatController> CHAT_SET = new CopyOnWriteArraySet<ChatController>();

	private static List<User> onlineUsers = new ArrayList<User>();

	private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

	private Session session;

	private User user;

	@OnOpen
	public void openConnection(final Session session, final EndpointConfig config) {
		this.session = session;
		final HttpSession httpsession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
		user = (User) httpsession.getAttribute("login_user");
		onlineUsers.add(user);
		CHAT_SET.add(this);
		System.out.println(user.getNickName() + "进入聊天室");
		onlineNotify(user.getNickName() + "进入聊天室");
	}

	@OnClose
	public void close() {
		CHAT_SET.remove(this);
		onlineUsers.remove(user);
		System.out.println(user.getNickName() + "离开聊天室");
		onlineNotify(user.getNickName() + "离开聊天室");
	}

	@OnMessage
	public void handlerMessage(final ClientMessage message, final Session session) {
		final PushMessage pushMsg = new PushMessage();
		pushMsg.setFromUser(user.getUsername());
		pushMsg.setType(message.getType());
		if ("chat".equalsIgnoreCase(message.getType())) {
			pushMsg.setMessage("<span style='color:green;font-size:8px'>" + user.getNickName() + " "
					+ sdf.format(new Date()) + "</span><p>" + message.getMessage() + "</p>");
		}
		pushMsg.setData(message.getData());
		final String toUser = message.getToUser();
		if (StringUtils.isEmpty(toUser) || "all".equalsIgnoreCase(toUser)) {// 推送给所有人
			pushMsg.setToUser("all");
			broadcast(pushMsg);
		} else {// 推送给自己和对方
			pushMsg.setToUser(toUser);
			sendData(pushMsg);
			for (final ChatController item : CHAT_SET) {
				if (toUser.equals(item.user.getUsername())) {
					item.sendData(pushMsg);
				}
			}
		}
	}

	@OnError
	public void error(final Session session, final Throwable error) {
		System.out.println("发生错误:" + error.getMessage());
	}

	private void onlineNotify(final String msg) {
		final PushMessage message = new PushMessage();
		message.setType("onlineUsers");
		message.setData(onlineUsers);
		message.setMessage("<span style='color:purple;font-size:8px'>" + msg + "</span><br/>");
		message.setToUser("all");
		broadcast(message);
	}

	private void broadcast(final PushMessage message) {
		for (final ChatController item : CHAT_SET) {
			item.sendData(message);
		}
	}

	public void sendData(final PushMessage data) {
		try {
			session.getBasicRemote().sendObject(data);
		} catch (final IOException e) {
			e.printStackTrace();
		} catch (final EncodeException e) {
			e.printStackTrace();
		}
	}
}
象棋websocket入口

/**
 * @author 东哥 2017年6月13日
 *
 */
@ServerEndpoint(value = "/chess", configurator = GetHttpSessionConfig.class, encoders = {
		MsgEncoder.class }, decoders = { MsgDecoder.class })
@Component
public class ChessController {

	public static final Map<String, ChessRoom> ROOM_MAP = new HashMap<String, ChessRoom>();

	private User user;

	private Session session;

	@OnOpen
	public void openConnection(final Session session, final EndpointConfig config) {
		this.session = session;
		final HttpSession httpsession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
		user = (User) httpsession.getAttribute("login_user");
		final String roomId = session.getRequestParameterMap().get("roomId").get(0);
		session.getUserProperties().put("roomId", roomId);
		ChessRoom room = null;
		if (ROOM_MAP.get(roomId) != null) {
			room = ROOM_MAP.get(roomId);
			room.getUserList().add(user);
			room.getSessionList().add(session);
		} else {
			room = new ChessRoom(roomId);
			final List<User> userList = new ArrayList<User>();
			userList.add(user);
			room.setUserList(userList);
			final List<Session> sessionList = new ArrayList<Session>();
			sessionList.add(session);
			room.setSessionList(sessionList);
			ROOM_MAP.put(roomId, room);
		}
		final PushMessage pushMsg = new PushMessage();
		pushMsg.setType("room_msg");
		pushMsg.setMessage(user.getNickName() + "进入房间");
		pushMsg.setData(room.getUserList());
		room.braodcast(pushMsg);
		notifyAllUsers();
	}

	private void notifyAllUsers() {
		final List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
		for (final String key : ROOM_MAP.keySet()) {
			final ChessRoom room = ROOM_MAP.get(key);
			final Map<String, Object> item = new HashMap<String, Object>();
			item.put("roomId", key);
			item.put("userList", room.getUserList());
			data.add(item);
		}
		final PushMessage pushMsg = new PushMessage();
		pushMsg.setType("room_msg");
		pushMsg.setData(data);
		for (final ChatController chat : ChatController.CHAT_SET) {
			chat.sendData(pushMsg);
		}
	}

	@OnClose
	public void close() {
		final String roomId = (String) session.getUserProperties().get("roomId");
		if (ROOM_MAP.get(roomId) != null) {
			final ChessRoom room = ROOM_MAP.get(roomId);
			room.getUserList().remove(user);
			room.getSessionList().remove(session);
			final PushMessage pushMsg = new PushMessage();
			pushMsg.setType("room_msg");
			pushMsg.setMessage(user.getNickName() + "离开了房间");
			pushMsg.setData(room.getUserList());
			room.braodcast(pushMsg);
			if (room.getUserList().isEmpty()) {
				ROOM_MAP.remove(roomId);
			}
		}
		session.getUserProperties().remove("roomId");
		notifyAllUsers();
	}

	@OnMessage
	public void handlerMessage(final ClientMessage message, final Session session) {
		final PushMessage pushMsg = new PushMessage();
		pushMsg.setFromUser(user.getUsername());
		pushMsg.setType(message.getType());
		pushMsg.setData(message.getData());
		pushMsg.setMessage(message.getMessage());
		final String roomId = (String) session.getUserProperties().get("roomId");
		if (ROOM_MAP.get(roomId) != null) {
			final ChessRoom room = ROOM_MAP.get(roomId);
			room.braodcast(pushMsg);
		}
	}

	@OnError
	public void error(final Session session, final Throwable error) {
		System.out.println("发生错误:" + error.getMessage());
	}

前端核心代码:

聊天主窗口创建的时候建立聊天websocket连接

initComponent : function() {
		websocket = new WebSocket('ws://' + serverIp + '/chat');
		websocket.onmessage = onmessage;

		window.onbeforeunload = function() {
			if (websocket != null) {
				websocket.close();
			}
		}
		this.callParent(arguments);
	}
function onmessage(event) {
	var data = Ext.JSON.decode(event.data);
	if (data.type == 'onlineUsers') {
		onlineUsers = data.data;
		refreshOlUsers(onlineUsers);
		setGroupWinMsg(data.message);
	} else if (data.type == 'chat') {
		var toUser = data.toUser == currentUser.username ? data.fromUser
				: data.toUser;
		var nickName = getUserByUsername(toUser).nickName;
		var node = {
			id : toUser,
			text : nickName
		};
		showChatWin(node, data.message);
	} else if (data.type == 'room_msg') {
		var roomMap = data.data;
		if (gamehall) {
			gamehall.setRoomPanelInfo(roomMap);
		}
	}
}

进入房间后打开chess的websocket

function onWinRender(win) {
	var canvas = Ext.query('#' + win.id + ' canvas')[0];
	drawer = new ChessDrawer(canvas);
	drawer.init();
	canvas.addEventListener('click', clickCanvas);

	chessSocket = new WebSocket('ws://' + serverIp + '/chess?roomId='
			+ win.roomId);
	chessSocket.onmessage = onChessMsg;
	win.on('close', function() {
		if (chessSocket != null) {
			chessSocket.close();
		}
	});

	window.onbeforeunload = function() {
		if (chessSocket != null) {
			chessSocket.close();
		}
	}
}

function onChessMsg(event) {
	var data = Ext.JSON.decode(event.data);
	if (data.message) {
		room.setMsg(data.message);
	}
	if (data.type == 'room_msg') {
		roomUsers = data.data;
		if (roomUsers && roomUsers.length == 2) {
			readyable = true;
			roomUsers[0].isfirst = true;
			roomUsers[1].isfirst = false;
			for ( var i in roomUsers) {
				if (currentUser.username == roomUsers[i].username) {
					isfirst = roomUsers[i].isfirst;
					turn = isfirst ? 1 : 0;
				}
			}
		} else {
			readyable = false;
			selfReady = false;
			opReady = false;
			isfirst = false;
			isplay = false;
			room.down('button[name=ready]').enable();
			room.down('button[name=lose]').disable();
		}
	} else if (data.type == 'chat') {
		//
	} else if (data.type == 'chess') {
		moveChess(data.data.x, data.data.y, data.data.ex, data.data.ey);
		isplay = !isplay;
		judge();

	} else if (data.type == 'ready') {
		var t = data.data.turn;
		if (t != turn) {
			Ext.MessageBox.alert('提示', '对方已准备');
			opReady = true;
		}
		if (selfReady && opReady) {
			isplay = isfirst;
			room.down('button[name=draw]').enable();
			room.down('button[name=lose]').enable();
		}
	} else if (data.type == 'gameover') {
		var t = data.data.turn;
		if (t != turn) {
			Ext.MessageBox.alert('提示', data.data.opAlertMsg);
		}
		isplay = false;
		selfReady = false;
		opReady = false;
		isfirst = !isfirst;
		turn = isfirst ? 1 : 0;
		room.down('button[name=ready]').enable();
		room.down('button[name=draw]').disable();
		room.down('button[name=lose]').disable();
	} else if (data.type == 'draw') {
		var t = data.data.turn;
		if (t != turn) {
			Ext.MessageBox.confirm('提示', '对手选择和棋,是否同意', function(bid) {
				var agree = false, msg = '';
				if ('yes' == bid) {
					agree = true;
					msg = '同意和棋请求,游戏结束';
				} else {
					agree = false;
					msg = '不同意和棋请求';
				}
				var data = {
					type : 'draw_result',
					data : {
						turn : turn,
						agree : agree
					},
					message : currentUser.nickName + msg
				};
				chessSocket.send(Ext.JSON.encode(data));
			});
		}
	} else if (data.type == 'draw_result') {
		if (data.data.agree) {
			isplay = false;
			selfReady = false;
			opReady = false;
			isfirst = !isfirst;
			turn = isfirst ? 1 : 0;
			room.down('button[name=ready]').enable();
			room.down('button[name=draw]').disable();
			room.down('button[name=lose]').disable();
		} else {
			var t = data.data.turn;
			if (t != turn) {
				Ext.MessageBox.alert('提示', '对方不同意您的和棋请求');
			}
		}
	}
}


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/renhd_1987/article/details/73743227
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-28 02:03:19
  • 阅读 ( 689 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢