websocket-cometd源碼閱讀-transport

說明

transport就是我們的處理器器,比如websoket通信,http長輪詢,支持jsonp方式的長輪詢

如我們的初始化配置的代碼

  @Bean(initMethod = "start", destroyMethod = "stop")
    public BayeuxServer bayeuxServer() {
        BayeuxServerImpl bean = new BayeuxServerImpl();
        bean.setTransports(new WebSocketTransport(bean), new JSONTransport(bean), new JSONPTransport(bean));
        servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bean);
        bean.setOption(ServletContext.class.getName(), servletContext);
        bean.setOption("ws.cometdURLMapping", "/cometd/*");
        return bean;
    }

類圖

接口

Transport定義

定義一些獲取transport名字 以及配置的的接口

public interface Transport {
    /**
     * @return The well known name of this transport, used in transport negotiations
     * @see Bayeux#getAllowedTransports()
     * 獲得協議名稱,用於請求的時候根據參數名稱找到對應的處理器
     */
    String getName();

    /**
     * @param name the configuration option name
     * @return the configuration option with the given {@code qualifiedName}
     * @see #getOptionNames()
     * 獲取配置相關參數
     */
    Object getOption(String name);

    /**
     * @return the set of configuration options
     * @see #getOption(String)
     * 獲取配置相關參數的names
     */
    Set<String> getOptionNames();

    /**
     * Specifies an option prefix made of string segments separated by the "."
     * character, used to override more generic configuration entries.
     *
     * @return the option prefix for this transport.
     */
    String getOptionPrefix();
}

ServerTransport

服務性質的transport,比如會定義一些獲取超時配置

public interface ServerTransport extends Transport {
    /**
     * @return the timeout (in milliseconds) of this transport
     * 傳輸超時時間
     */
    public long getTimeout();

    /**
     * @return the interval of time (in milliseconds) of this transport
     * 傳輸間隔,比如輪訓/meta/connect
     */
    public long getInterval();

    /**
     * @return the maximum interval of time (in milliseconds) before the server consider the client lost
     * 最大間隔時間,超過這個時間服務端認爲斷開連接  比如多久沒調用/meta/connect
     */
    public long getMaxInterval();

    /**
     * @return the maximum time (in milliseconds) before dispatching lazy messages
     * 調度延遲消息之前的最長時間(毫秒)
     */
    public long getMaxLazyTimeout();

    /**
     * @return whether the messages are delivered to clients exclusively via the "/meta/connect" channel
     * 消息是否僅通過“/meta/connect”通道傳遞給客戶端  
     */
    public boolean isMetaConnectDeliveryOnly();
}

AbstractTransport

僅僅定義了封裝transport名字以及參數,以及獲得相關option參數方法的實現

public class AbstractTransport implements Transport {
    private final String _name;
    private final Map<String, Object> _options;
    private String[] _prefix = new String[0];
    private String _optionPrefix = "";

    protected AbstractTransport(String name, Map<String, Object> options) {
        _name = name;
        _options = options == null ? new HashMap<>(1) : options;
    }

    @Override
    public String getName() {
        return _name;
    }

    /**
     * Returns an option value for the given option name, searching the option name tree.
     * The option map is searched for the option name with the most specific prefix.
     * If this transport was initialized with a call to:
     * <pre>
     *   setOptionPrefix("long-polling.jsonp");
     * </pre>
     * then a call to getOption("foobar") will look for the
     * most specific value with names:
     * <pre>
     *   long-polling.json.foobar
     *   long-polling.foobar
     *   foobar
     * </pre>
     *
     * @param name the option name to return the value for.
     */
    @Override
    public Object getOption(String name) {
        Object value = _options.get(name);
        String prefix = null;
        for (String segment : _prefix) {
            prefix = prefix == null ? segment : (prefix + "." + segment);
            String key = prefix + "." + name;
            if (_options.containsKey(key)) {
                value = _options.get(key);
            }
        }
        return value;
    }

    /**
     * Sets the option value with the given name.
     * The option name is inspected to see whether it starts with the {@link #getOptionPrefix() option prefix};
     * if it does not, the option prefix is prepended to the given name.
     *
     * @param name  the option name to set the value for.
     * @param value the value of the option.
     */
    public void setOption(String name, Object value) {
        String prefix = getOptionPrefix();
        if (prefix != null && prefix.length() > 0 && !name.startsWith(prefix)) {
            name = prefix + "." + name;
        }
        _options.put(name, value);
    }

    @Override
    public String getOptionPrefix() {
        return _optionPrefix;
    }

    /**
     * Set the option name prefix segment.
     * <p> Normally this is called by the super class constructors to establish
     * a naming hierarchy for options and iteracts with the {@link #setOption(String, Object)}
     * method to create a naming hierarchy for options.
     * For example the following sequence of calls:<pre>
     *   setOption("foo","x");
     *   setOption("bar","y");
     *   setOptionPrefix("long-polling");
     *   setOption("foo","z");
     *   setOption("whiz","p");
     *   setOptionPrefix("long-polling.jsonp");
     *   setOption("bang","q");
     *   setOption("bar","r");
     * </pre>
     * will establish the following option names and values:<pre>
     *   foo: x
     *   bar: y
     *   long-polling.foo: z
     *   long-polling.whiz: p
     *   long-polling.jsonp.bang: q
     *   long-polling.jsonp.bar: r
     * </pre>
     * The various {@link #getOption(String)} methods will search this
     * name tree for the most specific match.
     *
     * @param prefix the prefix name
     * @throws IllegalArgumentException if the new prefix is not prefixed by the old prefix.
     */
    public void setOptionPrefix(String prefix) {
        if (!prefix.startsWith(_optionPrefix)) {
            throw new IllegalArgumentException(_optionPrefix + " not prefix of " + prefix);
        }
        _optionPrefix = prefix;
        _prefix = prefix.split("\\.");
    }

    @Override
    public Set<String> getOptionNames() {
        Set<String> names = new HashSet<>();
        for (String name : _options.keySet()) {
            int lastDot = name.lastIndexOf('.');
            if (lastDot >= 0) {
                name = name.substring(lastDot + 1);
            }
            names.add(name);
        }
        return names;
    }

    /**
     * Get option or default value.
     *
     * @param option   The option name.
     * @param dftValue The default value.
     * @return option or default value
     * @see #getOption(String)
     */
    public String getOption(String option, String dftValue) {
        Object value = getOption(option);
        return (value == null) ? dftValue : value.toString();
    }

    /**
     * Get option or default value.
     *
     * @param option   The option name.
     * @param dftValue The default value.
     * @return option or default value
     * @see #getOption(String)
     */
    public long getOption(String option, long dftValue) {
        Object value = getOption(option);
        if (value == null) {
            return dftValue;
        }
        if (value instanceof Number) {
            return ((Number)value).longValue();
        }
        return Long.parseLong(value.toString());
    }

    /**
     * Get option or default value.
     *
     * @param option   The option name.
     * @param dftValue The default value.
     * @return option or default value
     * @see #getOption(String)
     */
    public int getOption(String option, int dftValue) {
        Object value = getOption(option);
        if (value == null) {
            return dftValue;
        }
        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        return Integer.parseInt(value.toString());
    }

    /**
     * Get option or default value.
     *
     * @param option   The option name.
     * @param dftValue The default value.
     * @return option or default value
     * @see #getOption(String)
     */
    public boolean getOption(String option, boolean dftValue) {
        Object value = getOption(option);
        if (value == null) {
            return dftValue;
        }
        if (value instanceof Boolean) {
            return (Boolean)value;
        }
        return Boolean.parseBoolean(value.toString());
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章