springboot 整合 websocket

pom.xml文件添加依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

WebSocketConfig

import com.common.config.MyEndpointConfigure;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocket配置
 * @Author JYuan
 */
@Configuration
public class WebSocketConfig{

    /**
     * 用途:扫描并注册所有携带@ServerEndpoint注解的实例。 @ServerEndpoint("/websocket")
     * PS:如果使用外部容器 则无需提供ServerEndpointExporter。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    /**
     * 支持注入其他类
     */
    @Bean
    public MyEndpointConfigure myEndpointConfigure(){
        return new MyEndpointConfigure();
    }
}

MyEndpointConfigure

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.websocket.server.ServerEndpointConfig;

/**
 * @Author JYuan
 */
public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {

    private static volatile BeanFactory context;

    @Override
    public <T> T getEndpointInstance(Class<T> clazz){
        return context.getBean(clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyEndpointConfigure.context = applicationContext;
    }
}

WebSocketServer

import com.alibaba.fastjson.JSONObject;
import com.common.config.MyEndpointConfigure;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



/**
 * WebSocket服务
 * @Author JYuan
 */
@RestController
@RequestMapping("/websocket")
@ServerEndpoint(value = "/websocket/{userNo}", configurator = MyEndpointConfigure.class)
public class WebSocketServer {

    /**
     * 在线人数
     */
    private static int onlineCount = 0;

    /**
     * 在线用户的Map集合,key:用户名,value:Session对象
     */
    private static Map<String, Session> sessionMap = new HashMap<>();


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userNo") String userNo { 
        //在webSocketMap新增上线用户
        sessionMap.put(userNo, session);
        //在线人数加加
        WebSocketServer.onlineCount++;
        //通知除了自己之外的所有人
         sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + username + "'}");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("userType") String userType) {
        //下线用户名
        String logoutUserName = "";

        //从webSocketMap删除下线用户
        for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
            if (entry.getValue() == session) {
                sessionMap.remove(entry.getKey());
                logoutUserName = entry.getKey();
                break;
            }
        }
        //在线人数减减
        WebSocketServer.onlineCount--;
        //通知除了自己之外的所有人
        sendOnlineCount(session, "{'type':'onlineCount','onlineCount':" + WebSocketServer.onlineCount + ",username:'" + logoutUserName + "'}");
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            //JSON字符串转 HashMap
            HashMap hashMap = new ObjectMapper().readValue(message, HashMap.class);

            //消息类型
            String type = (String) hashMap.get("type");

            //来源用户
            Map srcUser = (Map) hashMap.get("srcUser");

            //目标用户
            Map tarUser = (Map) hashMap.get("tarUser");

            //如果点击的是自己,那就是群聊
            if (srcUser.get("userNo").equals(tarUser.get("userNo"))) {
                //群聊
                groupChat(session,hashMap);
            } else {
                //私聊
                privateChat(session, tarUser, hashMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
     public void onError(Throwable e){
        e.printStackTrace();
    }

    /**
     * 通知除了自己之外的所有人
     */
    private void sendOnlineCount(Session session, String message) {
        for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
            try {
                if (entry.getValue() != session) {
                    entry.getValue().getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 私聊
     */
    private void privateChat(Session session, Map tarUser, HashMap hashMap) throws IOException {
        //获取目标用户的session
        Session tarUserSession = sessionMap.get(tarUser.get("userNo"));
        //如果不在线则发送“对方不在线”回来源用户
        if (tarUserSession == null) {
            session.getBasicRemote().sendText("{\"type\":\"0\",\"message\":\"对方不在线\"}");
        } else {
            hashMap.put("type", "1");
            tarUserSession.getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
        }
    }

    /**
     * 群聊
     */
    private void groupChat(Session session,HashMap hashMap) throws IOException {
        for (Map.Entry<String, Session> entry : sessionMap.entrySet()) {
            //自己就不用再发送消息了
            if (entry.getValue() != session) {
                hashMap.put("type", "2");
                entry.getValue().getBasicRemote().sendText(new ObjectMapper().writeValueAsString(hashMap));
            }
        }
    }

    /**
     * 登录
     */
    public ModelAndView login(HttpServletRequest request, @PathVariable String userNo, @PathVariable String userType) {
        return new ModelAndView("socketChart.html", "userNo", userNo);
    }

    /**
     * 登出
     */
    public String loginOut(HttpServletRequest request, @PathVariable String userNo) {
        return "退出成功!";
    }

    /**
     * 获取在线用户
     */
    @PostMapping("/getOnlineList")
    private List<String> getOnlineList(@RequestBody JSONObject requestJson) {
        String userNo = requestJson.getString("userNo");
        List<String> list = new ArrayList<>();
        //遍历webSocketMap
        for (Map.Entry<String, Session> entry : WebSocketServer.sessionMap.entrySet()) {
            if (!entry.getKey().equals(userNo)) {
                list.add(entry.getKey());
            }
        }
        return list;
    }

}

其他问题

项目启动报错

Registering @ServerEndpoint class: class com.cxy.common.controller.WebSocketServer$$EnhancerBySpringCGLIB$$badc049a

问题是EnhancerBySpringCGLIB,可以看出来,使用了CGLIB代理,那么问题就很明显了,此类被AOP做了代理,在AOP中将此类移除就可以了。

@Pointcut("execution(* com.*.controller..*(..)) && !execution(* com.common.controller.WebSocketServer.*(..))")
    public void aspect() {
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值