需要的jar
<!-- start websocket -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>
<!-- end websocket -->
实现具体类:
1、SpringWebSocketHandlerInterceptor类
package com.jero.esc.web.webSocket;
import com.jero.esc.common.utils.StringUtil;
import com.jero.esc.po.userinfo.LogInfo;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import javax.servlet.http.HttpSession;
import java.util.Map;
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
/** 在拦截器内强行修改websocket协议,将部分浏览器不支持的 x-webkit-deflate-frame 扩展修改成 permessage-deflate */
if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")){
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
// TODO Auto-generated method stub
System.out.println("Before Handshake");
//获取当前Session
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
if (session != null) {
//使用userName区分WebSocketHandler,以便定向发送消息
LogInfo currentUser=(LogInfo) session.getAttribute("logInfo");
System.out.println(currentUser.getLogId());
String userName = currentUser.getLogName();
System.out.println(userName);
String infoId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("infoId");
String receiveLogId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("receiveLogId");
String userId=currentUser.getLogId();
String toId="";
if(StringUtil.isNotEmptys(infoId,receiveLogId)){
userId=currentUser.getLogId()+infoId;//发送者
toId=receiveLogId+infoId;//接收者
}else{
receiveLogId="";
infoId="";
}
if (userName == null) {
userName = "default-system";
}
attributes.put("WEBSOCKET_USERNAME", userName);
attributes.put("userId",userId);
attributes.put("toId",toId);
attributes.put("receiveLogId",receiveLogId);
attributes.put("infoId",infoId);
attributes.put("loginfoId",currentUser.getLogId());
}else{
}
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
// TODO Auto-generated method stub
super.afterHandshake(request, response, wsHandler, ex);
}
}
2、SystemWebSocketHandler
package com.jero.esc.web.webSocket;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jero.esc.common.utils.StringUtil;
import com.jero.esc.mapper.goodsinfo.ChatRecordMapper;
import com.jero.esc.mapper.userinfo.LogInfoMapper;
import com.jero.esc.po.goodsinfo.ChatRecord;
import com.jero.esc.po.userinfo.LogInfo;
import com.jero.esc.service.goodsinfo.IChatService;
import com.jero.esc.vo.goodsinfo.ChatRecordVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class SystemWebSocketHandler implements WebSocketHandler {
@Autowired
private IChatService chatService;
@Autowired
private ChatRecordMapper chatRecordMapper;
@Autowired
private LogInfoMapper logInfoMapper;
//当MyWebSocketHandler类被加载时就会创建该Map,随类而生
public static final Map<String, WebSocketSession> userSocketSessionMap;
static {
userSocketSessionMap = new HashMap<String, WebSocketSession>();
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.print("连接成功");
String username= (String) session.getAttributes().get("WEBSOCKET_USERNAME");
String userId=(String) session.getAttributes().get("userId");
String toId=(String) session.getAttributes().get("toId");
userSocketSessionMap.put(userId,session);
System.out.println("当前用户数量: " + userSocketSessionMap.size());
System.out.println("用户名 "+username);
System.out.println("用户ID "+userId);
if(StringUtil.isNotEmpty(toId)){
if(userSocketSessionMap.get(toId)!=null){
Map<String,Object> map=new HashMap<String, Object>();
map.put("flag",true);
sendMessageToUser(userId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
}
}
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
String schatMessage = (String) message.getPayload();//用户输入
System.out.println("用户输入" + schatMessage);
if(message.getPayloadLength()==0)return;
//得到Socket通道中的数据并转化为Message对象
ChatRecord msg=new Gson().fromJson(message.getPayload().toString(),ChatRecord.class);
Timestamp now = new Timestamp(System.currentTimeMillis());
msg.setCreateTime(now);
String toId=msg.getReceiveLogId()+msg.getInfoId();
List<ChatRecordVo> recordVoList=chatRecordMapper.selectChatList((String) session.getAttributes().get("receiveLogId"));
//将信息保存至数据库
Map<String,Object> map=chatService.sendChat((String) session.getAttributes().get("loginfoId"),msg.getInfoId(),msg.getInfoType(),msg.getReceiveLogId(),msg.getContent());
if(!(boolean)map.get("flag")){//如果保存数据库失败抛异常
throw new RuntimeException(map.get("msg").toString());
}else{
msg.setRecordId((String) map.get("recordId"));
//发送Socket信息
//判断对方是否在线
if(userSocketSessionMap.get(toId)==null){
//判断对方是否在列表页
if(userSocketSessionMap.get((String) session.getAttributes().get("receiveLogId"))!=null){
Map<String,Object> map1=new HashMap<String, Object>();
map1.put("flag",false);
for(ChatRecordVo recordVo:recordVoList){
if(recordVo.getInfoId().equals(msg.getInfoId())){//判断是否是第一次发送消息
map1.put("flag",true);//不是则推送未读消息+1
map1.put("infoId",msg.getInfoId());
map1.put("dateTimeStr",msg.getCreateTimeStr());
break;
}
}
if(!(boolean)map1.get("flag")){//如果是第一次发送消息,推送聊天列表信息
//聊天列表信息
for(ChatRecordVo recordVo: chatRecordMapper.selectChatList((String) session
.getAttributes().get("receiveLogId"))){
if(recordVo.getInfoId().equals(msg.getInfoId())){
map1.put("record",recordVo);
break;
}
}
}
sendMessageToUser((String) session.getAttributes().get("receiveLogId"), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map1)));
}
}else{
//在线直接推送消息
sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
}
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
String toId=(String) session.getAttributes().get("toId");
if(StringUtil.isNotEmpty(toId)){
if(userSocketSessionMap.get(toId)!=null){
Map<String,Object> map=new HashMap<String, Object>();
map.put("infoId",(String) session.getAttributes().get("infoId"));
sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
System.out.print("关闭连接");
String userId=(String) webSocketSession.getAttributes().get("userId");
System.out.println("WebSocket:"+webSocketSession.getAttributes().get("userId")+"close connection");
Iterator<Map.Entry<String,WebSocketSession>> iterator = userSocketSessionMap.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry<String,WebSocketSession> entry = iterator.next();
if(entry.getValue().getAttributes().get("userId")==webSocketSession.getAttributes().get("userId")){
userSocketSessionMap.remove(webSocketSession.getAttributes().get("userId"));
System.out.println("WebSocket in staticMap:" + webSocketSession.getAttributes().get("userId") + "removed");
break;
}
}
System.out.println("用户数量: " + userSocketSessionMap.size());
String toId=(String) webSocketSession.getAttributes().get("toId");
if(StringUtil.isNotEmpty(toId)){
if(userSocketSessionMap.get(toId)!=null){
Map<String,Object> map=new HashMap<String, Object>();
map.put("flag",false);
sendMessageToUser(toId, new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(map)));
}
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
//发送信息的实现
public void sendMessageToUser(String uid, TextMessage message)
throws IOException {
WebSocketSession session = userSocketSessionMap.get(uid);
if (session != null && session.isOpen()) {
session.sendMessage(message);
}
}
}
3、WebSocketConfig
package com.jero.esc.web.webSocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.client.standard.WebSocketContainerFactoryBean;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(systemWebSocketHandler(),"webSocket.do").addInterceptors(new SpringWebSocketHandlerInterceptor());
}
@Bean
public WebSocketHandler systemWebSocketHandler(){
return new SystemWebSocketHandler();
}
@Bean
public WebSocketContainerFactoryBean createWebSocketContainer() {
WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
}
前端连接webSocket
var isConnect=false;
var webSocket;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
webSocket = new WebSocket("ws://www.jindaoj.com:8083/webSocket.do?infoId=${infoId}&receiveLogId=${receiveLogId}");
//webSocket = new WebSocket("ws://6xtbd9.natappfree.cc/escq/webSocket.do?infoId=${infoId}&receiveLogId=${receiveLogId}");
console.log("link success");
}else{
alert('Not support websocket');
}
webSocket.onopen = function(event){
console.log("连接成功");
isConnect=true;
console.log(event);
};
webSocket.onerror = function(event){
console.log("连接失败");
isConnect=false;
alert("对不起,连接失败,请检查您的网络情况");
};
webSocket.onclose = function(event){
isConnect=false;
console.log("Socket连接断开");
alert("您已经断开连接,请重新连接");
$(".btns2,.btns").click(function(){
location.reload();
});
};
webSocket.onmessage = function(event){
//接受来自服务器的消息
var message = JSON.parse(event.data);
if(message.msg!=undefined){
alert(message.msg);
}else if(message.flag!=undefined){
if(message.flag){
$("#status").text("在线");
$(".ChatHeadImg").css('-webkit-filter',"initial");
}else{
$(".ChatHeadImg").css("-webkit-filter","grayscale(100%)");
$("#status").text("离线");
}
}else{
$.ajax({
url: path + '/wap/chat/updateReadStatusByAjax.html',
data: {
recordId: message.recordId
},
dataType: 'json',
type: 'post',
success: function (res) {}
});
if(/.(gif|jpg|jpeg|png|gif|jpg|png)$/.test(message.content)){
$(".chatBox-content-demo").append("<div class='clearfloat'>"+
"<div class='author-name'><small class='chat-date'>"+message.createTime+"</small></div>"+
"<div class='left'>"+
"<div class='chat-avatars'><img src='${receiveUserInfo.userPhoto}' alt='头像'/></div>"+
"<div class='chat-message' style='background:#fff'>"+
"<img src='"+message.content+"' alt='图片'></div></div></div>");
//聊天框默认最底部
$(document).ready(function () {
$("<img/>").attr("src",message.content).load(function() {//imgSrc是图片地址
var realHeight = this.height;
$("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight+realHeight);
})
});
}else{
$(".chatBox-content-demo").append("<div class='clearfloat'>"+
"<div class='author-name'>"+
"<small class='chat-date'>"+message.createTime+"</small></div>"+
"<div class='left'>"+
"<div class='chat-avatars'><img src='${receiveUserInfo.userPhoto}' alt='头像'/></div>"+
"<div class='chat-message'>"+message.content+"</div> </div> </div>");
//聊天框默认最底部
$(document).ready(function () {
$("#chatBox-content-demo").scrollTop($("#chatBox-content-demo")[0].scrollHeight);
});
}
}
}