Spring Cloud微服务使用webSocket的方法

webSocket

webSocket长连接是一种在单个tcp连接上进行全双工通信的协议,允许双向数据推送。一般微服务提供的restful API只是对前端请求做出相应。使用webSocket可以实现后端主动向前端推送消息。

网关配置

spring cloud 的网关组件有zuul和getway

getway

base:
  config:
    nacos:
      nacoshost: localhost
      port: 8848

spring:
  application:
    name: gateway
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      discovery:
        server-addr: ${base.config.nacos.nacoshost}:${base.config.nacos.port}
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        #  websocket
        - id: CLOUD-WEBSOCKET
          uri: lb:ws://cloud-websocket
          predicates:
            - Path=/cloud-websocket/**
server:
  port: 8888

配置网关的时候注意添加ws协议。

zuul

zuul只能管理http请求,不推荐使用zuul管理websocket连接,推荐直连。

服务端

添加maven依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

添加webSocket 配置

@Configuration
@EnableWebSocket
public class WebsocketConfiguration implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // webSocket通道
        // 指定处理器和路径
        registry.addHandler(new WebSocketHandler(), "/websocket")
                // 指定自定义拦截器
                .addInterceptors(new WebSocketInterceptor())
                // 允许跨域
                .setAllowedOrigins("*");
        // sockJs通道
        registry.addHandler(new WebSocketHandler(), "/sock-js")
                .addInterceptors(new WebSocketInterceptor())
                .setAllowedOrigins("*")
                // 开启sockJs支持
                .withSockJS();
    }
}

添加处理器

package com.auexpress.cloud.handler;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description
 * @ClassName WebSocketHandler
 * @Author HYSong
 * @date 2020.04.14 10:08
 */
public class WebSocketHandler extends AbstractWebSocketHandler {
    /**
     *  存储sessionId和webSocketSession
     *  需要注意的是,webSocketSession没有提供无参构造,不能进行序列化,也就不能通过redis存储
     *  在分布式系统中,要想别的办法实现webSocketSession共享
     */
    private static Map<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();
    private static Map<String, String> userMap = new ConcurrentHashMap<>();

    /**
     * webSocket连接创建后调用
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        // 获取参数
        String user = String.valueOf(session.getAttributes().get("user"));
        userMap.put(user, session.getId());
        sessionMap.put(session.getId(), session);
    }

    /**
     * 接收到消息会调用
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        JSONObject jsonObject = JSONObject.parseObject(message.getPayload().toString());
        String content = jsonObject.getString("content");
        String targetAdminId = jsonObject.getString("targetId");
        if("0".equals(targetAdminId)){
            //  推送给所有人
            userMap.forEach((key,value)->{
                try {
                    this.sendMessage(key,content);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }else{
            sendMessage("1", content);
        }
    }

    /**
     * 连接出错会调用
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        sessionMap.remove(session.getId());
    }

    /**
     * 连接关闭会调用
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        sessionMap.remove(session.getId());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 后端发送消息
     */
    public void sendMessage(String user, String message) throws IOException {
        String sessionId = userMap.get(user);
        if (StringUtils.isEmpty(sessionId)) {
            return;
        }
        WebSocketSession session = sessionMap.get(sessionId);
        if (session == null) {
            return;
        }
        session.sendMessage(new TextMessage(message));
    }
}

添加拦截器

package com.auexpress.cloud.interceptor;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

/**
 * @Description
 * @ClassName WebSocketInterceptor
 * @Author HYSong
 * @date 2020.04.14 10:09
 */
public class WebSocketInterceptor implements HandshakeInterceptor {
    /**
     * handler处理前调用,attributes属性最终在WebSocketSession里,
     * 可能通过webSocketSession.getAttributes().get(key值)获得
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
            // 获取请求路径携带的参数
            String user = serverHttpRequest.getServletRequest().getParameter("user");
            attributes.put("user", user);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }
}

到此这篇关于Spring Cloud微服务使用webSocket的方法的文章就介绍到这了,更多相关Spring Cloud使用webSocket内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot websocket简单入门示例

    之前做的需求都是客户端请求服务器响应,新需求是服务器主动推送信息到客户端.百度之后有流.长轮询.websoket等方式进行.但是目前更加推崇且合理的显然是websocket. 从springboot官网翻译了一些资料,再加上百度简单实现了springboot使用websocekt与客户端的双工通信. 1.首先搭建一个简单的springboot环境 <!-- Inherit defaults from Spring Boot --> <parent> <groupId>o

  • springboot websocket集群(stomp协议)连接时候传递参数

    最近在公司项目中接到个需求.就是后台跟前端浏览器要保持长连接,后台主动往前台推数据. 网上查了下,websocket stomp协议处理这个很简单.尤其是跟springboot 集成. 但是由于开始是单机玩的,很顺利. 但是后面部署到生产搞集群的话,就会出问题了. 假如集群两个节点,浏览器A与节点A建立连接,A节点发的消息浏览器A节点肯定能收到.但是B节点由于没有跟浏览器A建立连接.B节点发的消息浏览器就收不到了. 网上也查了好多,但是没有一个说的很清楚的,也很多都是理论层面的. 还有很多思路都

  • SpringBoot使用WebSocket的方法实例详解

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输. 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道.两者之间就直接可以数据互相传送. java怎么写 配置Be

  • SpringBoot集成WebSocket实现前后端消息互传的方法

    什么是WebSocket? WebSocket 协议是基于 TCP 的一种新的网络协议.它实现了浏览器与服务器全双工 (full-duplex) 通信-允许服务器主动发送信息给客户端. 为什么需要WebSocket? 大家都知道以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较大.另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一直不返

  • 详解Spring Cloud微服务架构下的WebSocket解决方案

    WebSocket在现代浏览器中的应用已经算是比较普遍了,在某些业务场景下,要求必须能够在服务器端推送消息至客户端.在没有WebSocket的年代,我们使用过dwr,在那个时候dwr真实一个非常棒的方案.但是在WebSocket兴起之后,我们更愿意使用标准实现来解决问题. 首先交代一下,本篇文章不讲解WebSocket的配置,主要讲的是针对在微服务架构集群模式下解决方案的选择. 微服务架构大家应该都不陌生了,在微服务架构下,服务是分布式的,而且为了保证业务的可用性,每个服务都是以集群的形式存在.

  • Spring Cloud微服务使用webSocket的方法

    webSocket webSocket长连接是一种在单个tcp连接上进行全双工通信的协议,允许双向数据推送.一般微服务提供的restful API只是对前端请求做出相应.使用webSocket可以实现后端主动向前端推送消息. 网关配置 spring cloud 的网关组件有zuul和getway getway base: config: nacos: nacoshost: localhost port: 8848 spring: application: name: gateway main:

  • Servlet+MyBatis项目转Spring Cloud微服务,多数据源配置修改建议

    一.项目需求 在开发过程中,由于技术的不断迭代,为了提高开发效率,需要对原有项目的架构做出相应的调整. 二.存在的问题 为了不影响项目进度,架构调整初期只是把项目做了简单的maven管理,引入springboot并未做spring cloud微服务处理.但随着项目的进一步开发,急需拆分现有业务,做微服务处理.因此架构上的短板日益突出.spring cloud config 无法完全应用,每次项目部署需要修改大量配置文件.严重影响开发效率,因此便萌生了对项目架构再次调整的决心. 三.调整建议 为了

  • spring Cloud微服务跨域实现步骤

    这篇文章主要介绍了spring Cloud微服务跨域实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 第一步:在gateway网关的配置文件中加上下面这些: ly: cors: allowedOrigins: - http://manage.leyou.com - http://xxx.xxx.com # 允许哪些网址就继续加,不要写 *,否则cookie就无法使用了 allowedCredentials: true # 代表携带cook

  • 使用kotlin编写spring cloud微服务的过程

    创建工程 使用idea的spring initializr创建一个项目,语言选择kotlin, 类型为gradle. 根据需要选择依赖 配置文件 yml或者properties文件和java是完全一样的,这里不详细说明 修改build.gradle.kts中的参数: plugins { //spring boot版本 id("org.springframework.boot") version "2.3.3.RELEASE" //自动依赖包版本管理 id("

  • Spring Cloud微服务架构的构建:分布式配置中心(加密解密功能)

    前言 要会用,首先要了解.图懒得画,借鉴网上大牛的图吧,springcloud组建架构如图: 微服务架构的应用场景: 1.系统拆分,多个子系统 2.每个子系统可部署多个应用,应用之间负载均衡实现 3.需要一个服务注册中心,所有的服务都在注册中心注册,负载均衡也是通过在注册中心注册的服务来使用一定策略来实现. 4.所有的客户端都通过同一个网关地址访问后台的服务,通过路由配置,网关来判断一个URL请求由哪个服务处理.请求转发到服务上的时候也使用负载均衡. 5.服务之间有时候也需要相互访问.例如有一个

  • 详解Spring Cloud Zuul 服务网关

    有了Eureka服务注册发现.Hystrix断路器.Ribbon服务调用负载均衡,以及spring cloud config 集群配置中心,似乎一个微服务框架已五脏俱全,last but not least,一个服务网关却不可或缺. Spring Cloud Zuul路由是微服务架构的不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务.Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器. Zuul介绍 在整个Spring Cloud微服务框架里,Zuul扮演着"智能网

  • Spring Cloud Gateway 服务网关快速实现解析

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 Spring 5+,基于 Spring Boot 2.x 响应式的.非阻塞式的 API.同时,它支持 websockets,和 Spring 框架紧密集成,用来代替服务网关Zuul,开发体验相对来说十分不错. Spring Cloud Gateway 是 Spring Cloud 微服务平台的一个子

  • 教你在Spring Boot微服务中集成gRPC通讯的方法

    一.首先声明gRPC接口 这里引入的是最新的gRpc-core 1.37版本, 采用的grcp-spring-boot-starter封装的版本进行实现,github地址: https://github.com/yidongnan/grpc-spring-boot-starter 要实现gRpc通讯, 先定义接口以及入参出参信息 syntax = "proto3"; option java_multiple_files = true; option java_package = &qu

  • Spring Cloud 网关服务 zuul 动态路由的实现方法

    zuul动态路由 网关服务是流量的唯一入口.不能随便停服务.所以动态路由就显得尤为必要. 数据库动态路由基于事件刷新机制热修改zuul的路由属性. DiscoveryClientRouteLocator 可以看到DiscoveryClientRouteLocator 是默认的刷新的核心处理类. //重新加载路由信息方法 protected方法.需要子方法重新方法. protected LinkedHashMap<String, ZuulRoute> locateRoutes() //触发刷新的

随机推荐