项目中有个实时聊天的需求,查看很多资料,主要是实现从服务端发送信息到客户端,实现方法有长轮询,长连接,websocket等,还是websocket最简单,不过需要浏览器支持。
需要的支持
需要jdk7以上,tomcat7以上,反正我的7.0.55是不行,7.0.64可以,,引入
socket.java
import bo.MessageChat;
import bo.SessionMap;
import com.alibaba.fastjson.JSONArray;
import server.ChatInfoServer;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* Created by keygod on 2016/4/25.
*/
@ServerEndpoint(value ="/websocket/{from}/{to}")
public class SocketChat{
private ChatInfoServer chatInfoServer = new ChatInfoServer();
private String from;
private String to;
private Session session;
private static final Logger sysLogger = Logger.getLogger("sysLog");
@OnOpen
public void open(Session session, @PathParam(value = "from")String from,@PathParam(value = "to")String to) throws IOException {
this.session = session;
this.from = from;
this.to = to;
SessionMap.getSessionMap().put(from,session);
List<MessageChat> messageChats = chatInfoServer.getByFromAndto(from,to,1,5);
String json = JSONArray.toJSONString(messageChats);
session.getBasicRemote().sendText(json);
Session sessionto = SessionMap.getSessionMap().get(to);
if(sessionto!=null){
session.getBasicRemote().sendText("online");//接受人的状态 上线
}else {
session.getBasicRemote().sendText("offline");//接受人的状态 上线
}
sysLogger.info("*** WebSocket opened from ship " + from);
}
@OnMessage
public void inMessage(String message,Session session) {
try {
MessageChat messageChat = new MessageChat();
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
messageChat.setFromDate(date);
messageChat.setFromName(from);
messageChat.setTodate(date);
messageChat.setToName(to);
messageChat.setMessage(message);
Session sessionto = SessionMap.getSessionMap().get(to);
if(sessionto!=null){
messageChat.setReadtype("1");
sysLogger.info("*** *** WebSocket opened to ship " + to);
sessionto.getBasicRemote().sendText(JSONArray.toJSONString(messageChat));
session.getBasicRemote().sendText("online");
}else {
messageChat.setReadtype("0");
session.getBasicRemote().sendText("offline");
}
chatInfoServer.insert(messageChat);
} catch (IOException e) {
e.printStackTrace();
}
}
@OnClose
public void end() {
SessionMap.getSessionMap().remove(from);
sysLogger.info("*** WebSocket closed from sessionId " + this.session.getId());
}
@OnError
public void error(Throwable t) {
// 添加处理错误的操作
System.out.println(t.getMessage());
System.out.println(t.getCause());
t.printStackTrace();
}
}
其中 ,SessionMap 用来保存session的key ,因为websocket的session是按照顺序1,2来的,所以每次open链接把session存入全局变量sessionMap中,就可以指定发送人。
发送信息方式为session.getBasicRemote().sendText(“”);
SeesionMap.java
package bo;
import javax.websocket.Session;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Created by keygod on 2016/4/25.
*/
public class SessionMap {
private static Map<String,Session> sessionMap = new ConcurrentHashMap<String, Session>();
public static Map<String, Session> getSessionMap() {
return sessionMap;
}
public static void setSessionMap(Map<String, Session> sessionMap) {
SessionMap.sessionMap = sessionMap;
}
}
sessionMap需要加锁,
点对点发送信息只需要这两个类,之后就是加上存数据库的操作了。。
404问题
首先依赖环境是
WebSocket是HTML5才支持的
Java EE 7.0以后的版本才支持
Tomcat7以后的版本才支持
其他的服务容器则应该是有对应的自己支持的包
具体的如何请求和接受就不做记录了,主要似乎404的问题
而Oracle 自己的WebSocket包在目前为止最新的是 WebSocket-api1.0 release版本
Maven配置如下
http://mvnrepository.com/artifact/javax.websocket/javax.websocket-api/1.0
Xml代码 收藏代码
javax.websocket
javax.websocket-api
1.0
注意一点是(404的原因)就要引入Tomcat7的 Run Time 的依赖包,不要用WebSocket-api.jar
Tomcat7内部有Tomat7-WebSocket.jar 和 WebSocket-api.jar的包,里面实现了这个基于WebSocket-api.jar的内容,基于这个包的基础上又进行修饰的包
在 Tomcat运行时环境 卡特琳娜里面的,所以,要是用Maven部署的话,会有Jar包冲突
而在开发的过程中,就要引入Tomcat7的 Run Time 的依赖包,不要用WebSocket-api.jar
这是Tomcat7的关于WebSocket的说明文档,未来使用WebSocket-api.jar,Tomcat说将在Tomcat 8的版本移出自己内部的包,就可以直接使用Oracle的了
http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html
其他404,那可能就是代码里面访问的路径错误导致找不到啦