1、样式展示
登录界面
(用户名自己取,密码是111,可在前端文件中改,因为做的比较简单,没有把用户做数据库相关的,所以直接在前端固定了密码是111)
聊天界面
2、代码展示
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<title>登录</title>
<script>
$(function() {
var websocket=null;
//登录
$(".loginBtn").click(function(){
var nickname=$(".nicknameI").val()
var password=$(".passwordI").val()
if(nickname==""){
alert("请输入昵称")
return
}
if(password==""){
alert("请输入密码")
return
}
if(password==111){
alert("登录成功")
$(".container").hide()
$(".messageBox").show()
$(".nicknameI").val("")
$(".passwordI").val("")
}else{
alert("密码错误")
}
//判断当前浏览器是否支持websocket
var supprotWebSocket='WebSocket' in window || 'MozWebSocket' in window;
if(supprotWebSocket){
//建立websocket连接
websocket = new WebSocket("ws://localhost:8080/websocket/"+nickname);
}else{
alert("该浏览器不支持websocket,请更换")
}
//建立连接发生错误回调方法
websocket.onerror=function(){
console.log("error")
}
//建立连接正确回调
websocket.onopen=function (){
console.log("连接建立成功")
}
//收到消息回调方法
websocket.onmessage=function(event){
console.log(event)
var flag=event.data.search("恭喜您成功连接上WebSocket")!=-1;
console.log(flag)
if(flag){
onlineMessage(event.data)
return
}
messageShow(event.data)
}
//关闭连接回调方法
websocket.onclose=function() {
console.log("连接关闭")
}
//监听窗口关闭时间,窗口关闭主动关闭websocket连接,防止连接还没断开就关闭
window.onbeforeunload=function (){
websocket.close();
}
})
//将消息显示到界面
function messageShow(message){
$("#messageArea").append('<span>'+message+'</span><br/><br/>');
}
//显示在线人数信息
function onlineMessage(message){
$(".onlineMessage").empty()
$(".onlineMessage").append(message)
}
//关闭websocket连接
$(".close").click(function (){
websocket.close();
$(".messageBox").hide()
$(".container").show()
})
//发送消息
$(".send").click(function(){
var message=$(".message").val();
var toUser=$(".toUser").val()
var socketMsg = {msg:message,toUser:toUser};
if(toUser == ''){
//群聊.
socketMsg.type = 0;
}else{
//单聊.
socketMsg.type = 1;
}
//转为JSON格式
websocket.send(JSON.stringify(socketMsg));
$(".message").val("")
$(".toUser").val("")
})
});
</script>
</head>
<body>
<div class="messageBox">
<div class="onlineMessage"></div>
<div id="messageArea"></div>
<div class="operate">
<input type="text" placeholder="输入你想说的话" class="message">
<input class="toUser" type="text" placeholder="目标"/>
<input type="button" value="发送" class="send">
<input type="button" value="下线" class="close">
</div>
</div>
<div class="container">
<ul class="tab">
<li class="current">快速登录</li>
</ul>
<div class="content">
<div class="maincontent1">
<div class="nickname">
<div class="nicknameT">昵称:</div>
<input type="text" class="nicknameI">
</div>
<div class="password">
<div class="passwordT">密码:</div>
<input type="password" class="passwordI">
</div>
<div class="forget"><a href="#">忘记密码?</a></div>
<input type="button" value="登录" class="loginBtn" id="conectWebSocket">
</div>
</div>
</div>
</body>
<style>
* {
margin: 0;
padding: 0;
text-decoration: none;
}
body {
text-align: center;
}
.container {
width: 400px;
background-color: rgba(189, 218, 234, 0.7);
margin: 200px auto;
border-radius: 30px;
}
.maincontent1 {}
.tab {
display: flex;
justify-content: space-between;
margin: 20px auto 35px auto;
list-style: none;
}
.current {
border-bottom: 2px solid rgba(161, 161, 160,0.8);
}
.tab>li {
width: 100%;
padding: 15px ;
cursor: pointer;
font-size: 20px;
text-shadow: 3px 2px 1px darkgray;
}
.nickname {
display: flex;
justify-content: space-around;
margin: 20px auto 20px auto;
}
.password {
display: flex;
justify-content: space-around;
margin: 20px auto 20px auto;
}
.nicknameI,
.passwordI,
.message,
.toUser{
width: 60%;
height: 25px;
border-radius: 5px;
border: none;
outline: none;
box-shadow: -1px 1px 1px 2px rgba(42, 84, 96, 0.16);
}
.toUser{
width:30px;
margin: 0px 3px 0px 8px;
}
.forget {
width: 90%;
text-align: right;
}
.loginBtn {
width: 80%;
height: 35px;
background-color: rgb(57, 134, 156);
margin: 30px auto 35px auto;
border: none;
border-radius: 7px;
cursor: pointer;
box-shadow: -1px 1px 1px 2px rgba(0, 0, 156, 0.16);
}
.loginBtn:hover {
background: rgb(62, 121, 138);
background-position-x: -280px;
}
.messageBox{
display: none;
margin: 50px auto;
width: 500px;
height: 600px;
border:3px solid rgb(57, 134, 156);
border-radius: 15px;
padding: 10px;
position: relative;
}
.messageBox .send,.close{
width: 45px;
height: 26px;
margin: 0px 3px;
background-color: rgb(57 134 156 / 68%);;
border: none;
border-radius: 7px;
cursor: pointer;
box-shadow: 1px 1px 0px 1px rgb(137 137 145 / 70%);
}
.messageBox .send:hover,.messageBox .close:hover{
background-color: rgb(57, 134, 156);
}
.operate{
width: 100%;
display: flex;
position: absolute;
left:calc(250px - 41%);
bottom: 20px;
}
#messageArea{
width: 400px;
margin:10px auto 20px;
padding:20px;
max-height: 480px;
white-space: pre-line;
word-break: break-all;
overflow-y:auto;
}
.onlineMessage{
width: 430px;
height: 20px;
margin:-5px auto;
}
#messageArea span{
padding: 2px 3px;
margin-top: 3px;
height: 25px;
border-radius: 5px;
border: none;
outline: none;
box-shadow: -1px 1px 1px 2px rgba(42, 84, 96, 0.16);
}
</style>
</html>
后端
首先做一个WebSocket的配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
然后需要一个消息实体类
import lombok.Data;
@Data
public class SocketMsg {
/**
*聊天类型
*/
private int type;
/**
* 发送者
*/
private String fromUser;
/**
* 接收者
*/
private String toUser;
/**
* 消息
*/
private String msg;
}
接着写websocket逻辑
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.qcby.socketdemo.entity.SocketMsg;
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.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @Auther: liu.ning
* @Description: websocket的具体实现类
*/
@Slf4j
@ServerEndpoint(value = "/websocket/{nickname}")
@Component
public class MyWebSocket {
//用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private String nickname;
private static Map<String,Session> map=new HashMap<>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session,@PathParam("nickname") String nickname) {
this.session = session;
this.nickname=nickname;
map.put(session.getId(),session);
//加入set中
webSocketSet.add(this);
System.out.println("有新连接加入:"+nickname+",当前在线人数为" + webSocketSet.size());
this.session.getAsyncRemote().sendText("恭喜您成功连接上WebSocket【"+session.getId()+"】-->当前在线人数为:"+webSocketSet.size());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
System.out.println("有一连接关闭!当前在线人数为" + webSocketSet.size());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session,@PathParam("nickname") String nickname) {
System.out.println("来自客户端的消息-->"+nickname+": " + message);
try{
//从客户端过来的是json数据,将其转换为SocketMsg对象
Gson gson=new Gson();
SocketMsg socketMsg=gson.fromJson(message,SocketMsg.class);
log.info("json转为对象:"+socketMsg);
log.info("map"+map);
if(socketMsg.getType()==1){
//单聊
socketMsg.setFromUser(session.getId());
// socketMsg.setToUser();
Session fromSession=map.get(socketMsg.getFromUser());
log.info("touser:"+socketMsg.getToUser());
Session toSession=map.get(socketMsg.getToUser());
log.info("接收方:"+toSession+"发送方:"+fromSession);
if(toSession!=null){
fromSession.getAsyncRemote().sendText(nickname+":"+socketMsg.getMsg());
toSession.getAsyncRemote().sendText(nickname+":"+socketMsg.getMsg());
}else{
fromSession.getAsyncRemote().sendText("对方不在线或您输入的频道号错误");
}
}else{
//群发消息
broadcast(nickname+": "+socketMsg.getMsg());
}
}catch (JsonParseException e) {
e.printStackTrace();
}
}
/**
* 发生错误时调用
*
*/
@OnError
public void one rror(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* 群发自定义消息
* */
public void broadcast(String message){
for (MyWebSocket item : webSocketSet) {
item.session.getAsyncRemote().sendText(message);//异步发送消息.
}
}
}
到这儿所有想过逻辑都写完了,我们需要一个登录跳转
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class loginController {
@RequestMapping("/login")
public String skip(){
return "login";
}
}
启动项目,打开浏览器 输入http://localhost:8080/login,访问登录页面
(这里端口号因为没做配置所以使用的默认端口号8080,根据自己情况更改)
当然我们可以根据启动信息,找到端口号