springBoot和Websocket(tomcat/netty)

基于web服务器的websocket

  • pom
	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-websocket</artifactId>
		</dependency>
		
  • 使用
    • 注入ServerEndpointExporter
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
	
    • 声明端口


@ServerEndpoint("/webim/{userid}")
@Slf4j
public class WebSocketEndpoint {

  

	@OnOpen
	public void open(@PathParam("userid") String userid, Session session){
	
	}
	
	@OnClose
	public void close(@PathParam("userid") String userid, Session session){
		log.info("on close : " + userid);
	}
	
	@OnError
	public void error(@PathParam("userid") String userid, Session session, Throwable error){
		log.info("on error : " + userid);
	}
	
	@OnMessage
	public void handleMessage(@PathParam("userid") String userid, Session session, String message) throws IOException {
		log.info(userid + " on message :" )
	}

}

基于netty的websocket

  • 推荐:https://gitee.com/Yeauty/netty-websocket-spring-boot-starter

代码解读

在spring.factories中定义了需要加载的配置项:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.yeauty.autoconfigure.NettyWebSocketAutoConfigure

在配置项中,使用了注解@EnableWebSocket,所以我们可以通过@EnableWebSocket来定义我们的websocket server

@EnableWebSocket
public class NettyWebSocketAutoConfigure {
}

EnableWebSocket通过Import的方式又加载了NettyWebSocketSelector,并且在里面创建了一个ServerEndpointExporter,这是整个服务的核心类。
ServerEndpointExporter主要做了以下工作:

  • 完成了websocket服务地址和netty server实例的对应并且缓存。注意,整个实例是spring的代理类。
//ServerEndpointExporter.java
//可以创建多个websocket服务
 private final Map<InetSocketAddress, WebsocketServer> addressWebsocketServerMap = new HashMap<>();
 

那么,addressWebsocketServerMap 又是怎么添加上的?

//继承ApplicationObjectSupport就可以通过getApplicationContext()取到上下文,从而取到对应的代理类
public class ServerEndpointExporter extends ApplicationObjectSupport implements SmartInitializingSingleton, BeanFactoryAware {
    protected void registerEndpoints() {
    // 通过ServerEndpoint取到SpringContext中的ServerEndpoint代理实例。
        Set<Class<?>> endpointClasses = new LinkedHashSet<>();

        ApplicationContext context = getApplicationContext();
        if (context != null) {
            String[] endpointBeanNames = context.getBeanNamesForAnnotation(ServerEndpoint.class);
            for (String beanName : endpointBeanNames) {
                endpointClasses.add(context.getType(beanName));
            }
        }

        for (Class<?> endpointClass : endpointClasses) {
            registerEndpoint(endpointClass);
        }
        //调用了WebsocketServer的init
        init();
    }
    ....
    }

WebsocketServer在init方法中启动了netty server。并且添加了一个HttpServerHandler,在read方法中完成了消息的读取、发送、握手等操作。

HttpServerHandler.java
HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> 

创建websocket需要注意的事项

  1. 安全性:只有系统用户可以连接,因此,在握手时需要校验身份。
  2. 重连机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值