websocket 實現在線聊天效果
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.53</version>
<scope>compile</scope>
</dependency>
</dependencies>
添加 config 配置類
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
后端接收處理消息
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Slf4j
@Controller
public class WebSocketController {
@RequestMapping("/webSocket/{name}")
public String webSocket(@PathVariable String name, Model model) {
try {
log.info("跳轉到websocket的頁面上");
model.addAttribute("username", name);
return "_user";
} catch (Exception e) {
log.info("跳轉到websocket的頁面上發生異常,異常信息是:" + e.getMessage());
return "error";
}
}
@RequestMapping("/webSocket")
public String page() {
try {
log.info("跳轉到總頁面上");
return "ChatRoom";
} catch (Exception e) {
log.info("跳轉到websocket的頁面上發生異常,異常信息是:" + e.getMessage());
return "error";
}
}
}
Socket處理
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
@ServerEndpoint("/webSocket/{username}")
public class WebSocket {
public static int onlineNumber = 0;
/**
* 以用戶的姓名為key,WebSocket為對象保存起來
*/
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
/**
* 會話
*/
private Session session;
/**
* 用戶名稱
*/
private String username;
@OnOpen
public void onOpen(@PathParam("username") String username, Session session) {
onlineNumber++;
log.info("現在來連接的客戶id:" + session.getId() + "用戶名:" + username);
this.username = username;
this.session = session;
log.info("有新連接加入! 當前在線人數" + onlineNumber);
try {
//messageType 1代表上線 2代表下線 3代表在線名單 4代表普通消息
//先給所有人發送通知,說我上線了
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 1);
map1.put("username", username);
sendMessageAll(JSON.toJSONString(map1), username);
//把自己的信息加入到map當中去
clients.put(username, this);
//給自己發一條消息:告訴自己現在都有誰在線
Map<String, Object> map2 = new HashMap<>();
map2.put("messageType", 3);
//移除掉自己
Set<String> set = clients.keySet();
map2.put("onlineUsers", set);
sendMessageTo(JSON.toJSONString(map2), username);
} catch (IOException e) {
log.info(username + "上線的時候通知所有人發生了錯誤");
}
}
@OnError
public void onError(Session session, Throwable error) {
log.info("服務端發生了錯誤" + error.getMessage());
//error.printStackTrace();
}
@OnClose
public void onClose() {
onlineNumber--;
//webSockets.remove(this);
clients.remove(username);
try {
//messageType 1代表上線 2代表下線 3代表在線名單 4代表普通消息
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 2);
map1.put("onlineUsers", clients.keySet());
map1.put("username", username);
sendMessageAll(JSON.toJSONString(map1), username);
} catch (IOException e) {
log.info(username + "下線的時候通知所有人發生了錯誤");
}
log.info("有連接關閉! 當前在線人數" + onlineNumber);
}
@OnMessage
public void onMessage(String message, Session session) {
try {
log.info("來自客戶端消息:" + message + "客戶端的id是:" + session.getId());
JSONObject jsonObject = JSON.parseObject(message);
String textMessage = jsonObject.getString("message");
String fromusername = jsonObject.getString("username");
String tousername = jsonObject.getString("to");
//如果不是發給所有,那么就發給某一個人
//messageType 1代表上線 2代表下線 3代表在線名單 4代表普通消息
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 4);
map1.put("textMessage", textMessage);
map1.put("fromusername", fromusername);
if (tousername.equals("All")) {
map1.put("tousername", "所有人");
sendMessageAll(JSON.toJSONString(map1), fromusername);
} else {
map1.put("tousername", tousername);
sendMessageTo(JSON.toJSONString(map1), tousername);
}
} catch (Exception e) {
log.info("發生了錯誤了");
}
}
public void sendMessageTo(String message, String ToUserName) throws IOException {
for (WebSocket item : clients.values()) {
if (item.username.equals(ToUserName)) {
item.session.getAsyncRemote().sendText(message);
break;
}
}
}
public void sendMessageAll(String message, String FromUserName) throws IOException {
for (WebSocket item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
public static synchronized int getOnlineCount() {
return onlineNumber;
}
}