Springboot2.1集成WebSocket配置wss访问

WebSocket介绍

WebSocket是H5的一种新协议,与http协议基本没有关系,在webSocket没有出现之前,服务端与客户端的通信主要通过轮询来实现,而轮询可以分为两种:传统轮询(Traditional pulling)和长轮询(Long pulling)。

传统轮询,每次都会新建一个http链接,而且不是每次都能够返回需要的数据,当同时发起的请求数量达到一定的数目,会给服务端造成较大的负担。所以,就出现了长轮询。

长轮询:在每次客户端发出请求后,服务器检查上次返回的数据与此次请求时的数据之间是否有更新,如果有更新则返回新数据并结束此次连接,否则服务器 hold 住此次连接,直到有新数据时再返回相应。而这种长时间的保持连接可以通过设置一个较大的 HTTP timeout` 实现。

虽然长轮询可以有效地解决传统轮询带来的带宽浪费,但是每次连接的保持是以消耗服务器资源为代价的。尤其对于Apache+PHP 服务器,由于有默认的 worker threads 数目的限制,当长连接较多时,服务器便无法对新请求进行相应。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务端推送技术的一种。其他特点包括:

  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是 80 和 443 ,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。 
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

IDEA创建SpringBoot项目

 

除以上截图的注意点其余的都是点击next,idea就自动创建成功了。

SpringBoot集成WebSocket

1.在pom.xml中添加依赖

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


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
        <!--webSocket-->

2.新建WebSocket代码配置文件


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

}

3.编写WebSocket设置代码,类似于controller



@Slf4j
@ServerEndpoint(value = "/websocket/{platformType}/{userId}")
@Component
public class WebSocketServer {

    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    public static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    public static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

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

    //接收参数中的用户ID
    public Long userId;

    //接收用户中的平台类型
    public Integer platformType;


    /**
     * 连接建立成功调用的方法
     * 接收url中的参数
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("platformType") Integer platformType, @PathParam("userId") Long userId) {
        this.session = session;
        this.userId = userId;
        this.platformType = platformType;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1

        log.info("有新连接加入!当前在线人数为" + getOnlineCount() + "  userId==== " + userId + "  platformType==== " + platformType);
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("websocket IO异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("来自客户端的消息:" + message);
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误" + error);
        error.printStackTrace();
    }


    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 私发
     *
     * @param message
     * @throws IOException
     */
    public static void sendInfo(Long userId, String message) throws IOException {
        for (WebSocketServer item : webSocketSet) {
            try {
                if (item.userId.equals(userId)) {
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }


    /**
     * 群发自定义消息
     */
    public static void sendInfos(String message) throws IOException {
        log.info(message);
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }


}

此时我们可以从网上查找现成的WebSocket测试工具,输入:ws://localhost:8080/websocket/1/1,点击连接之后,我们可以从界面上看到接收到我们在连接成功发的“连接成功”的字样。

配置ssl,实现wss访问

1.ssl简介

SSl是一种安全协议。

SSL(Secure Sockets Layer)及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。

SSL为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密技术,可确保数据在网络上之传输过程中不会被截取及窃听。一般通用之规格为40 bit之安全标准,美国则已推出128 bit之更高安全标准,但限制出境。

SSL协议位于tcp/ip协议与各种应用层协议之间,为数据通讯提供安全支持。广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。

2.生成自签名证书

keytool -genkeypair -alias tomcat -keyalg RSA -keystore F:\keystore.jks

生成别名为tomcat的自签名证书,保存在F盘。然后按照提示输入个人(单位)信息。

3.项目配置ssl

server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=123456
server.ssl.key-password=123456
server.ssl.key-alias=tomcat

将生成的keystore.jks拷贝到resource下,在application.properties或者application.yml中配置以上信息

4.配置tomcat实现https访问


@Configuration
public class TomcatConfiguration {


    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();

        tomcat.addAdditionalTomcatConnectors(createSslConnector());
        return tomcat;
    }

    private Connector createSslConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        //Connector监听的http的端口号
        connector.setPort(8080);
        connector.setSecure(false);
        //监听到http的端口号后转向到的https的端口号
        connector.setRedirectPort(8443);
        return connector;
    }

    /**
     * 创建wss协议接口
     *
     * @return
     */
    @Bean
    public TomcatContextCustomizer tomcatContextCustomizer() {
        System.out.println("init");
        return new TomcatContextCustomizer() {
            @Override
            public void customize(Context context) {
                System.out.println("init   customize");
                context.addServletContainerInitializer(new WsSci(), null);
            }

        };
    }


}

5.创建简单的控制层访问,测试是否成功


@RestController
@RequestMapping("websocket")
public class TestController {

    @RequestMapping("test")
    public String test() {
        return "Hello World";
    }
}

从界面上可以看出ssl配置成功,实现了https访问,而https访问天然支持webSocket的wss。

6.测试wss

现成的测试网站中,输入wss://localhost:8443/websocket/1/1,在界面中也可以看到“连接成功”的字样。此时需主意的是:不能用IP去访问,需要用域名,否则连接不会成功。从WebSocketde源码阅读可以看出,如果是wss的话,WebSocket会去验证域名,验证不通过直接就抛出io异常,导致链接不成功。

 

代码传送门

 

  • 13
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
在Spring Boot中集成WebSocket可以通过以下步骤实现: 1. 首先,在pom.xml文件中添加WebSocket的依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建一个WebSocketConfig类,用于配置WebSocket相关的参数和处理器: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new WebSocketHandler(), "/websocket"); // 指定WebSocket处理器和连接的路径 } } ``` 3. 创建一个WebSocketHandler类,实现WebSocketHandler接口: ``` @Component public class WebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理收到的文本消息 String payload = message.getPayload(); // 发送消息给所有连接的客户端 for (WebSocketSession webSocketSession : sessions) { webSocketSession.sendMessage(new TextMessage(payload)); } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } } ``` 4. 在Vue中使用WebSocket连接服务器: ``` new Vue({ created() { this.socket = new WebSocket('ws://localhost:8080/websocket'); this.socket.onmessage = this.handleMessage; }, methods: { handleMessage(event) { // 收到消息后的处理逻辑 } } }) ``` 以上是Spring Boot和Vue集成WebSocket的基本步骤。通过配置WebSocketConfig类和创建WebSocketHandler类实现服务器端的消息处理和推送,然后在Vue中创建WebSocket对象进行连接并处理收到的消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值