单点登录踢下线

dev_2.0.0
liu 1 year ago
parent 74f5ac4514
commit f380b9fc10

@ -41,6 +41,7 @@ public class WebConfig implements WebMvcConfigurer {
paths.add("/error");
paths.add("/favicon.ico");
paths.add("/user/login");
paths.add("/webSocket/**");
// 开发环境,放开不校验token.每次修改这里需要重启(热部署不行)
// paths.add("/**");
return paths;

@ -3,4 +3,6 @@ package com.supervision.constant;
public interface UserTokenConstant {
String TOKEN_CACHE = "USER:LOGIN:TOKEN:";
String KICK_CHANNEL = "USER:KICK:CHANNEL";
}

@ -53,6 +53,11 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
<build>

@ -3,9 +3,11 @@ package com.supervision;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
@SpringBootApplication
@MapperScan(basePackages = {"com.supervision.**.mapper"})
@EnableWebSocket
public class VirtualPatientApplication {
public static void main(String[] args) {

@ -0,0 +1,17 @@
package com.supervision.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 {
/**
* ServerEndpointExporter,Bean使@ServerEndpointwebsocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

@ -0,0 +1,82 @@
package com.supervision.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
@Component
@Slf4j
@ServerEndpoint("/webSocket/{uid}")
public class WebSocketServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static final AtomicInteger onlineNum = new AtomicInteger(0);
//concurrent包的线程安全Set用来存放每个客户端对应的WebSocketServer对象。
private static final CopyOnWriteArraySet<Session> SESSION_POOL = new CopyOnWriteArraySet<Session>();
/**
*
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "uid") String uid) {
SESSION_POOL.add(session);
onlineNum.incrementAndGet();
log.info(uid + "加入webSocket当前人数为" + onlineNum);
}
/**
*
*/
@OnClose
public void onClose(Session session) {
SESSION_POOL.remove(session);
int cnt = onlineNum.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
/**
*
*/
public void sendMessage(Session session, String message) throws IOException {
if (session != null) {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
}
}
/**
*
*/
public void broadCastInfo(String message) throws IOException {
for (Session session : SESSION_POOL) {
if (session.isOpen()) {
sendMessage(session, message);
}
}
}
/**
*
*/
@OnError
public void onError(Session session, Throwable throwable) {
log.error("发生错误");
throwable.printStackTrace();
}
// 实现一个方法用于踢下线用户
public void kickUser(String userId) {
SESSION_POOL.removeIf(session -> session.getUserPrincipal().getName().equals(userId));
}
}

@ -0,0 +1,25 @@
package com.supervision.usermanage;
import com.supervision.constant.UserTokenConstant;
import com.supervision.controller.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class KickUserListener implements MessageListener {
@Autowired
private WebSocketServer webSocketServer;
@Override
public void onMessage(Message message, byte[] pattern) {
String userId = message.toString();
log.info("Redis的Channel:{}收到踢用户下线消息:{}", UserTokenConstant.KICK_CHANNEL, userId);
webSocketServer.kickUser(userId);
}
}

@ -0,0 +1,24 @@
package com.supervision.usermanage;
import com.supervision.constant.UserTokenConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration
public class RedisConfig {
@Autowired
private KickUserListener kickUserListener;
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(kickUserListener, new ChannelTopic(UserTokenConstant.KICK_CHANNEL));
return container;
}
}
Loading…
Cancel
Save