我使用Spring的STOMP而不是WebSocket实现,使用功能齐全的ActiveMQ代理.当用户SUBSCRIBE访问某个主题时,在成功订阅之前,他们必须通过一些权限逻辑.我正在使用ChannelInterceptor来应用权限逻辑,如下所示:
WebSocketConfig.java:
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost("relayhost.mydomain.com")
.setRelayPort(61613);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new MySubscriptionInterceptor());
}
}
Run Code Online (Sandbox Code Playgroud)
WebSocketSecurityConfig.java:
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpSubscribeDestMatchers("/stomp/**").authenticated()
.simpSubscribeDestMatchers("/user/queue/errors").authenticated()
.anyMessage().denyAll();
}
}
Run Code Online (Sandbox Code Playgroud)
MySubscriptionInterceptor.java:
public class MySubscriptionInterceptor extends ChannelInterceptorAdapter {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
Principal …Run Code Online (Sandbox Code Playgroud) java activemq-classic stomp spring-messaging spring-websocket
我正在玩新的(从4.2版开始)java STOMP客户端支持.我的出发点是入门指南(使用WebSocket构建交互式Web应用程序).
示例中提供了以下端点:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
Run Code Online (Sandbox Code Playgroud)
我可以使用浏览器客户端成功连接.尝试使用java stomp客户端使用以下命令连接到此端点时:
WebSocketClient transport = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(transport);
stompClient.setMessageConverter(new StringMessageConverter());
String url = "ws://127.0.0.1:8080/hello";
ListenableFuture<StompSession> future = stompClient.connect(url,myHandler);
Run Code Online (Sandbox Code Playgroud)
我遇到以下异常:
08:56:30.629 [SimpleAsyncTaskExecutor-1] DEBUG o.s.m.simp.stomp.DefaultStompSession - Failed to connect session id=4e6737da-8f68-691d-375f-9e46f48bc149
javax.websocket.DeploymentException: The HTTP response from the server [HTTP/1.1 200 OK
] did not permit the HTTP upgrade to WebSocket
at org.apache.tomcat.websocket.WsWebSocketContainer.parseStatus(WsWebSocketContainer.java:637) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
at org.apache.tomcat.websocket.WsWebSocketContainer.processResponse(WsWebSocketContainer.java:621) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:309) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:152) ~[spring-websocket-4.2.0.BUILD-SNAPSHOT.jar:4.2.0.BUILD-SNAPSHOT]
at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:149) ~[spring-websocket-4.2.0.BUILD-SNAPSHOT.jar:4.2.0.BUILD-SNAPSHOT] … 我试图测试websocket而不使用socketjs库,我也不想添加任何stomp连接.
我正在关注stackoverflow问题的例子: 带有Sockjs和Spring 4的WebSocket,但是没有Stomp
所以没有stomp服务器,我已经成功通过socketjs库与url连接:ws:// localhost:8080/greeting/741/0tb5jpyi/websocket
现在我想删除socketjs库以允许原始websocket连接(可能是android,ios等设备......)
当我删除参数:.withSockJS()时,我无法通过websocket连接.
我尝试了以下网址,但它们不起作用:
ws://localhost:8080/greeting/394/0d7xi9e1/websocket not worked
ws://localhost:8080/greeting/websocket not worked
ws://localhost:8080/greeting/ not worked
Run Code Online (Sandbox Code Playgroud)
我应该用哪个URL连接?
我想要什么:
GET / HTTP/1.1(不Connection: upgrade) - 此请求应由RequestMappingHandlerMappingConnection: upgradeGET请求 - 此请求应由...处理ServletWebSocketHandlerRegistry我的Java配置:
@Configuration
@EnableWebSocket
public class WebsocketConfiguration extends WebMvcConfigurationSupport
implements WebSocketConfigurer {
@Bean
WebsocketComponent wsHandler() {
return new WebsocketComponent();
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(wsHandler(), "/").setAllowedOrigins("*");
}
}
Run Code Online (Sandbox Code Playgroud)
我的webmvc控制器:
@Controller
public class Status {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String status() {
return "OK";
}
}
Run Code Online (Sandbox Code Playgroud)
问题是 - 当MVC控制器优先时,它总是以HTTP 200响应,从未到达WebSocket处理程序.当WebSocket处理程序具有优先权时 - 它适用于WebSocket客户端,但是当我尝试使用http客户端(浏览器)时,它会响应,Can "Upgrade" only to "WebSocket".
是否有可能以某种方式替换此错误页面并回退到我的MVC映射?任何其他配置,以使我先描述的?
我已经实现的WebSockets与春季启动应用程序,并试图测试使用Chrome扩展"的WS连接时有以下错误信息智能的WebSocket客户端 ".但是,在本地运行Spring Boot应用程序时没有问题.
WebSocket connection to 'ws://192.168.X.XYZ:8080/test' failed:
Error during WebSocket handshake: Unexpected response code: 403
Run Code Online (Sandbox Code Playgroud)
我看到的唯一区别是在Request标头中:
在它工作的那个 - 起源:http://192.168.X.XYZ:8080
在一个它不工作 - 起源:铬扩展:// omalebghpgejjiaoknljcfmglgbpocdp
我在WebSocketConfig类中所做的如下:
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/test").setAllowedOrigins("http://192.168.X.XYZ:8080");
}
Run Code Online (Sandbox Code Playgroud)
仍然无法正常工作.
您能告诉我该错误的原因是什么以及如何解决?
先感谢您.
我需要实现RPC over STOMP,其中客户端在浏览器中使用javascript运行,服务器端使用Spring消息传递功能实现.
虽然使用@MessageMapping对于正常消息传递很好,但我发现使用@SendToUser非常限制实现RPC,因为当客户端发出多个同时请求时,客户端很难理解哪个回复与场景中的哪个请求相关联.
当然只有一个请求就没有问题,并且客户端等待它的回复,但是当客户端必须跟踪多个"开放"rpc调用时会出现问题.
通过将ID与每个请求相关联,我设法使系统变得更好,即:客户端将id与消息一起发送,并且服务器回复包含此id的特殊消息包装器,因此客户端能够将异步回复与请求相关联.
这很好但有几个限制:
我必须开发需要理解这种结构的代码,并且这使得uitlity无法使用简单的带注释的方法
当服务器端代码生成异常时,调用Spring @MessageExceptionHandler并将正确的异常返回给客户端,但请求ID丢失,因为处理程序没有(简单)方法来访问它.
我知道使用rabbitmq我们可以为每个需要与特殊回复(rpc响应)关联的请求添加"reply-to"标头,这是通过创建用户自动订阅的特殊临时队列来实现的,但是我如何在Spring中使用这个方案呢?此外,这将使我成为一个特定的经纪人.
我怎样才能在Spring中优雅地实现正确的RPC调用,正确处理服务器端异常?
我发现这是一个普遍的问题,我认为Spring可以大大有益于本地实现它.
我已经使用Spring MVC实现了Web Socket,它对我来说很好用,即从一个浏览器工作到另一个浏览器,这个浏览器使用这个代码打开.
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public HelloMessage greeting(HelloMessage message) throws Exception {
Thread.sleep(3000); // simulated delay
return message;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我从正常的api控制器调用@SendTo("/ topic/greetings").我尝试使用它但它对我不起作用
@RequestMapping(value = "/sendMessage")
@SendTo("/topic/greetings")
public HelloMessage sendMessage() throws Exception {
return new HelloMessage((int) Math.random(), "This is Send From Server");
}
Run Code Online (Sandbox Code Playgroud)
对此有何看法?
谢谢
我正在尝试使用弹簧启动后端为移动应用程序(离子3)实现1-1聊天.似乎遇到了一些配置问题.
无法发送消息可能是因为未创建目标通道
后端:
ChatController:
@RestController
public class ChatController {
@Autowired
private PrivateChatService privateChatService;
private final static Logger logger = LogManager.getLogger(ChatController.class.getName());
@RequestMapping(value = "/chat/messages/{item_id}/chat_with/{buyer_login}", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<String> getExistingChatMessages(@PathVariable("item_id") String itemId, @PathVariable("buyer_login") String buyerLogin) {
List<ChatMessage> messages = privateChatService.getExistingChatMessages(itemId, buyerLogin);
logger.info("Here get messages");
return JSONResponseHelper.createResponse(messages, HttpStatus.OK);
}
@MessageMapping("/chat/{item_id}/send")
@SendTo("/topic/chat/{item_id}/chat_with/{buyer_login}")
public ChatMessage send(@Payload ChatMessage message,
@DestinationVariable("item_id") String item_id) throws Exception {
// logger.info(principal.getName());
logger.info(message.toString());
logger.info(item_id);
privateChatService.submitMessage(message);
return message;
}
}
Run Code Online (Sandbox Code Playgroud)
WebSocketConfig:
@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
public class …Run Code Online (Sandbox Code Playgroud) 有没有澄清,如果我使用"简单代理",Spring Websocket + SockJS的/ topic,/ queue等之间有什么区别?例如,这里向Spring Websocket上的特定用户发送消息:当您的客户端订阅以/ user /开头的频道时,例如:/ user/queue/reply,您的服务器实例将订阅名为queue/reply-user的队列[会话ID]
我想以一种明确的方式理解这种转换背后的逻辑.
我有一个OpenShift Wildfly服务器.我正在用Spring MVC框架构建一个网站.我的一个网页也使用WebSocket连接.在服务器端,我使用了@ServerEndpoint注释和javax.websocket.*库来创建我的websocket:
package com.myapp.spring.web.controller;
import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.web.socket.server.standard.SpringConfigurator;
@ServerEndpoint(value="/serverendpoint", configurator = SpringConfigurator.class)
public class serverendpoint {
@OnOpen
public void handleOpen () {
System.out.println("JAVA: Client is now connected...");
}
@OnMessage
public String handleMessage (Session session, String message) throws IOException {
if (message.equals("ping")) {
// return "pong"
session.getBasicRemote().sendText("pong");
}
else if (message.equals("close")) {
handleClose();
return null;
}
System.out.println("JAVA: Received from client: "+ message); …Run Code Online (Sandbox Code Playgroud) spring-mvc spring-security websocket spring-boot spring-websocket
spring-websocket ×10
java ×7
spring ×7
stomp ×4
websocket ×4
spring-mvc ×3
spring-boot ×2
cors ×1
ionic3 ×1
rpc ×1
sockjs ×1
spring-4 ×1