java - 如何向具体用户发送websocket消息?

标签 java spring spring-security spring-websocket

我在服务器端有以下代码:

@Autowired
private SimpMessagingTemplate simpMessagingTemplate;

@MessageMapping("/hello")
public void greeting(@Payload HelloMessage message, Principal principal) throws Exception {
    Thread.sleep(1000); // simulated delay
    simpMessagingTemplate.convertAndSendToUser(principal.getName(), "/topic/greetings", new Greeting("Ololo"));        
}

客户端代码:

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}
function showGreeting(message) {
    $("#greetings").append("<tr><td>" + message + "</td></tr>");
}

我的行动:

我运行应用程序,以 user1 身份登录并启动从客户端到服务器的消息发送,我看到方法 greeting 被调用,行 simpMessagingTemplate.convertAndSendToUser( principal.getName(), "/topic/greetings", new Greeting("Ololo")) 执行成功,但我在客户端看不到该消息。

我怎样才能

更多来源:

Spring 安全配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String SECURE_ADMIN_PASSWORD = "rockandroll";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .formLogin()
                .loginPage("/index.html")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/sender.html")
                    .permitAll()
                .and()
                .logout()
                    .logoutSuccessUrl("/index.html")
                    .permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/js/**", "/lib/**", "/images/**", "/css/**", "/index.html", "/","/*.css","/webjars/**", "/*.js").permitAll()
                .antMatchers("/websocket").hasRole("ADMIN")
                .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ADMIN")
                .anyRequest().authenticated();

    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(new AuthenticationProvider() {

            @Override
            public boolean supports(Class<?> authentication) {
                return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
            }

            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;

                List<GrantedAuthority> authorities = SECURE_ADMIN_PASSWORD.equals(token.getCredentials()) ?
                        AuthorityUtils.createAuthorityList("ROLE_ADMIN") : null;

                return new UsernamePasswordAuthenticationToken(token.getName(), token.getCredentials(), authorities);
            }
        });
    }
}

网络套接字配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket").withSockJS();
    }

}

更新

建议和阅读主题之后Sending message to specific user on Spring Websocket我尝试了以下方法:

1.

服务器端:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

客户端:

stompClient.subscribe('/user1/queue/greetings', function(menuItem){
    alert(menuItem);
});

2.

服务器端:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

客户端:

stompClient.subscribe('/user/queue/greetings', function(menuItem){
    alert(menuItem);
});

3.

服务器端:

simpMessagingTemplate.convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo"));

客户端:

stompClient.subscribe('user/user1/queue/greetings', function(menuItem){
    alert(menuItem);
});

无论如何都不起作用

最佳答案

只需在客户端 (app.js) 进行必要的更改:订阅 /user/queue,而不是 /user/user1/queue/greetings/问候:

stompClient.subscribe('/user/queue/greetings', ...

然后在 Web 界面中以 user1 身份登录。它必须是 user1,因为这是服务器的目标用户:

convertAndSendToUser("user1", "/queue/greetings", new Greeting("Ololo")) 

点击发送后,Ololo 消息将显示为客户端警报。

关于java - 如何向具体用户发送websocket消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50044077/

相关文章:

java - 何时使用抽象类作为类型

spring - 关于Grails服务的一些问题

java - @Async 阻止线程继续,直到其他线程完成

迁移到 WAS 8.5 和 java 1.7 后的 javax.naming.ConfigurationException

spring-security - Spring Security 在自定义过滤器上排除 URL

java - 如何在并发 HashMap 中声明一个易变列表?

java - 如何在Windows中设置sbt代理

java - 未找到 UsernamePasswordAuthenticationToken 的 AuthenticationProvider

scala - Play2-Auth vs SecureSocial vs Deadbolt2

java - 多线程中困惑的输出显示死锁?