springboot 与 微信小程序实现 WebSocket通信

2019-11-07  本文已影响0人  这是个懒得不想动脑的昵称

文章摘要

由于项目功能需求,要在springboot与微信小程序之间实现WebSocket连接,Google了一天虽然底层还不明白,但至少能跑起来能用不是么。
此文章将记录从新建项目开始的大多数操作,如哪里有错误请诸位看到的大佬指点下,谢谢
spring版本:2.2.0
java版本:1.8
Tomcat版本:9.0.27
maven版本:3.5.4
微信小程序开发工具版本:Stable V1.02.1910120
微信小程序开发工具基础调试库版本:2.9.2
这些一路默认各位大佬已经配置好了,如果没有配置好,emm,不怪我,别找我

tomcat配置SSL后可以直接用wss连接,不需要做额外的配置。也就是https能正常连接,那么wss也可以正常连接

微信小程序WebSocket实现

先写一下微信小程序的吧,因为spring实现WebSocket有三种方式,我会写下其中两种。微信小程序的WebSocket实现就这一种(我只是根据官方文档来的,也许会有多种),要看spring的直接往下滑吧。代码就不过多解释了,请参考官方文档,肯定比我了解的详细多了

wechatdevtools_3tl0dh9EDM.png

页面wxml代码

<text>{{response}}</text>

页面js代码

Page({

  /**
   * 页面的初始数据
   */
  data: {
    response:""
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    var that = this

    // 创建一个 WebSocket 连接
    wx.connectSocket({
      url: 'ws://127.0.0.1:8088/WebSocketDemo_war/websocketapi',
    })
    /////////////////////////

    // 监听 WebSocket 连接打开事件
    wx.onSocketOpen(function (res){

      // 通过 WebSocket 连接发送数据
      wx.sendSocketMessage({
        data: "Hello Spring WebSocket",
        success(){
          console.log("数据发送成功")

          // 监听 WebSocket 接受到服务器的消息事件
          wx.onSocketMessage(function(re){
            that.setData({ response: re.data})
            console.log("SocketMessage: "+re.data)
          })
          //////////////////////////////////////

        },
        fail(){
          console.log("数据发送失败")
        }
      })
      /////////////////////////////

    })
    ///////////////////////////////
  },
  
})

SpringBoot WebSocket实现

新建springboot项目
新建项目,选Spring Initializr,next 想调的可以随便调,这里我作为演示就不动了,一律默认,next 这里再Spring Web打上勾,next 项目名字可以更改,这里我改了下,Finish

接下来就让代码跑一会儿,等创建完成

创建完就是这个样子了,记得把右下角的Enable Auto-Import点了

springboot内置了tomcat,所以可以有两种方式启动,一种使用spring内置的Tomcat启动,一种用外置Tomcat启动。使用mvn命令打包后第一种生成Jar包,第二种生成War包。我就两个都写一下吧。
下面是pom.xml文件配置

使用spring内置Tomcat启动,直接在<dependencies>标签内添加以下代码

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

使用外置Tomcat启动需要额外做一些修改,额外添加以下代码

<packaging>war</packaging>

<dependency>
  <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 移除嵌入式tomcat插件 -->
    <exclusions>
      <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
      </exclusion>
    </exclusions>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
        相当于compile,但是打包阶段做了exclude操作-->
    <scope>provided</scope>
</dependency>

下面是我的完整的pom.xml文件配置,因为要打包成war包,也就是使用外置Tomcat启动。所以各位根据自己需要看着改吧。其实都可以添加到pom里。在idea里不影响,两种都能启动。如果需要使用mvn命令打包的话还是改改吧。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <!--    打包成war包,添加第18行代码-->
    <packaging>war</packaging>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 在这里添加 29-35行代码-->
            <!-- 移除嵌入式tomcat插件 -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 在这里添加 39-45行代码-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
                相当于compile,但是打包阶段做了exclude操作-->
            <scope>provided</scope>
        </dependency>

        <!-- 添加 48-51行代码-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

在基于Spring的应用中使用WebSocket一般可以有以下三种方式(也许会有多总,我这里只写前两种):

  1. 使用Java提供的@ServerEndpoint注解实现
  2. 使用Spring提供的低层级WebSocket API实现
  3. 使用STOMP消息实现
使用@ServerEndpoint注解实现

在com.example.demo下新建Controller包,在Controller包里新建WebSocketServerEndpoint类,在WebSocketServerEndpoint类添加代码。

类名不一样的注意修改

代码:

@ServerEndpoint("/websocketapi")
public class WebSocketServerEndpoint {
    @OnMessage
    public void handleMessage(Session session, String message) throws IOException {
        System.out.println("服务器接收到的消息:"+message);
        session.getBasicRemote().sendText("服务器回复的消息: " + "Hello,Are you OK?");
    }
}
使用外置Tomcat启动
添加tomcat,会使用外置的tomcat来运行,注意URL和端口号,我这里改了下
添加时右下角会有一个Fix报错,点他选第一个
使用spring内置Tomcat启动

Jar包启动需要额外配置一下,在Controller包里新建WebSocketServerEndpointConfig类,添加代码


@Configuration
@EnableWebSocket
public class WebSocketServerEndpointConfig {

    @Bean
    public WebSocketServerEndpoint reverseWebSocketEndpoint() {
        return new WebSocketServerEndpoint();
    }

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

配置完成后,直接点右上角启动DemoApplication。
如果要以外置Tomcat启动,请把WebSocketServerEndpointConfig注释掉,否则会报错

添加完后点击运行就OK了。
然后在微信小程序的js文件里填入WebSocketURL:
使用外置Tomcat启动URL:ws://127.0.0.1:8088/WebSocketDemo_war/websocketapi
使用spring内置Tomcat启动URL:ws://127.0.0.1:8088/websocketapi
(注:因为在application.properties配置了端口使用8088,所以这里不是8080,如果application.properties没有配置,默认使用8080)

可以看到微信小程序连接成功。我这里用外置Tomcat启动的,使用spring内置Tomcat启动请修改URL,
服务器也连接成功

使用Spring提供的低层级WebSocket API实现

在Controller包里新建类WebSocketConfig,添加代码。
"websocketapi"为ws的URL路径,可自行修改。
因为spring默认不接受跨域访问,设置setAllowedOrigins("*")允许接收跨域访问。


@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(handler(), "websocketapi").setAllowedOrigins("*");
    }
    
    @Bean
    public CustomizeWebSocketHandler handler() {
        return new CustomizeWebSocketHandler();
    }
}

在Controller包里新建类CustomizeWebSocketHandler ,添加代码


public class CustomizeWebSocketHandler extends TextWebSocketHandler {

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        System.out.println("服务器接收到的数据:"+payload);
        session.sendMessage(new TextMessage("服务器回复的消息: " + "Hello,Are you OK?"));
    }
}
Jar包启动

代码添加完成后,直接点右上角选择DemoApplication启动。

war包启动

在Controller包里新建类WebSocketInitializer,添加代码。一开始启动后提示404,后来搜到了某位大佬的解决方法

public class WebSocketInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() { return null; }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {WebSocketConfig.class};
    }

    @Override
    protected String[] getServletMappings() { return new String[] {"/"}; }
}

启动结果参考“使用@ServerEndpoint注解实现”的启动结果,URL也请参考上面的。这里一摸一样,就不再放了。Jar包启动时请把WebSocketInitializer注释掉(不注释也可以正常使用,个人觉得注释掉吧,以防止产生多余的bug)。

上一篇下一篇

猜你喜欢

热点阅读