websocket实现服务器向前端推送消息

SpringBoot项目中使用WebSocket

什么是Websocket:WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

实现原理:在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” 。在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

优点:在以前的消息推送机制中,用的都是 Ajax 轮询(polling),在特定的时间间隔由浏览器自动发出请求,将服务器的消息主动的拉回来,这种方式是非常消耗资源的,因为它本质还是http请求,而且显得非常笨拙。而WebSocket 在浏览器和服务器完成一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据。

1.引入依赖

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

2.开启WebSocket支持

/**
 * @Author hf
 * @create 2022/1/17 14:08
 *
 * 开启WebSocket支持
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    //服务器支持跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST","OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("Access-Control-Allow-Headers",
                        "Access-Control-Allow-Methods",
                        "Access-Control-Allow-Origin",
                        "Access-Control-Max-Age",
                        "X-Frame-Options")
                .allowCredentials(false)
                .maxAge(36000);
    }

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller,直接@ServerEndpoint("/websocket"),@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage等方法

开发完成后遇到一个问题,前端调用websocket接口,连接成功后、马上报错自动关闭了连接。

后台报错:后台 显示已连接,然后就报错java.io.IOException: 你的主机中的软件中止了一个已建立的连接。

找了很多解决办法都不行,发现是被项目配置的防止XSS攻击过滤器拦截了,添加第6-9行代码就可以正常连接成功了

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;

    if("websocket".equals(req.getHeader("upgrade"))){ //放开拦截
        chain.doFilter(request,response);
        return;
    }
    //对请求进行拦截,防xss处理
    chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
}

前端代码:

/** 初始化 WebSocket */
initWebSocket() {
  if (this.ws === null) {
    const domain = buyerUrl.replace('https://', 'wss://').replace('http://', 'ws://')
    const url = `${domain}/buyer/webSocket/${this.form.memberId}`

    this.ws = new WebSocket(url)
    this.ws.onmessage = this.websocketonmessage;
    this.ws.onopen = this.websocketonopen;
    this.ws.onerror = this.websocketonerror;
    this.ws.onclose = this.websocketclose;

    console.log('this.ws: ', this.ws)
  }
},
websocketonopen(){ //连接建立之后执行send方法发送数据
  console.log('--1')
},
websocketonerror(){//连接建立失败重连
  this.initWebSocket();
  console.log('--2')
},
websocketonmessage(e){ //数据接收
//1.认证成功 0.认证失败
  console.log('--3')
  const redata = JSON.parse(e.data);
},
websocketsend(Data){//数据发送
  this.ws.send(Data);
  console.log('--4')
},
websocketclose(e){  //关闭
  console.log('断开连接',e);
  console.log('--5')
},

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值