POM文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
配置文件
public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
private static volatile BeanFactory context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
MySpringConfigurator.context = applicationContext;
}
@Override
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
return context.getBean(clazz);
}
}
@Configuration
@ConditionalOnWebApplication
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public MySpringConfigurator mySpringConfigurator() {
return new MySpringConfigurator();
}
}
核心代码
@Slf4j
@Component
@ServerEndpoint(value = "/education/bes/v1/system/user/websocket/{userOnlineInfoId}")
public class WebSocket {
private static int onlineCount = 0;
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
private Session session;
private String userOnlineInfoId;
@OnOpen
public void onOpen(@PathParam("userOnlineInfoId") String userOnlineInfoId, Session session) throws IOException {
this.userOnlineInfoId = userOnlineInfoId;
this.session = session;
beforeOpen();
addOnlineCount();
clients.put(userOnlineInfoId, this);
log.info("{}: 上线,已连接: {}", userOnlineInfoId, getOnlineCount());
}
@OnClose
public void onClose() throws IOException {
beforeClose();
clients.remove(userOnlineInfoId);
subOnlineCount();
log.info("{}: 下线,已连接: {}", userOnlineInfoId, getOnlineCount());
}
@OnMessage
public void onMessage(String message) throws IOException {
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
public void sendMessageTo(CommonResponse commonResponse, String To) throws IOException {
for (WebSocket item : clients.values()) {
if (item.userOnlineInfoId.equals(To)){
item.session.getAsyncRemote().sendText(JSON.toJSONString(commonResponse));
break;
}
}
}
public void sendMessageToList(CommonResponse commonResponse, List<String> ToList) throws IOException {
for (WebSocket item : clients.values()) {
if(ToList.contains(item.userOnlineInfoId)){
item.session.getAsyncRemote().sendText(JSON.toJSONString(commonResponse));
}
}
}
public void sendMessageAll(String message) throws IOException {
for (WebSocket item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
public void beforeOpen() throws IOException {
for (WebSocket item : clients.values()) {
if(item.userOnlineInfoId.equals(userOnlineInfoId)){
sendMessageTo(CommonResponse.Builder.fail(ErrorCodeConstant.USER_ONLINE_CROWDING_OUT, ErrorCodeConstant.USER_ONLINE_CROWDING_OUT_MSG), userOnlineInfoId);
onClose();
break;
}
}
}
public void beforeClose() throws IOException {
UserOnlineInfoDto userOnlineInfoDto = new UserOnlineInfoDto();
userOnlineInfoDto.setUserOnlineInfoId(Long.parseLong(userOnlineInfoId));
ApplicationContext act = ApplicationContextRegister.getApplicationContext();
IUserOnlineService userOnlineService = act.getBean(IUserOnlineService.class);
userOnlineService.logout(userOnlineInfoDto);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
public static synchronized Map<String, WebSocket> getClients() {
return clients;
}
}
工具类
@Component
@Lazy(false)
public class ApplicationContextRegister implements ApplicationContextAware {
private static ApplicationContext APPLICATION_CONTEXT;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
APPLICATION_CONTEXT = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return APPLICATION_CONTEXT;
}
}
前端部分
import { MessageBox } from 'element-ui'
import store from '@/store'
const state = {
websocket: null,
websocketonmessage: null
}
const mutations = {
SET_WEBSOCKET: (state, websocket) => {
state.websocket = websocket
},
SET_WEBSOCKETONMESSAGE: (state, websocketonmessage) => {
state.websocketonmessage = websocketonmessage
if(websocketonmessage.head.code !== '0'){
store.dispatch('user/logout')
MessageBox.confirm(websocketonmessage.head.message, '提示', {
showClose: false,
closeOnClickModal: false,
closeOnPressEscape: false,
showCancelButton: false,
confirmButtonText: '确定',
type: 'warning'
}).then(() => {
location.reload()
})
}
}
}
const actions = {
initWebSocket({commit}, userOnlineInfoId){
return new Promise((resolve, reject) => {
const wsuri = `ws://localhost:9700/education/bes/v1/system/user/websocket/${userOnlineInfoId}`
commit('SET_WEBSOCKET', new WebSocket(wsuri))
state.websocket.onmessage = function(e){
let res = JSON.parse(e.data)
commit('SET_WEBSOCKETONMESSAGE', res)
}
resolve()
})
},
destoryedWebSocket(){
return new Promise((resolve) => {
state.websocket.close()
resolve()
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
await store.dispatch('webSocket/initWebSocket', localStorage.getItem('userOnlineInfoId'))
await store.dispatch('webSocket/destoryedWebSocket')