使用websocket实现服务端主动发送消息到客户端

平时我们都是由客户端浏览器主动发送请求到服务端,然后服务器处理请求后返回结果,服务器无法主动向客户端浏览器发送消息。

但是在某些业务场景下我们需要由服务器主动发送消息到客户端浏览器,如当客户用户下订单后,服务器需要主动发消息提醒商户用户有新的订单被创建,请及时处理。在这种需求下我们就需要使用到websocket。

WebSocket是一种在单个TCP连接上进行全双工通信的协议。

下面来看一看websocket的使用示例:

前端代码

创建一个发送消息到服务端的页面sendMessage.html,模拟用户下订单

通过ajax方式发送消息到服务端




    
    Title


    输入需要发送的消息:
    


创建一个接收服务端消息的页面websocketPage.html,模拟商户接收到消息

这里只是将接收到的消息展示在页面上,也可以做成弹出弹窗、消息图标显示角标等其它形式。

注意:websocket协议的url是以ws开头的而不是http!




    
    Title


消息展示区:

后端代码

在springboot项目中引入websocket依赖


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

创建一个websocket服务点导出器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebsocketConfig {
    @Bean
    public ServerEndpointExporter getServerEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

创建一个websocket服务类

import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/websocketurl")//设置websocket连接url,就是前端创建websocket需要提供的url
public class MyWebSocketService {
    private Session session;
    
    //存放所有的websocket连接
    private static CopyOnWriteArraySet myWebSocketServicesSet = new CopyOnWriteArraySet<>();
    
    //建立websocket连接时自动调用
    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        myWebSocketServicesSet.add(this);
        System.out.println("有新的websocket连接进入,当前连接总数为" + myWebSocketServicesSet.size());
    }

    //关闭websocket连接时自动调用
    @OnClose
    public void onClose(){
        myWebSocketServicesSet.remove(this);
        System.out.println("连接断开,当前连接总数为" + myWebSocketServicesSet.size());
    }

    //websocket接收到消息时自动调用
    @OnMessage
    public void onMessage(String message){
        System.out.println("this:" + message);
    }

    //通过websocket发送消息
    public void sendMessage(String message){
        for (MyWebSocketService webSocketService : myWebSocketServicesSet){
            try {
                webSocketService.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                System.err.println(this + "发送消息错误:" + e.getClass() + ":" + e.getMessage());
            }
        }
    }
}

创建一个接收创建订单信息的控制器

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import xyz.syyrjx.websockettest.websocketService.MyWebSocketService;

import javax.annotation.Resource;

@Controller
public class MyController {

    @Resource
    MyWebSocketService webSocketService;

    @RequestMapping("/sendMessage")
    @ResponseBody
    public Object sendMessage(String msg){
        webSocketService.sendMessage(msg);
        return null;
    }
}

规定url和视图的映射关系

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MVCConfiguration implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/websocketPage").setViewName("websocketPage");
        registry.addViewController("/sendMessagePage").setViewName("sendMessage");
    }
}

启动项目进行测试

启动一个edge浏览器,进入websocketPage页面等待消息,服务端接收到websocket连接,打印当前连接数

使用websocket实现服务端主动发送消息到客户端_第1张图片

 启动一个chrome浏览器,进入sendMessagePage页面发送消息

使用websocket实现服务端主动发送消息到客户端_第2张图片

 在sendMessagePage页面输入消息并发送,在websocketPage页面就会接收到消息并展示,此时websocketPage没有主动发送请求给服务器,而是服务器主动发送消息给浏览器

使用websocket实现服务端主动发送消息到客户端_第3张图片

 

你可能感兴趣的:(websocket,java)