java实现websocket server/client

最近在项目中有一个场景,在内网的应用需要接受外网应用的指令。有两种解决方案:

1.内网应用轮询外网应用,http请求指令

2.内网应用与外网应用之间建立websocket长连接

记录一下websocket server/client的java实现

一、websocket server

@Configuration
public class WebSocketConfig extends Configurator
{
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketConfig.class);

    /**
     * 首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。
     * 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
     *
     * @return ServerEndpointExporter
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter()
    {
        return new ServerEndpointExporter();
    }

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request,
                                HandshakeResponse response)
    {
        /* 如果没有监听器,那么这里获取到的HttpSession是null */
        StandardSessionFacade ssf = (StandardSessionFacade)request.getHttpSession();
        if (ssf != null)
        {
            HttpSession httpSession = (HttpSession)request.getHttpSession();
            // 关键操作
            sec.getUserProperties().put("sessionId", httpSession.getId());
            LOGGER.debug("获取到的SessionID:" + httpSession.getId());
        }
    }

}
@Component
@ServerEndpoint(value = "/ws/{userId}")
public class WebSocketServer
{
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);

    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    // 保存允许建立连接的id
    private static List<String> idList = Lists.newArrayList();

    private String id = "";

    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    /**
     * <关闭连接>
     *
     * @param userId userId
     * @throws
     */
    public void closeConn(String userId)
    {
        // 关闭连接
        try
        {
            WebSocketServer socket = webSocketMap.get(userId);
            if (null != socket)
            {
                if (socket.session.isOpen())
                {
                    socket.session.close();
                }
            }
        }
        catch (IOException e)
        {
            LOGGER.error("error, cause: ", e);
        }
        webSocketMap.remove(userId);
        idList.remove(userId);
    }

    /**
     * <连接/注册时去重>
     *
     * @param userId userId
     * @throws
     */
    public void conn(String userId)
    {
        // 去重
        if (!idList.contains(userId))
        {
            idList.add(userId);
        }
    }

    /**
     * <获取注册在websocket进行连接的id>
     *
     * @return 结果
     * @throws
     */
    public static List<String> getIdList()
    {
        return idList;
    }

    /**
     * <初始化方法>
     *
     * @throws
     */
    @PostConstruct
    public void init()
    {
        try
        {
            /**
             * TODO 这里的设计是在项目启动时从DB或者缓存中获取注册了允许建立连接的id
             */
            // TODO 初始化时将刚注入的对象进行静态保存

        }
        catch (Exception e)
        {
            // TODO 项目启动错误信息
            LOGGER.error("error, cause: ", e);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值