快速搭建springboot websocket客户端

一、前言

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

二、快速搭建springboot-websocket项目的服务端

1 导入依赖

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

2 创建配置类

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3 创建WebSocketServer服务类 用来接收数据

websocket的常用注解只有这5个

  • @ServerEndpoint注意上下文路径,websocket连接地址

  • @OnMessage只有第一次加载websocket的时候,会调用,生命周期只有一次

  • @OnClose只有关闭websocket链接的时候,会调用,生命周期只有一次

  • @OnMessage每次接收信息的时候,都会调用,调用比较频繁

  • @OnError发生错误的时候调调用

/**
 * 类似RequestMapping的地址
 * ws://localhost:8080/ws/000001
 */
@ServerEndpoint("/ws/{uuid}")
@Component
public class WebSocketServer {

    private Session session; //客户端会话
    
    //存放每个客户端的连接会话
    public static ConcurrentHashMap<String,WebSocketServer> clients = new ConcurrentHashMap<>();
    
    //开启连接
    //存入连接回话中
    @OnOpen
    public void onOpen(Session session, @PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        this.session = session;
        clients.put(uuid,this);
    }

    //发送消息
    @OnMessage
    public void OnMessage(String msg, @PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        System.out.println("收到消息: "+msg);
    }

    //关闭连接
    @OnClose
    public void onClose(@PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        System.out.println("关闭socket连接"+uuid);
        clients.remove(uuid);
    }
    //发生异常的情况
    @OnError
    public void onError(Throwable error) {
        error.printStackTrace();
    }
    
}

4 启动项目

三、一般都是前端为客户端,后端为服务端这种方式

前端客户端,我不会,需要的自己百度,哈哈哈

四、搭建java-websocket客户端

该案例,只是告诉大家,可以用java搭建客户端

4.1 依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.5</version>
        </dependency>

4.2 客户端代码

@Component
public class WebSocketConfig {
 
    @Bean
    public WebSocketClient webSocketClient() {
        try {
                WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://localhost:8081/ws/000001"),new Draft_6455()) {
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    System.out.println("ws 连接成功");
                }
 
                @Override
                public void onMessage(String message) {
                    System.out.println("ws 收到消息"+message);
 
                }
 
                @Override
                public void onClose(int code, String reason, boolean remote) {
                    System.out.println("ws 退出");
                }
 
                @Override
                public void onError(Exception ex) {
                    System.out.println("连接错误"+ex.getMessage());
                }
            };
            webSocketClient.connect();
            return webSocketClient;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
}

4.3 发送消息的代码

@SpringBootApplication
@RestController
public class SpringbootWebsocketClientApplication {


    @Autowired
    private WebSocketClient webSocketClient;

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebsocketClientApplication.class, args);
    }


    @RequestMapping("/get")
    public String send(){
        webSocketClient.send("我是ws客户端,你好!!!");
        return "发送成功";
    }

}

4.4 结果

4.5 服务端收到消息

当前的uuid为:000001
收到消息: 我是ws客户端,你好!!!

websocket传递头信息,协议头token的前后端解决方案

  1. js websocket 传递token

websocket协议在握手阶段借用了HTTP的协议,但是在JavaScript websocketAPI中并没有修改请求头的方法。

1.1 基于协议头

websocket请求头中可以包含Sec-WebSocket-Protocol这个属性,该属性是一个自定义的子协议。它从客户端发送到服务器并返回从服务器到客户端确认子协议。我们可以利用这个属性添加token。

var token='fasdfadfasdfa'

var  ws = new WebSocket("ws://" + url+ "/webSocketServer",[token]);
  1. 后台取出websocket协议头的参数

2.1 取出token

token = ((HttpServletRequest) servletRequest).getHeader("Sec-WebSocket-Protocol");

2.2 注意大坑

如果传递了token参数,后端响应的时候,也必须带上这个token响应!否则前端接收不到数据!

可以采用servlet的过滤器来做

@Order(1)
@Component
@WebFilter(filterName = "WebsocketFilter", urlPatterns = "/home/*")
public class WebsocketFilter implements Filter {
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String token = ((HttpServletRequest) servletRequest).getHeader("Sec-WebSocket-Protocol");

        response.setHeader("Sec-WebSocket-Protocol",token);

        filterChain.doFilter(servletRequest, servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}

六、结尾

websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据。

第一、WebSocket是HTML5中的协议,支持持久连接;而Http协议不支持持久连接。

第二、首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说

HTTP的生命周期通过 Request 来界定,也就是一个 Request 一个 Response ,那么在 HTTP1.0 中,这次HTTP请求就结束了。

在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。

第三、传统的http请求,其并发能力都是依赖同时发起多个TCP连接访问服务器实现的(因此并发数受限于浏览器允许的并发连接数),而websocket则允许我们在一条ws连接上同时并发多个请求,即在A请求发出后A响应还未到达,就可以继续发出B请求。由于TCP的慢启动特性(新连接速度上来是需要时间的),以及连接本身的握手损耗,都使得websocket协议的这一特性有很大的效率提升。

第四、http协议的头部太大,且每个请求携带的几百上千字节的头部大部分是重复的,很多时候可能响应都远没有请求中的header空间大。如此多无效的内容传递是因为无法利用上一条请求内容,websocket则因为复用长连接而没有这一问题。

第五、当需要实现客户端刷新消息时,传统方案往往通过定时ajax请求实现,实际上对多数用户多数时间下这些请求都是无意义了,并且非常占用资源,websocket资源占用就小很多

猜你喜欢

转载自blog.csdn.net/qq_39706515/article/details/130064394