首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring WebFlux和WebSocket

Spring WebFlux和WebSocket
EN

Stack Overflow用户
提问于 2019-11-19 20:50:31
回答 2查看 7.8K关注 0票数 1

我正在尝试向使用Spring的现有应用程序添加WebSocket功能。它使用:

服务jsp页面的2.2.1.RELEASE

  • Tomcat container

  • Configured

当我试图通过JavaScript连接到它时(从jsp页面中),我收到的错误是“WebSocket握手期间失败:错误:意外响应代码: 404”。

我注意到,如果我创建一个控制器类,映射url '/ws/event-emitter‘(映射在我的websocket配置中),接受GET请求,当它试图打开websocket连接时,它会接收来自Javascript调用的请求,这使我更加困惑。

我遗漏了什么?

在阅读了Internet上的一些教程之后,我将配置设置如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>

">https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot spring-启动器-父程序2.2.1.starter br.com.samsung监视器0.0.1-快照监视器健康检查监视器

代码语言:javascript
复制
<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!-- 
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
     -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.projectreactor</groupId>
        <artifactId>reactor-spring</artifactId>
        <version>1.0.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</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>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- MongoDB -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-releasetrain</artifactId>
        <version>Lovelace-SR9</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencies>

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

代码语言:javascript
复制
@Configuration

公共类ReactiveWebSocketConfiguration {

代码语言:javascript
复制
@Autowired
private WebSocketHandler webSocketHandler;

@Bean
public HandlerMapping webSocketHandlerMapping() {
    Map<String, WebSocketHandler> map = new HashMap<>();
    map.put("/ws/event-emitter", webSocketHandler);

    SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
    handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
    handlerMapping.setUrlMap(map);
    return handlerMapping;
}

@Bean
public WebSocketHandlerAdapter handlerAdapter(WebSocketService webSocketService) {
    return new WebSocketHandlerAdapter(webSocketService);
}

@Bean
public WebSocketService webSocketService() {
    TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
    strategy.setMaxSessionIdleTimeout(0L);
    return new HandshakeWebSocketService(strategy);
}

}

@Component公共类ReactiveWebSocketHandler实现WebSocketHandler {

代码语言:javascript
复制
private static final ObjectMapper json = new ObjectMapper();

private Flux<String> eventFlux = Flux.generate(sink -> {
    Event event = new Event(randomUUID().toString(), now().toString());
    try {
        sink.next(json.writeValueAsString(event));
    } catch (JsonProcessingException e) {
        sink.error(e);
    }
});

private Flux<String> intervalFlux = Flux.interval(Duration.ofMillis(1000L))
  .zipWith(eventFlux, (time, event) -> event);

@Override
public Mono<Void> handle(WebSocketSession webSocketSession) {
    return webSocketSession.send(intervalFlux
      .map(webSocketSession::textMessage))
      .and(webSocketSession.receive()
        .map(WebSocketMessage::getPayloadAsText).log());
}

}

代码语言:javascript
复制
		<script>
		    var clientWebSocket = new WebSocket("ws://localhost:6600/ws/event-emitter");
		    clientWebSocket.onopen = function() {
		        console.log("clientWebSocket.onopen", clientWebSocket);
		        console.log("clientWebSocket.readyState", "websocketstatus");
		        clientWebSocket.send("event-me-from-browser");
		    }
		    clientWebSocket.onclose = function(error) {
		        console.log("clientWebSocket.onclose", clientWebSocket, error);
		        events("Closing connection");
		    }
		    clientWebSocket.onerror = function(error) {
		        console.log("clientWebSocket.onerror", clientWebSocket, error);
		        events("An error occured");
		    }
		    clientWebSocket.onmessage = function(error) {
		        console.log("clientWebSocket.onmessage", clientWebSocket, error);
		        events(error.data);
		    }
		    function events(responseEvent) {
		        document.querySelector(".events").innerHTML += responseEvent + "<br>";
		    }
		</script>

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-25 12:44:40

我可以让它工作,消除spring-启动程序-web和tomcat-嵌入-jasper依赖。我想春-启动-启动-网络可能与春-启动-启动-网络流量相冲突。

此外,我还将ReactiveWebSocketConfiguration类更改为使用ReactorNettyRequestUpgradeStrategy而不是TomcatRequestUpgradeStrategy设置WebSocketService bean。

代码语言:javascript
复制
@Bean
public WebSocketService webSocketService() {
    return new HandshakeWebSocketService(new ReactorNettyRequestUpgradeStrategy());
}

在这些更改之后,我的jsp页面停止工作,因为我的web容器从Tomcat更改为。我不得不使用Thymeleaf (添加了spring-boot-starter依赖项,配置它的基本结构并将我的页面转换为.html文件),而不是传统的jsp。

由于时间限制,我选择了从传统的jsp改为Thymeleaf,因为我的应用程序只有很少的简单页面。

我用所有这些配置创建了一个非常简单的项目,包括一个通过javascript连接到websocket的虚拟页面。

https://github.com/atilio-araujo/spring-webflux-websocket

票数 4
EN

Stack Overflow用户

发布于 2020-12-06 01:59:21

Spring WebFlux WebSocket:

只是为那些试图用websocket实现webflux的人添加这个答案。

  1. OP由于某种原因同时具有webwebflux依赖关系。但是,您只需要only.
  2. Implement依赖WebFlux,一个WebSocketHandler

代码语言:javascript
复制
    @Service
    public class WebFluxWebSocketHandler implements WebSocketHandler {
    
        @Override
        public Mono<Void> handle(WebSocketSession webSocketSession) {
            Flux<WebSocketMessage> stringFlux = webSocketSession.receive()
                    .map(WebSocketMessage::getPayloadAsText)
                    .map(String::toUpperCase)
                    .map(webSocketSession::textMessage);
            return webSocketSession.send(stringFlux);
        }
    
    }

  1. 添加了路径处理程序映射.这里,处理程序是websockethandler.

的一个实例

代码语言:javascript
复制
     @Bean
       public HandlerMapping handlerMapping(){
           Map<String, WebFluxWebSocketHandler> handlerMap = Map.of(
                   "/test", handler
           );
           return new SimpleUrlHandlerMapping(handlerMap, 1);
       }

就这样!现在客户端应该能够连接到ws://localhost:8080/test

查看这里获取更多信息- https://www.vinsguru.com/spring-webflux-websocket/

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58942599

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档