springboot整合websocket实现根据条件给不同的用户弹窗

前端代码

<script type="text/javascript">
    var websocket = null;
    var last_health = -1;
    var health_timeout = 20000;
    var health_message = "520";//心跳包
    var isOpenWebsocket = false;//是否已经建立连接
    openWebsocket();
    var timer = setInterval(function () {
        sendHealth()
    }, 5000);

    //打开websocket
    function openWebsocket() {
        if (websocket != null) {
            closeWebSocket();
        }
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            var address = "ws://" + location.host + "/productWebSocket/";
            var loginName = [[${user.loginName}]];
            websocket = new WebSocket(address + loginName);
        } else {
            //不支持websocket
        }


        //连接发生错误的回调方法
        websocket.onerror = function () {
        };


        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            isOpenWebsocket = true;
            var time = new Date();
            last_health = time.getTime();
            sendMessage(health_message);
        }


        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            if (health_message == event.data) {
                //收到心跳包,重置最后一次时间
                var time = new Date();
                last_health = time.getTime();
                return;
            }
            var message = {
                "code": -1,
                "desc": "",
                "data": {"userPhone": "", "address": "", "headNumber": "", "driverName": "", "type": -1}
            };
            message = JSON.parse(event.data);
            if (message.code == 0) {
                if (message.data.type == 1) {
                    //告诉服务器消息已经发送成功
                    message.data.type = 2;
                    // sendMessage(JSON.stringify(message.data));
                    var s = message.data.headNumber+"距离最近的工厂地址"+message.data.address+"已超出50km范围外,请及时处理"
                    openAlarmAlert(s);
                }
            }
        }


        //连接关闭的回调方法
        websocket.onclose = function () {
            isOpenWebsocket = false;
        }


        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            closeWebSocket();
            cancelTask();
        }
    }

    //检测心跳是否正常
    function sendHealth() {
        //判断是否正常
        var time = new Date();
        if (last_health != -1 && (time.getTime() - last_health > health_timeout)) {
            //此时即可以认为连接断开,重新连接
            openWebsocket();
        } else {
            sendMessage(health_message);
        }
    }

    function cancelTask() {
        if (timer != null) {
            clearInterval(timer);
        }
    }

    //关闭连接
    function closeWebSocket() {
        try {
            websocket.close();
        } catch (e) {

        }
    }

    //发送消息
    function sendMessage(string) {
        try {
            if (isOpenWebsocket) {
                websocket.send(string);
            }
        } catch (e) {

        }
    }

    //弹窗方法
    function openAlarmAlert(string) {
        alert(string);
    }
</script>

配置文件

package com.yj.oa.project.websocket.config;

import com.yj.oa.common.utils.shiro.ShiroUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
/**
 * create by niejin on 2019/10/10
 * MyEndpointConfigure配置就是为了解决websocket无法注入的问题,如果没有需要可以不用配置
 */
public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
    //这个有问题 用了websocket生成对象貌似永远只有一个
//    private static volatile BeanFactory context;
//
//    @Override
//    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
//        return context.getBean(clazz);
//    }
//
//    @Override
//    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//        MyEndpointConfigure.context = applicationContext;
//    }
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        // 将用户信息存储到socket的配置里
        sec.getUserProperties().put("user", ShiroUtils.getUser());
        super.modifyHandshake(sec, request, response);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    }
}
package com.yj.oa.project.websocket.config;


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


/**
 * create by niejin on 2019/10/10
 * Websocket配置
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public MyEndpointConfigure newConfigure() {
        return new MyEndpointConfigure();
    }
    /**
     * springboot需要配置方法(不是好像得去掉)
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

最后的具体代码

package com.yj.oa.project.websocket;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yj.oa.project.po.DriverMessage;
import com.yj.oa.project.po.ResponseEntity;
import com.yj.oa.project.po.User;
import com.yj.oa.project.websocket.config.MyEndpointConfigure;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * create by niejin on 2019/10/10
 * Websocket 用来给网页弹窗
 */
@ServerEndpoint(value = "/productWebSocket/{loginName}", configurator = MyEndpointConfigure.class)
@Component
public class ProductWebSocket {

    ObjectMapper mapper = new ObjectMapper();
    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    // concurrent包的线程安全Set,用来存放每个客户端对应的ProductWebSocket对象。
    private static CopyOnWriteArraySet<ProductWebSocket> webSocketSet = new CopyOnWriteArraySet<ProductWebSocket>();

    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    /**
     * 用户信息
     */
    private User user;
    /**
     * 心跳包
     */
    private static final String HEALTH_MESSAGE = "520";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("loginName") String loginName, Session session) {
        addOnlineCount(); // 在线数加1
        this.user = (User) session.getUserProperties().get("user");
        //如果用户名对应
        if (user != null && loginName != null && loginName.equals(user.getLoginName())) {
//            int processID = getProcessID();
//            System.out.println("websocket进程id:"+processID);
            this.session = session;
            ProductWebSocket.webSocketSet.add(ProductWebSocket.this); // 加入set中
        } else {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static final int getProcessID() {
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        System.out.println(runtimeMXBean.getName());
        return Integer.valueOf(runtimeMXBean.getName().split("@")[0])
                .intValue();
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        ProductWebSocket.webSocketSet.remove(ProductWebSocket.this); // 从set中删除
        subOnlineCount(); // 在线数减1
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        //收到心跳包回发
        if (HEALTH_MESSAGE.equals(message)) {
            sendMessage(message);
            return;
        }
//        try {
//            DriverMessage driverMessage = mapper.readValue(message, DriverMessage.class);
//            if (driverMessage == null) {
//                return;
//            }
//            if (driverMessage.getType() == 2) {//2代表是客服端返回已读标志 1代表是服务器发送的
//                //更新数据库消息id状态,或者不保存到数据库 反正计时器几分钟就会扫描 到时候就会触发,不管发不发送成功
//
//            }
//        } catch (Exception e) {
//            //解析异常
//            e.printStackTrace();
//        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    private void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        ProductWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        ProductWebSocket.onlineCount--;
    }

    /**
     * 给特定用户发送消息
     *
     */
    public static void sendMessage(DriverMessage driverMessage) {
        try {
            if (driverMessage == null || driverMessage.getUserPhone() == null) {
                return;
            }
            //发送弹窗消息
            ResponseEntity responseEntity = new ResponseEntity(0, "有新消息", driverMessage);
            for (ProductWebSocket productWebSocket : ProductWebSocket.webSocketSet) {
                if (driverMessage.getUserPhone().equals(productWebSocket.user.getLoginName())) {
                    String message = productWebSocket.mapper.writeValueAsString(responseEntity);
                    productWebSocket.sendMessage(message);
                }
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot是一个用于快速构建基于Spring框架的Java应用程序的开源框架。它简化了Spring应用程序的开发过程,并提供了许多内置的功能和插件,使得开发人员可以更加专注于业务逻辑的实现WebSocket是一种在Web浏览器和Web服务器之间建立持久连接的通信协议,能够实现实时双向通信。 要实现聊天软件的功能,可以使用Spring Boot来快速搭建项目结构和配置。首先,需要在pom.xml文件中添加WebSocket的依赖,例如使用Spring的Spring WebSocket库: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 然后,需要创建一个WebSocket配置类来配置WebSocket的相关信息,例如定义访问WebSocket的端点、配置消息传输方式等。可以继承Spring提供的AbstractWebSocketMessageBrokerConfigurer类,并重写相关方法: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/chat").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } } ``` 在上述配置类中,使用"/chat"作为WebSocket的端点,并启用了基于内存的消息代理(SimpleBroker),其中"/topic"为消息主题的前缀,"/app"为应用程序请求的前缀。 接下来,可以创建一个WebSocket处理器类来处理WebSocket的连接、关闭和消息等事件。可以实现Spring的WebSocketHandler接口,并重写相关方法: ```java @Component public class ChatHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new ArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } } ``` 上述处理器类中,使用一个静态List来保存所有连接的WebSocketSession,以便将消息发送给所有已连接的客户端。 最后,在需要使用WebSocket的控制器或服务中,可以使用@Autowired注解将ChatHandler注入,并使用它来发送消息。 总结来说,通过以上的步骤,我们可以使用Spring Boot整合WebSocket实现聊天软件的功能。当有新的WebSocket连接建立时,我们将其保存在一个静态List中,并在收到消息时将消息发送给所有的连接。通过Spring Boot的简化开发流程和WebSocket的实时双向通信特性,实现了一个简单的聊天软件。 ### 回答2: Spring Boot是一个用于开发Java应用程序的框架,它能够帮助开发人员更快速、更简洁地构建应用程序。WebSocket是HTML5新增的一种协议,它能够在客户端与服务器之间建立持久的双向通信连接,实时地传输数据。 要实现聊天软件的功能,首先需要导入Spring Boot和WebSocket的相关依赖。在pom.xml文件中添加Spring Boot和WebSocket的依赖项。 在Spring Boot的主类中,使用@EnableWebSocket注解启用WebSocket的支持。编写一个WebSocket处理器类,继承自TextWebSocketHandler,并重写其中的方法。在onTextMessage方法中处理接收到的文本消息,在sendMessage方法中处理发送消息。 配置WebSocket的映射路径和处理器,使用@Configuration注解和实现WebSocketConfigurer接口。重写registerWebSocketHandlers方法,设置WebSocket的映射路径和处理器。 在前端界面中,使用JavaScript代码连接WebSocket服务器,并处理接收消息和发送消息的逻辑。通过WebSocket对象的onmessage方法处理接收到的消息,并将消息显示在聊天界面上。通过WebSocket对象的send方法发送消息给服务器。 通过以上步骤,就可以实现Spring Boot和WebSocket整合,从而实现聊天软件的功能。开发人员可以根据具体的需求,进一步完善聊天软件的功能,例如用户名的验证、消息的存储和管理等。 总结起来,使用Spring Boot和WebSocket可以快速、简洁地实现聊天软件。借助Spring Boot的开发效率和WebSocket的实时通信功能,开发人员能够轻松地构建出高效、稳定的聊天软件。 ### 回答3: Spring Boot 是一个基于 Spring 框架的开源服务端开发框架,提供了快速开发和方便部署的特性。WebSocket 是一种基于TCP协议的双向通信协议,通过浏览器与服务器建立持久连接,实现实时通信。 使用 Spring Boot 整合 WebSocket 实现聊天软件的步骤如下: 1. 创建一个 Spring Boot 项目,引入 WebSocket 依赖包。 2. 在配置类上添加 `@EnableWebSocket` 注解以启用 WebSocket 功能。 3. 创建一个 WebSocket 处理器类,继承自 `TextWebSocketHandler`,覆写其中的方法,如 `handleTextMessage()` 和 `afterConnectionEstablished()`。 4. 在 `handleTextMessage()` 方法中,获取客户端发送的消息,处理后将消息发送给所有连接到服务器的客户端。 5. 在 `afterConnectionEstablished()` 方法中,可以处理客户端连接成功后的逻辑。 6. 创建一个控制器类,处理客户端与服务器的交互,如发送消息、接收消息等。 7. 在控制器类中,使用 `@Autowired` 注入 WebSocket 处理器类的对象,并通过该对象发送消息给客户端。 8. 在前端页面中使用 JavaScript 创建 WebSocket 连接,并实现相应的回调函数,实现与服务器的实时通信。 通过以上步骤,可以实现一个简单的聊天软件。用户在页面上发送消息,消息通过 WebSocket 连接发送到服务器,服务器将消息广播给所有客户端,实现实时聊天的功能。 总之,借助 Spring Boot 提供的便利性和 WebSocket 协议的实时通信特性,可以快速实现一个聊天软件。不仅可以在浏览器上实现聊天功能,还可以通过移动端等其他客户端实现跨平台的聊天应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值