tomcat的常量类:
public class Constants {
public static final String BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = "org.apache.tomcat.websocket.binaryBufferSize"; public static final String TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = "org.apache.tomcat.websocket.textBufferSize"; public static final String ENFORCE_NO_ADD_AFTER_HANDSHAKE_CONTEXT_INIT_PARAM = "org.apache.tomcat.websocket.noAddAfterHandshake";
public static final String SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE = "javax.websocket.server.ServerContainer"; }
tomcat启动时,会new一个WsServerContainer(它是WsWebSocketContainer的子类), 然后放入ServletContext,名称就是"javax.websocket.server.ServerContainer"。 这个名字好像是java的websocket规范规定的。
(1)创建WsServerContainer实例时,会从web.xml里读取context的param,也就是常量类的前三个。 所以,最简单的设置方法就是web.xml里设置,如: <context-param> <param-name>org.apache.tomcat.websocket.textBufferSize</param-name> <param-value>81920</param-value> </context-param> <context-param> <param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name> <param-value>81920</param-value> </context-param> 默认8192字节,也就是8KB
(2)第二种,是spring的ServletServerContainerFactoryBean, 它会从ServletContext中获取ServerContainer this.serverContainer = (ServerContainer)servletContext.getAttribute("javax.websocket.server.ServerContainer"); 然后给ServerContainer设置参数,如这两个BufferSize。
<bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean"> <property name="maxTextMessageBufferSize" value="81920"/> <property name="maxBinaryMessageBufferSize" value="81920"/> </bean>
或者注解方式
@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer {
@Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(81920); container.setMaxBinaryMessageBufferSize(81920); return container; } }
效果跟第一种一样的,只是赋值时机不同。
(3)第三种,就是手写代码
webSocketContainer = ContainerProvider.getWebSocketContainer(); webSocketContainer.setDefaultMaxTextMessageBufferSize(81920); webSocketContainer.setDefaultMaxBinaryMessageBufferSize(81920);
tomcat的话,getWebSocketContainer每次都new了一个WsWebSocketContainer返回的, 所以每次都要设置。
(4)注解@ServerEndpoint,就是注册入口 @ServerEndpoint(value = "/xx/yyy", configurator = SpringConfigurator.class) public class xxxWebsocketServer{}
tomcat启动时,会扫描这个注解,然后自动注册。 用的ServerContainer就是ServletContext中那个。 这个ServerContainer是单例,全局唯一的。
(5)创建WsSession时,会从ServerContainer获取这两个Size,复制给session的俩属性。 创建buffer时,会用这俩属性来设置大小。 所以,这个size是每个session的buffer大小,不能设置得太大。session一多,就完蛋了。
(6)服务端,收到消息超过buffersize时, 服务端返回关闭websocket的消息:The decoded text message was too big for the output buffer and the endpoint does not support partial messages 客户端回复关闭websocket。 然后双向关闭socket连接。 具体代码在tomcat的WsFrameBase里。
|