spring 是不是同时支持 Rest 和 Websocket 控制器/连接?

Posted

技术标签:

【中文标题】spring 是不是同时支持 Rest 和 Websocket 控制器/连接?【英文标题】:does spring support Rest and Websocket controllers/connection at the same time?spring 是否同时支持 Rest 和 Websocket 控制器/连接? 【发布时间】:2019-06-01 21:32:55 【问题描述】:

我想在我的应用程序中通过 rest api(和其他一些东西)和 websockets 的主要功能对用户进行授权。 我面临下一个问题。想象一下,我有一个带有下一个控制器的超级简单的 spring 应用程序。

@RestController
public class FieldController

    @ResponseBody
    @RequestMapping(value = "/getString", method = RequestMethod.GET)
    public String getString()
    
        return "[\"id\":11, \"name\":\"qwer\"]";
    

效果很好,我在浏览器中看到此 URL 的响应。 但是当我尝试将 websocket 配置类添加到应用程序时

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer

    public void registerStompEndpoints(StompEndpointRegistry registry)
    
        registry.addEndpoint("/socket").withSockJS();
    

    public void configureMessageBroker(MessageBrokerRegistry registry)
    
        registry.setApplicationDestinationPrefixes("/app")
        .enableSimpleBroker("/chat");
    

浏览器停止查看此网址。在日志中:

org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /app/getString

我不知道为什么,谷歌也不知道。也许是因为 spring 将其视为 websocket 控制器。问题是有人见过这样的工作行为吗?至少我想确认这不应该工作或确认我做错了什么。谢谢

【问题讨论】:

可以,正常支持这个;您使用不同的注释来指示 WebSocket 控制器。这很可能是一个相当普通的映射问题。我认为你有这个倒退,因为你告诉 Spring 它应该使用/app for WebSocket,而不是传统的 MVC 控制器。将您的org.springframework.web 登录到 DEBUG,您应该会在启动时获得所有映射的完整列表。 @chrylis 为什么注释不同? RestController其实就是Controller+ResponseBody。对于 websocket,我们使用 Controller。 对于WebSocket,一般使用@MessageMapping 【参考方案1】:

答案有点晚了,但请参阅上面的示例采用的以下配置和控制器:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer 

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) 
        stompEndpointRegistry.addEndpoint("/socket")
                             .withSockJS();
    

    @Override
    public void configureMessageBroker(MessageBrokerRegistry messageBrokerRegistry) 
        messageBrokerRegistry.enableSimpleBroker("/chat");
        messageBrokerRegistry.setApplicationDestinationPrefixes("/app");
    

@Slf4j
@RestController
public class FooBarController 

    @MessageMapping("/foobar-ws")
    @PostMapping("/foobar-rest")
    public String foobar(@RequestBody String in) 
        LOG.debug("Received ", in);
        return "Answer to " + in;
    

使用 HTTP/REST 进行测试

POSTing 到 /foobar-rest 按预期工作:

curl -X POST "http://localhost:8080/foobar-rest" -d "Test1"

这只是记录Received Test1 并返回Answer to Test1 作为HTTP 响应。

使用 WS/STOMP 进行测试

注册到http://localhost:8080/socket,然后将Test2 发送到/app/foobar-ws 会生成日志Received Test2

扩展示例

首先在方法中添加@SendTo注解:

@MessageMapping("/foobar-ws")
@PostMapping("/foobar-rest")
@SendTo("/chat/loremipsum")
public String foobar(@RequestBody String in) 
    LOG.debug("Received ", in);
    return "Answer to " + in;

然后,同上,注册http://localhost:8080/socket,订阅/chat/loremipsum。然后,当您将 Test3 发送到 /app/foobar-ws 时,输入将被记录 (Received Test3) 并返回到 WebSocket 客户端 (Answer to Test3)。顺便说一下,HTTP 仍然可以正常工作。

【讨论】:

以上是关于spring 是不是同时支持 Rest 和 Websocket 控制器/连接?的主要内容,如果未能解决你的问题,请参考以下文章

不支持 Spring Rest POST Json RequestBody 内容类型

Spring 4 vs Jersey 用于 REST Web 服务

仅使用 Spring Security 自定义令牌无状态保护 REST 控制器,同时保持常规状态完整 Web 登录正常工作

Spring Data REST 是不是支持响应式 crud 存储库?

在同一个 Spring Boot 应用程序中的 Rest 服务和 Web 服务

使用Swagger生成Spring Boot REST客户端(支持Feign)(待实践)