JHipster一知半解- 3.8websocket

回文集目录:JHipster一知半解

websocket 简要介绍

HTTP 协议是标准的C/S架构的思维,确实符合这个IT世界大部分的场景。服务端作为提供商,就像“坐商”一样,傻傻地等待“客户”的光临,利用自身能力,“响应”浏览器的请求即可。这就是HTTP 协议的缺陷:通信只能由客户端发起。然而有时候,服务器也需要主动向客户端发送信息。比如即使通讯场景,客户端也不知道什么时候有消息传递过来,用HTTP协议,只能改成客户端定时轮询,这在无实际有消息时,造成了极大的资源浪费(客户端空轮询,服务端空响应)。

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向对话(双工)。

JHipster具体配置

JHipster基本就采用spring-boot-starter-websocket的WebSocket的标准配置过程。具体个性化的地方不多。
有个标准的工程(jhipster-sample-app-websocket)可以直接下载运行

pom.xml


    org.springframework.boot
    spring-boot-starter-websocket

WebsocketConfiguration和WebsocketSecurityConfiguration

@EnableWebSocketMessageBroker

通过查看其源码可知,通过DelegatingWebSocketMessageBrokerConfiguration.class开启使用STOMP协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)开始支持@MessageMapping

public class WebsocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {}

配置websocket的适配器类,里面提供了默认的空实现。

@Override
    //把/topic注册为一个简单消息代理
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
    }
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //从配置中读取CORS配置
        String[] allowedOrigins = Optional.ofNullable(jHipsterProperties.getCors().getAllowedOrigins()).map(origins -> origins.toArray(new String[0])).orElse(new String[0]);
        //把/websocket/tracker注册为一个STOMP协议节点,并且制定使用SockJS,值得注意是,这里用了自定义两个Bean
        //1.defaultHandshakeHandler,在“握手”时,解析用户的权限principal(默认为匿名)
        //2.httpSessionHandshakeInterceptor,每次客户端有“请求”,都解析其ip地址,放入"IP_ADDRESS"参数中。
        registry.addEndpoint("/websocket/tracker")
            .setHandshakeHandler(defaultHandshakeHandler())
            .setAllowedOrigins(allowedOrigins)
            .withSockJS()
            .setInterceptors(httpSessionHandshakeInterceptor());
    }

WebsocketSecurityConfiguration直接从spring-security的AbstractSecurityWebSocketMessageBrokerConfigurer继承(这个算是spring=security的一个优势,内部关联性紧密)。

@Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
            .nullDestMatcher().authenticated()
            //定义了tracker消息代码的权限(admin)
            .simpDestMatchers("/topic/tracker").hasAuthority(AuthoritiesConstants.ADMIN)
            // matches any destination that starts with /topic/
            // (i.e. cannot send messages directly to /topic/)
            // (i.e. cannot subscribe to /topic/messages/* to get messages sent to
            // /topic/messages-user)
            // 其他就只需要认证即可
            .simpDestMatchers("/topic/**").authenticated()
            // message types other than MESSAGE and SUBSCRIBE
            .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
            // catch all
            // 默认是拒绝的
            .anyMessage().denyAll();
    }

ActivityDTO和ActivityService

ActivityDTO是用户活动的DTO类。包含sessionid,用户名,ip,当前访问页面,时间。(也就是说,每次页面切换,客户端都会上报这些信息给服务端,服务端接收后进行转发)
ActivityService是真正业务逻辑的地方。值得注意的是onApplicationEvent,监听用户的“离线”事件,使用messagingTemplate发送到给订阅客户端(admin)。--也就说只有登出,不监听新登入。因为登入的信息是由客户端主动发送,经过websoket转发过来的(服务端并没有跟踪,只是转发)。
--程序只显示打开traker页面后,其他客户端的访问情况。

//客户端通过发送给/topic/activity信息(报告自己活动状态),监听/topic/tracker(注意,上面配置/topic/tracker只能由admin才能连接,所以,也只有admin才能接收其他实体的活动信息)
//显然,这是个demo,因为无法获取到当前用户列表。
@SubscribeMapping("给/topic/activity")
@SendTo("/topic/tracker")
    public ActivityDTO sendActivity(@Payload ActivityDTO activityDTO, StompHeaderAccessor stompHeaderAccessor, Principal principal) {
        activityDTO.setUserLogin(principal.getName());
        activityDTO.setSessionId(stompHeaderAccessor.getSessionId());
        activityDTO.setIpAddress(stompHeaderAccessor.getSessionAttributes().get(IP_ADDRESS).toString());
        activityDTO.setTime(Instant.now());
        log.debug("Sending user tracking data {}", activityDTO);
        return activityDTO;
    }

总的来说,JHipster只是用来简单的Websocket接收与广播,甚至连一对一的setUserDestinationPrefix都没有用上。

资源和书籍推荐

Spring WebSocket支持(翻译)
http://blog.geekidentity.com/spring/spring_websocket_translation/

WebSocket 教程
http://www.ruanyifeng.com/blog/2017/05/websocket.html

STOMP协议详解
https://www.cnblogs.com/my_life/articles/7002138.html

认识HTML5的WebSocket
https://www.cnblogs.com/wei2yi/archive/2011/03/23/1992830.html

WebSocket与消息推送
https://www.cnblogs.com/best/archive/2016/09/12/5695570.html

在spring boot中使用webSocket组件
https://www.cnblogs.com/Java-dzz/p/6179317.html

WebSocket 是什么原理?为什么可以实现持久连接?
https://www.zhihu.com/question/20215561

Spring WebSocket+SockJS+Stomp实现一对一、一对多通信
http://blog.csdn.net/haoyuyang/article/details/53364372

你可能感兴趣的:(JHipster一知半解- 3.8websocket)