Spring Boot 的 WebSocket 开发说明文档

来源:互联网 发布:java语言图形界面 编辑:程序博客网 时间:2024/06/05 14:19

Spring Boot 的 WebSocket 开发说明文档

在 Spring Boot 中 使用 WebSocket 实现推送或点对点限时聊天,甚至实现群聊等即时消息功能
WebSocket 是什么原理?为什么可以实现持久连接?

环境要求和关键技术

  • Spring Boot 1.5.7.RELEASE
  • Spring Boot-WebSocket

开发的关键步骤

在 Spring Boot 中 添加 websocket 支持

//gradle 添加方式compile('org.springframework.boot:spring-boot-starter-websocket')
<!-- maven 添加方式 --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-websocket</artifactId></dependency>

在项目中添加 websocket 的 Spring 配置

@Configuration  //注册为 Spring 配置类/* * 开启使用STOMP协议来传输基于代理(message broker)的消息 * 启用后控制器支持@MessgeMapping注解 */@EnableWebSocketMessageBroker//继承 AbstractWebSocketMessageBrokerConfigurer 的配置类实现 WebSocket 配置public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {    //注册STOMP协议节点并映射url    @Override    public void registerStompEndpoints(StompEndpointRegistry registry) {        registry.addEndpoint("/websocket") //注册一个 /consulting 的 websocket 节点                .addInterceptors(myHandshakeInterceptor())  //添加 websocket握手拦截器                .setHandshakeHandler(myDefaultHandshakeHandler())   //添加 websocket握手处理器                .setAllowedOrigins("*") //设置允许可跨域的域名                .withSockJS();  //指定使用SockJS协议    }    /**     * WebSocket 握手拦截器     * 可做一些用户认证拦截处理     * @return     */    private HandshakeInterceptor myHandshakeInterceptor(){        return new HandshakeInterceptor() {            /**             * websocket握手连接             */            @Override            public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {                ServletServerHttpRequest req = (ServletServerHttpRequest) request;                //通过url的query参数获取认证参数                String token = req.getServletRequest().getParameter("token");                //根据token认证用户,不通过返回拒绝握手                Principal user = authenticate(token);                if(user == null){                    return false;                }                //保存认证用户                attributes.put("user", user);                return true;            }            @Override            public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {            }        };    }    //WebSocket 握手处理器    private DefaultHandshakeHandler myDefaultHandshakeHandler(){        return new DefaultHandshakeHandler(){            @Override            protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {                //设置认证通过的用户到当前会话中                return (Principal)attributes.get("user");            }        };    }    //定义一些消息连接规范(下面配置可不设置,最好设置规范一点)    @Override    public void configureMessageBroker(MessageBrokerRegistry registry) {        //设置客户端接收广播消息地址的前缀        registry.enableSimpleBroker("/topic");        //设置客户端接收点对点消息地址的前缀,默认为 /user        registry.setUserDestinationPrefix("/user");        //设置客户端向服务器发送消息的地址前缀        registry.setApplicationDestinationPrefixes("/app");    }    /**     * 根据token认证授权     * @param token     */    private Principal authenticate(String token){        //TODO 实现用户的认证并返回用户信息,如果认证失败返回 null        //用户信息需继承 Principal 并实现 getName() 方法,返回全局唯一值        return null;    }}

WebSocket的 消息处理

@Controller //注册一个Controllerpublic class WsController {    @Autowired    private SimpMessagingTemplate messagingTemplate;    //Spring WebSocket消息发送模板    //发送广播通知    @MessageMapping("/addNotice")   //接收客户端发来的消息,客户端发送消息地址为:/app/addNotice    @SendTo("/topic/notice")        //向客户端发送广播消息(方式一),客户端订阅消息地址为:/topic/notice    public Object notice(Object notice) {        //TODO 业务处理        //向客户端发送广播消息(方式二),客户端订阅消息地址为:/topic/notice        //messagingTemplate.convertAndSend("/topic/notice", notice);        return notice;    }    //发送点对点消息    @MessageMapping("/msg")         //接收客户端发来的消息,客户端发送消息地址为:/app/msg    @SendToUser("/user/msg/result") //向当前发消息客户端(就是自己)发送消息的发送结果,客户端订阅消息地址为:/user/msg/status    public Object sendMsg(Object message){        //TODO 业务处理        //前指定客户端发送消息,第一个参数Principal.name为前面websocket握手认证通过的用户name(全局唯一的),商户端订阅消息地址为:/user/msg/new        messagingTemplate.convertAndSendToUser("Principal.name", "/user/msg/new", message);        return message;    }}