tomcat搭建的websocket,相对于netty就简单的多。只需要一个java类就处理了。通过注解的方式,部署到tomcat服务器,一个websocke就搭建完成了。需要的jar包是:gson-2.8.2.jar,okhttp-3.9.0.jar,okio-1.13.0.jar,websocket-api.jar
具体代码如下:
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import okhttp3.*;
/**
* Time: 2017-08-01 13:00
* Intent: webSocket服务器
*/
@ServerEndpoint("/websocketsroom")
public class SocketsRoom {
// 使用map来收集session,key为userid
private static final Map<String, Session> clients = new ConcurrentHashMap<String, Session>();
@OnOpen //一个用户就是一次会话
public void connect(Session session) throws Exception {
// 将session按照房间名来存储,将各个房间的用户隔离
String userID = session.getQueryString();
try {
clients.remove(userID);
} catch (Exception e) {
}
clients.put(userID, session);
System.out.print("connect user:" + userID);
}
@OnClose
public void disConnect(Session session) {
String userID = session.getQueryString();
try {
clients.remove(userID);
} catch (Exception e) {
}
System.out.print("disconnect user:" + userID);
}
@OnMessage
public void receiveMsg(String msg, Session session) throws Exception {
System.out.print("recieve msg:" + msg);
if ("heart".equals(msg) || "@heart".equals(msg)) {
return;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String userID = session.getQueryString();
//解析msg,获取接收对象,如果连接池存在对象用户则发送消息.
try {
JsonObject jsonObject = new JsonParser().parse(msg).getAsJsonObject();
String msgType = jsonObject.get("msg_type").getAsString();
//保存消息到服务器。
Session disSession = clients.get(jsonObject.get("recieve").getAsJsonObject().get("userid").getAsString());
String time = sdf.format(new Date());
jsonObject.addProperty("time", time);
if ("txt".equals(msgType) || "audio".equals(msgType) || "image".equals(msgType)) {
session.getBasicRemote().sendText(jsonObject.toString());
}
if (disSession != null) {
disSession.getBasicRemote().sendText(jsonObject.toString());
}
InetAddress address = InetAddress.getLocalHost();
//System.out.println("Local HostAddress:"+addr.getHostAddress());
if ("txt".equals(msgType) || "audio".equals(msgType) || "image".equals(msgType)) {
// 保存数据
OkHttpClient client = new OkHttpClient();
Gson gson = new Gson();
Map<String, Object> map = new HashMap<>();
map.put("sender", jsonObject.get("recieve").getAsJsonObject().get("userid").getAsString());//消息接收人
map.put("uid", userID);//消息发送人
map.put("time", time); // 添加时间
map.put("type", jsonObject.get("msg_type"));//发送信息类型
map.put("message", jsonObject.get("msg_content"));//发送内容
map.put("type_info", "3");
// 保存图片或音频
if( "audio".equals(msgType) || "image".equals(msgType)) {
map.put("path", jsonObject.get("recieve").getAsJsonObject().get("msg_content"));
}
// 保存房间信息
RequestBody body = new FormBody.Builder()
.add("data", gson.toJson(map))
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("http://"+address.getHostAddress()+":8888/nngr/data/nngr/websocket.svt")
.post(body)
.build();
client.newCall(request).execute();
// 保存聊天信息
map.put("type_info", "4");
if (jsonObject.has("path")) {
map.put("path", jsonObject.get("path"));
}
body = new FormBody.Builder()
.add("data", gson.toJson(map))
.build();
client.newCall(new okhttp3.Request.Builder()
.url("http://"+address.getHostAddress()+":8888/nngr/data/nngr/websocket.svt")
.post(body)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
}
});
}
} catch (Exception e) {
}
}
}
上面的代码是接收消息后,调用了一个servlet接口,把数据存储到数据库。
tomcat搭建的websocket就一个java类,但是这样不能在一个服务器里启动了。因为会占用端口。如果能够让websocket的服务占用另一个端口,那么这个问题也就解决了。我之前试图用main方法也能启动websocket服务,但是没能成功,因为这种方式需要tomcat容器加载的时候去启动。
网友评论