Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 弹簧&x2B;WebSocket+;跺脚发送给特定会话的消息(非用户)_Java_Spring_Session_Websocket_Stomp - Fatal编程技术网

Java 弹簧&x2B;WebSocket+;跺脚发送给特定会话的消息(非用户)

Java 弹簧&x2B;WebSocket+;跺脚发送给特定会话的消息(非用户),java,spring,session,websocket,stomp,Java,Spring,Session,Websocket,Stomp,我正在尝试使用我找到的方法在Spring框架上设置基本的MessageBroker 作者声称它工作得很好,但我无法在客户端接收消息,尽管并没有发现明显的错误 目标: //app.js var stompClient = null; var subscription = '/user/queue/response'; //invoked after I hit "connect" button function connect() { //reading from input text for

我正在尝试使用我找到的方法在Spring框架上设置基本的MessageBroker

作者声称它工作得很好,但我无法在客户端接收消息,尽管并没有发现明显的错误

目标:

//app.js

var stompClient = null;
var subscription = '/user/queue/response';

//invoked after I hit "connect" button
function connect() {
//reading from input text form
var agentId = $("#agentId").val();

var socket = new SockJS('localhost:5555/cti');
stompClient = Stomp.over(socket);
stompClient.connect({'Login':agentId}, function (frame) {
    setConnected(true);
    console.log('Connected to subscription');
    stompClient.subscribe(subscription, function (response) {
        console.log(response);
    });
});

}

//invoked after I hit "send" button
function send() {

var cmd_str = $("#cmd").val();
var cmd = {
    'command':cmd_str
};
console.log("sending message...");
stompClient.send("/app/request", {}, JSON.stringify(cmd));
console.log("message sent");
}
我尝试做的基本上是相同的-客户端连接到服务器并请求一些异步操作。操作完成后,客户端应收到一个事件。重要提示:客户机未通过Spring的身份验证,但来自MessageBroker异步后端部分的事件包含他的登录名,因此我假设它足以存储登录SessionId对的并发映射,以便将消息直接发送到特定会话

客户端代码:

//app.js

var stompClient = null;
var subscription = '/user/queue/response';

//invoked after I hit "connect" button
function connect() {
//reading from input text form
var agentId = $("#agentId").val();

var socket = new SockJS('localhost:5555/cti');
stompClient = Stomp.over(socket);
stompClient.connect({'Login':agentId}, function (frame) {
    setConnected(true);
    console.log('Connected to subscription');
    stompClient.subscribe(subscription, function (response) {
        console.log(response);
    });
});

}

//invoked after I hit "send" button
function send() {

var cmd_str = $("#cmd").val();
var cmd = {
    'command':cmd_str
};
console.log("sending message...");
stompClient.send("/app/request", {}, JSON.stringify(cmd));
console.log("message sent");
}
这是我的配置

//message broker configuration

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{


@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    /** queue prefix for SUBSCRIPTION (FROM server to CLIENT)  */
    config.enableSimpleBroker("/topic");
    /** queue prefix for SENDING messages (FROM client TO server) */
    config.setApplicationDestinationPrefixes("/app");
}


@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {

    registry
            .addEndpoint("/cti")
            .setAllowedOrigins("*")
            .withSockJS();
}

}
现在,在基本配置之后,我应该实现一个应用程序事件处理程序,以提供有关客户端连接的会话相关信息

//application listener

@Service
public class STOMPConnectEventListener implements ApplicationListener<SessionConnectEvent> {

@Autowired
//this is basically a concurrent map for storing pairs "sessionId - login"
WebAgentSessionRegistry webAgentSessionRegistry;

@Override
public void onApplicationEvent(SessionConnectEvent event) {
    StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());

    String agentId = sha.getNativeHeader("Login").get(0);
    String sessionId = sha.getSessionId();

    /** add new session to registry */
    webAgentSessionRegistry.addSession(agentId,sessionId);

    //debug: show connected to stdout
    webAgentSessionRegistry.show();

}
}
好的,现在让我们尝试实现消息机制

//STOMPController


@Controller
public class STOMPController {

@Autowired
//our registry we have already set up earlier
WebAgentSessionRegistry webAgentSessionRegistry;
@Autowired
//a helper service which I will post below
MessageSender sender;

@MessageMapping("/request")
public void handleRequestMessage() throws InterruptedException {

    Map<String,String> params = new HashMap(1);
    params.put("test","test");
    //a custom object for event, not really relevant
    EventMessage msg = new EventMessage("TEST",params);

    //send to user2 (just for the sake of it)
    String s_id = webAgentSessionRegistry.getSessionId("user2");
    System.out.println("Sending message to user2. Target session: "+s_id);
    sender.sendEventToClient(msg,s_id);
    System.out.println("Message sent");

}
}
现在,让我们试着测试一下。我运行我的IDE,打开Chrome并创建了两个标签,我将其连接到服务器。User1和User2。结果控制台:

 session_id / agent_id
    -----------------------------
    |kecpp1vt|user1|
    |10g5e10n|user2|
    -----------------------------
Sending message to user2. Target session: 10g5e10n
Message sent
但是,正如我在开始时提到的,user2完全没有得到任何东西,尽管他已连接并订阅了“/user/queue/response”。也没有错误

一个问题是,我到底错过了什么?我读过很多关于这个问题的文章,但都没有用。 说这是可能的,而且应该有效。也许,id-s不是实际的会话id-s? 也许有人知道如何监控消息是否真的被发送了,而不是被内部的弹簧机构丢弃了

解决方案更新: 配置错误的位:

//WebSocketConfig.java:
....
 @Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    /** queue prefix for SUBSCRIPTION (FROM server to CLIENT)  */
    // + parameter "/queue"
    config.enableSimpleBroker("/topic","/queue");
    /** queue prefix for SENDING messages (FROM client TO server) */
    config.setApplicationDestinationPrefixes("/app");
}
....

我花了一天时间调试内部弹簧力学,以找出它到底出了什么问题:

//AbstractBrokerMessageHandler.java: 
....
protected boolean checkDestinationPrefix(String destination) {
    if ((destination == null) || CollectionUtils.isEmpty(this.destinationPrefixes)) {
        return true;
    }
    for (String prefix : this.destinationPrefixes) {
        if (destination.startsWith(prefix)) {
//guess what? this.destinationPrefixes contains only "/topic". Surprise, surprise
            return true;
        }
    }
    return false;
}
....

尽管我不得不承认,我仍然认为文档中提到的用户个人队列没有被明确配置,因为它们“已经存在”。也许我弄错了。

总的来说,它看起来不错,但你能从

config.enableSimpleBroker("/topic");


。。。看看这是否有效?希望这能有所帮助。

我花了一天时间调试内部弹簧力学,以找出到底哪里出了问题。我发布了一个新问题,你能帮我解决吗?
config.enableSimpleBroker("/topic");
config.enableSimpleBroker("/queue");