项目结构:
效果展示:
实现步骤
步骤一:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
步骤二:Java 代码 1,配置类:
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 serverEndpointExportelr() {
return new ServerEndpointExporter();
}
}
2,控制层
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
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.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/websocket/{username}")
@Controller
public class WebsocketController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private static int onlineNumber = 0;
private static Map<String, WebsocketController> clients =
new ConcurrentHashMap<>();
private Session session;
private String username;
@RequestMapping("/websocket")
public String webSocket(Model model) {
String name = "游客:";
String dataName = new SimpleDateFormat("yyyyMMddHHmmsss").format(new Date());
name = name + dataName;
String path = "ws://127.0.0.1:8080/websocket/";
model.addAttribute("path", path);
model.addAttribute("username", name);
return "socket";
}
@OnOpen
public void onOpen(@PathParam("username") String username, Session session) {
onlineNumber++;
this.username = username;
this.session = session;
logger.info("现在来连接的客户id:" + session.getId() + "用户名:" + username);
logger.info("有新连接加入! 当前在线人数" + onlineNumber);
try {
clients.put(username, this);
Set<String> userLists = clients.keySet();
HashMap<String, Object> map1 = new HashMap<>();
map1.put("onlineUsers", userLists);
map1.put("messageType", 1);
map1.put("username", username);
map1.put("number", onlineNumber);
sendMessageAll(JSON.toJSONString(map1), username);
HashMap<String, Object> map2 = new HashMap<>();
map2.put("messageType", 3);
map2.put("onlineUsers", userLists);
map2.put("number", onlineNumber);
sendMessageAll(JSON.toJSONString(map2), username);
} catch (Exception e) {
logger.info(username + "上线的时候通知所有人发生了错误");
}
}
@OnClose
public void onClose(){
onlineNumber--;
clients.remove(username);
try {
Map<String, Object> map1 = new HashMap();
map1.put("messageType", 2);
map1.put("onlineUsers", clients.keySet());
map1.put("username", username);
map1.put("number", onlineNumber);
sendMessageAll(JSON.toJSONString(map1), username);
}catch (Exception e){
logger.info(username + "下线的时候通知所有人发生了错误");
}
logger.info("有连接关闭! 当前在线人数" + onlineNumber);
}
@OnError
public void onError(Session session,Throwable error){
logger.info("服务器发生了错误" + error.getMessage());
}
@OnMessage
public void OnMessage(String message,Session session){
try {
logger.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");
HashMap<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){
logger.info("发生了错误了");
}
}
private void sendMessageTo(String message, String toUserName) throws IOException {
for (WebsocketController item : clients.values()) {
if (item.username.equals(toUserName)){
item.session.getBasicRemote().sendText(message);
break;
}
}
}
private void sendMessageAll(String message, String username) throws IOException {
for (WebsocketController item : clients.values()) {
item.session.getBasicRemote().sendText(message);
}
}
public static synchronized int getOnlineCount(){
return onlineNumber;
}
}
如果在配置类中写path:
url:
path: ws://127.0.0.1:8080/websocket/
控制层:
@Value("${url.path}")
private String path;
方便实现的话,可以直接写在控制层,不过建议写在配置文件中
步骤三:socket页面
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="../frame/layui/css/layui.css">
<link rel="stylesheet" href="../frame/static/css/style.css">
<link rel="icon" href="../frame/static/image/code.png">
<title>websocket</title>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
<script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
</head>
<body>
<input type="hidden" th:value="${path}" id="path" style="display: none"/>
<input type="hidden" th:value="${username}" id="username" style="display: none"/>
<br>
<span id="miqx"
style="width:80%;height:300px; background-color: papayawhip;float:left;overflow-y :auto;overflow :auto;">
<li style="text-align: center">群聊信息</li>
</span>
<span id="miax" style="width:20%;background-color: #24eb04;float:left;overflow-y :auto;overflow :auto;">
<li style="text-align: center">在线列表</li>
</span>
<textarea id="text" placeholder="请输入内容-发送消息[Ctrl+回车键]" rows="3%" cols="60%"></textarea>
<input onclick="send()" type="button" value="发送">
<td>消息发送至:</td>
<select id="onLineUser" size="1" style="width: 10%;height:30px">
<option value="所有人">所有人</option>
</select>
<div id="mizx" style="width:80%;height:300px;background-color: #bbebc7;float:left;overflow-y :auto;overflow :auto;">
<li style="text-align: center">私聊信息</li>
</div>
<br>
<br>
</body>
<script type="text/javascript">
function uaername(name) {
alert(name)
}
var miqx = $("#miqx");
var miax = $("#miax");
var mizx = $("#mizx");
var onLineUser = $("#onLineUser");
var webSocket;
var commWebSocket;
http:
if ("WebSocket" in window) {
webSocket = new WebSocket(document.getElementById('path').value +
document.getElementById('username').value);
webSocket.onopen = function () {
miqx.html(miqx.html() +
" <li style='text-align: center'>系统消息:[登陆成功]</li>")
};
webSocket.onmessage = function (evt) {
var received_msg = evt.data;
var obj = JSON.parse(received_msg);
var messageType = obj.messageType;
var onlineName = obj.username;
var number = obj.number;
if (obj.messageType == 1) {
if ((onlineName != $("#username").val())) {
miqx.html(miqx.html() + " <li style='text-align: center'>系统消息:[" + onlineName + "]上线了" + "</li>");
onLineUser.html(onLineUser.html() + "<option value='" + onlineName + "'>" + onlineName + "</option>");
}
var onlineName = obj.onlineUsers;
miax.html("<li style='text-align: center'>在线用户--[" + onlineName.length + "]</li>");
for (var i = 0; i < onlineName.length; i++) {
if ((onlineName[i] != $("#username").val())) {
miax.html(miax.html() + "<li style='text-align: left'>---" + onlineName[i] + "</li>");
}
}
}
else if (obj.messageType == 2) {
if ((onlineName != $("#username").val())) {
miqx.html(miqx.html() + " <li style='text-align: center'>系统消息:[" + onlineName + "]下线了" + "</li>");
}
var onlineName = obj.onlineUsers;
miax.html("<li style='text-align: center'>在线用户--[" + onlineName.length + "]</li>");
onLineUser.html("<option value='所有人'>所有人</option>");
for (var i = 0; i < onlineName.length; i++) {
if ((onlineName[i] != $("#username").val())) {
miax.html(miax.html() + "<li style='text-align: left'>---" + onlineName[i] + "</li>");
onLineUser.html(onLineUser.html() + "<option value='" + onlineName[i] + "'>" + onlineName[i] + "</option>");
}
}
}
else if (obj.messageType == 3) {
var onlineName = obj.onlineUsers;
miax.html("<li style='text-align: center'>在线用户--[" + onlineName.length + "]</li>");
onLineUser.html("<option value='所有人'>所有人</option>");
for (var i = 0; i < onlineName.length; i++) {
if (onlineName[i] != $("#username").val()) {
miax.html(miax.html() + " <li style='text-align: left'>---" + onlineName[i] + "</li>");
onLineUser.html(onLineUser.html() + "<option value='" + onlineName[i] + "'>" + onlineName[i] + "</option>");
}
}
}
else {
var time2 = new Date();
var date = time2.getHours() + ":" + time2.getMinutes() + ":" + time2.getSeconds();
if (obj.fromusername != $("#username").val()) {
if (obj.tousername == "所有人") {
miqx.html(miqx.html() + " <li style='text-align: left'>[" + obj.fromusername + "]说:-" + obj.textMessage + "</li>");
} else {
mizx.html(mizx.html() + " <li style='text-align: left'>[" + obj.fromusername + "]说:-" + obj.textMessage + "</li>");
}
}
}
};
webSocket.onclose = function () {
console.log("连接已关闭...");
setMessageInnerHTML("连接已经关闭....");
};
} else {
alert("您的浏览器不支持 WebSocket!");
}
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
function closeWebSocket() {
webSocket.close();
}
$(document).keyup(function (event) {
if (event.ctrlKey && event.which == 13 || event.which == 10) {
send();
} else if (event.shiftKey && event.which == 13 || event.which == 10) {
send();
}
});
function send() {
var usernameX = $("#username").val()
var usernameY = $("#onLineUser").val();
var message = $("#text").val();
if (usernameY == "所有人") {
usernameY = "All";
miqx.html(miqx.html() + " <li style='text-align: right'>" + message + " -- [" + usernameX + "]</li>");
} else {
mizx.html(mizx.html() + " <li style='text-align: right'>" + "你对-[" + usernameY + "]说:-" + message + "</li>");
}
var message = {
"message": message,
"username": usernameX,
"to": usernameY
};
webSocket.send(JSON.stringify(message));
$("#text").val("");
}
layui.use(['form', 'layedit', 'laydate'], function () {
var form = layui.form
, layer = layui.layer
, layedit = layui.layedit
, laydate = layui.laydate;
form.on('switch(switchTest)', function (data) {
layer.msg('你以' + (this.checked ? '上线' : '下线'), {
offset: '6px'
});
});
});
</script>
</html>
整天感觉还是挺简单的,不要只看不做,最好的学习方式就是自己实现一下,动起手来吧!!!
|