一.简单实现
实现一个页面给另一个页面发送一条消息的实例。
发消息实际上需要java端的websocket进行转发,就像我们的QQ,微信的消息实际上是发送到腾讯服务器然后由服务器转发给我们的。
客户端先和服务端进行一次握手确定连接,服务端对客户端分配一个id进行记录,以便发送消息给对应客户端。
1.导包:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
2.index.html页面(客户端)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
var ws = null;
var contextPath = function() {
return "/" + document.location.pathname.split("/")[1];
}
function connection() {
var username = document.getElementById("name").value;
if ('WebSocket' in window) {//首先判断当前浏览器支持不支持websocket
var url = "ws://" + document.location.host + contextPath()+"/socket/" + username;
console.log(url);
ws = new WebSocket(url);
} else {
alert("什么破电脑,都不支持websocket,砸了吧!!");
}
ws.onopen = function () {
//TODD
document.getElementById("message").innerText = "建立连接了";
}
ws.onmessage = function (event) {
var data = event.data;
console.log(111);
document.getElementById("message").innerText = data;
}
ws.onerror = function () {
document.getElementById("message").innerText = "出现异常了";
}
ws.onclose = function () {
document.getElementById("message").innerText = "连接关闭了";
}
ws.onbeforeunload = function () {//当浏览器页面窗口关闭,此处应该关闭连接,防止异常
if (ws != null) {
ws.close();
}
}
}
function sendMessage() {
var message = {toUser: toUser.value, toMessage: toMessage.value};
if(ws!=null){
console.log(message);
ws.send(JSON.stringify(message));
}else{
alert("未连接服务器");
}
}
</script>
</head>
<body>
<!--
打开链接,html标签没有这个功能,应该是
-->
输入你的名称:<input type="text" id="name" name="name">
<button onclick="connection()">连接</button>
<br>
接受者名字:<input type="text" id="toUser" name="toUser"><br>
内容:<input type="text" id="toMessage" name="toMessage">
<button onclick="sendMessage()">发送</button>
<br>
<span id="message">消息</span>
</body>
</html>
3.WebSocket.java
package com.tang.websocket;
import com.alibaba.fastjson.JSON;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
/**
* @author tang
* 与servlet的区别
* servlet是单例对象,但websocket是多例对象,因为他需要实时链接,需要知道每个链接是谁
*/
@ServerEndpoint("/socket/{name}")
public class WebSocket {
private String name;//用于记录当前websocket是谁
private Session session;//链接,用于记录当前链接
private static Map<String, WebSocket> allClients = new HashMap<String, WebSocket>();
/**
*
* @param name 代表地址参数中的name,用于区分链接是谁
* @param session 当前建立的连接
*
*/
@OnOpen //当建立连接时调用此方法
public void onOpen(@PathParam("name") String name, Session session){
this.name = name;
this.session = session;
allClients.put(name,this);
System.out.println("用户连接:"+ name + "连接上了");
}
/**
* 用于接收客户端发来的消息,这个地方更具实际业务需求决定写什么
* 比如两个人聊天,应该是这里收到消息后,转发
* 如何判断另外一个接受者是谁?to:zhangsan,message:neirong,data:2019-01-01
* @param session
* @param message
*/
@OnMessage //当服务器收到消息触发
public void onMessage(Session session, String message){
try {
System.out.println("收到消息:"+message);
// Map msg = (Map) JSON.parse(message);//这里卡住了
Map msg = JSON.parseObject(message);
//解析发过来的内容,找到目标接收者
String toUser = (String) msg.get("toUser"); //需要具体解析json
String toMessage = (String) msg.get("toMessage");
//更具目标接受者,找到他的session连接
WebSocket webSocket = allClients.get(toUser);//获取的目标接收者的websocket
//通过session发消息
if (webSocket != null) {
Session toSession = webSocket.getSession();
if (toSession.isOpen()) {//如果连接是打开状态
toSession.getAsyncRemote().sendText(toMessage);//发送
}
} else {
//正常来说应该缓存这个消息,并且发送一条对方不在线的消息
session.getAsyncRemote().sendText("对方不想搭理你,并向你抛了一个NotOnlineException");
}
}catch (Exception e){
e.printStackTrace();
}
}
@OnError //当出现异常的时候
public void onError(Session session, Throwable e){
}
@OnClose //当连接关闭的时候触发
public void onClose(Session session){
}
public Session getSession() {
return session;
}
}