1.什么是WebSocket
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
2.使用springboot中WebSocket实现登录操作
功能描述:不可多人登录一个账号,当他人登录该账号,其他使用该账号的用户自动被挤下线
2.1 导入websocket依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.2 配置websocket,即启用WebSocket的支持
package com.lin.fresh.websocket;
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();
}
}
2.3 WebSocket的服务端
package com.lin.fresh.websocket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
@Component
@ServerEndpoint("/wk/{id}")
public class WebServerSocket {
private static int onlineCount = 0; //在线人数
private Session session;
private String usid; //用户id
private static CopyOnWriteArrayList<WebServerSocket> webSocketSet = new CopyOnWriteArrayList<WebServerSocket>();
@OnOpen
public void onOp(Session session,@PathParam("id")String usid){
this.session = session;
this.usid = usid;
addOnlineCount();
sendMessage("连接websocket服务器成功...."); //给客户端一个响应信息
webSocketSet.add(this);
System.out.println("有新用户"+usid + "上线了,当前用户人数为:" + onlineCount);
// 当前在线人数1
}
/**
* 因为同一时刻只允许一个用户操作,人数+1
*/
private static synchronized void addOnlineCount() {
WebServerSocket.onlineCount ++;
}
/**
* 因为同一时刻只允许一个用户操作,人数-1
*/
private static synchronized void subOnlineCount() {
WebServerSocket.onlineCount --;
}
/**
* 当有连接断开时
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); //从在线列表中移除当前用户;
subOnlineCount(); //人数减一
System.out.println(usid+"下线了,人数"+onlineCount);
}
@OnMessage
public void onMessage(String msg,Session session){
System.out.println("收到来自"+usid + "的信息"+msg);
//群发信息
for (WebServerSocket wss : webSocketSet){
wss.sendMessage(msg);
}
}
@OnError
public void onError(Session session,Throwable error){
error.printStackTrace();
}
/**
* 发送信息给客户端
* @param msg
*/
public void sendMessage(String msg){
try {
this.session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取人数
* @return
*/
public static int getOnlineCount(){
return WebServerSocket.onlineCount;
}
/**
* 获取当前的websocket
* @param usid
* @return
*/
public static WebServerSocket getWebSocket(String usid){
if (webSocketSet.isEmpty()){
return null;
}
for (WebServerSocket wss:webSocketSet) {
if (usid.equals(wss.usid)){
return wss;
}
}
return null;
}
}
2.4 websocket的前端访问
function openWebSocket(id){
var socket;
if (typeof(WebSocket) == undefined){
alert("对不去,你的浏览器不支持WebSocket通信...");
return;
}
socket = new WebSocket("ws://127.0.0.1:80/wk/"+id);
socket.onopen = function(){
console.info("Socket已经连接...");
}
socket.onclose = function(){
console.info("Socket已经断开...");
}
socket.onerror = function(){
console.info("Socket访问服务器失败...");
}
socket.onmessage = function(msg){
if (msg.data == "100"){ //规定,如果响应的是100,则说明是挤退信息
alert("对不起,你已经在其他地方登录,若非本人操作,请及时修改密码...");
location.href="../../admin/loginout"
} else {
console.info(msg);
}
}
}
2.5 Controller
@Controller
@RequestMapping("/admin")
public class AdminInfoController {
@Autowired
private IAdminInfoBiz adminInfoBiz; //访问用户信息表的业务层
@RequestMapping(value="/login2",method=RequestMethod.POST)
@ResponseBody
public Map<String,Object> login2(AdminInfo ad, HttpSession session){
AdminInfo admin = adminInfoBiz.login(ad);
if (admin == null){
return ResponseUtil.responseMap(500,null,null);
}
session.setAttribute("currentLoginBackAdmin", admin);
//判断这个账号有没有在其他地方登录
WebServerSocket wss = WebServerSocket.getWebSocket(String.valueOf(admin.getAid()));
if(wss != null){ //说明在其他地方登录,则发送信息
wss.sendMessage("100");
}
return ResponseUtil.responseMap(200,null,null);
}
@RequestMapping("/checkLogin1")
@ResponseBody
private Map<String,Object> check1(HttpSession session ) {
Object obj = session.getAttribute("currentLoginBackAdmin");
AdminInfo ad = (AdminInfo) obj;
if(obj != null){
return ResponseUtil.responseMap(200, String.valueOf(ad.getAid()), null);
} else {
return ResponseUtil.responseMap(500, null, null);
}
}
}