WebSocket消息推送

文章介绍了使用WebSocket进行实时通信的流程,包括在SpringBoot后端设置WebSocket依赖,配置WebSocket服务,以及在前端创建WebSocket连接以接收订单通知。当新订单产生时,服务端向前端发送消息,前端接收到消息后弹出提醒框并播放音乐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

WebSocket是客户端和服务器端的一个通信,WebSocket分为客户端和服务端,所以我们两个端都要开发,前端的WebSocket在卖家订单管理界面的js代码里,会进行一个监听,一旦微信点餐的前端对服务端产生一个新的订单,服务端WebSocket就会对含有WebSocket的前端卖家订单管理界面发送消息,收到消息的前端就可以进行一系列的动作,如弹出提醒框、播放音乐等。
菜鸟教程:浏览器端WebSocket介绍
博客:https://blog.youkuaiyun.com/weixin_43580824/article/details/129990935?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129990935%22%2C%22source%22%3A%22weixin_43580824%22%7D
先是进行后端的开发
第一步 要引入SpringBoot对WebSocket的依赖

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

第二步

@Component
public class WebSocketConfig {

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

}

第三步 在排查业务里面产生新的排查项目推送消息给前端

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(ReportDTO dto) {
        SysUser user = LoginUserContextHolder.getUser();
        Report report = dto.getReport();
        Long reportId = report.getId();
        Assert.notNull(reportId, "报告id为空");
        Long n = baseMapper.selectCount(Wrappers.query(Report.builder().id(reportId).build()));
        Assert.isTrue(n == 1, "报告不存在");
        Long followerId = report.getFollowerId();
        Assert.notNull(followerId, "陪同人员为空");
        String followerName = report.getFollowerName();
        Assert.notBlank(followerName, "陪同人员为空");
        FileAttachment checkerSignPic = dto.getCheckerSignPic();
        Assert.isTrue(Objects.nonNull(checkerSignPic)
                && StrUtil.isNotBlank(checkerSignPic.getFileUrl()), "陪同人签名为空");
        FileAttachment followSignPic = dto.getFollowSignPic();
        Assert.isTrue(Objects.nonNull(followSignPic)
                && StrUtil.isNotBlank(followSignPic.getFileUrl()), "排查人签名为空");

        //更新排查内容,计算隐患项目
        List<Integer> resultList = subjectService.batchUpd(dto.getSubjectList());

        /*List<ReportSubjectDTO> subjectList = dto.getSubjectList();
        List<Integer> resultList = new ArrayList<>();
        subjectList.forEach(s -> resultList.add(s.getSubject().getCheckResult()));*/

        Integer reportResult = resultList.stream().max(Integer::compareTo).orElse(-1);
        Assert.isTrue(reportResult > -1, "错误的排查结果");
        report.setCheckResult(reportResult);
        //维护隐患状态
        report.setHiddenState(reportResult);
        report.setSubmitTime(LocalDateTime.now());
        long dangerNum = resultList.stream().filter(e -> e > 0).count();
        report.setDangerNum((int) dangerNum);
        report.setRestDangerNum((int) dangerNum);
        report.setReviewStatus(dangerNum > 0 ? 0 : -1);
        Long unitId = report.getUnitId();
        report.setSubmitFlag(1);
        if (dangerNum > 0) {
            LocalDate deadline = report.getDeadline();
            Assert.notNull(deadline, "截止日期为空");
        }
        //维护签名
        addSignInfo(reportId, checkerSignPic, followSignPic);
        baseMapper.updateById(report);

        //开始维护额外信息
        //个人工作统计
        workStatService.insertAndUpdateNumberOfHiddenDangersFound(report.getProjectId(), (int) dangerNum);
        //todo 维护 隐患变动记录(暂时不开发)
        if (Objects.equals(report.getRenewFlag(), 1)
                && Objects.nonNull(report.getRenewReportId())) {
            //维护 给上份报告增加复查记录(重新排查覆盖了上份报告的隐患)
            checkReportReviewService.updateUpCheckReportReview(report.getRenewReportId().toString());
            //每次创建报告清空单位的排查信息
            CheckUnitStatus newCheckUnitStatus = checkUnitStatusService.findNewCheckUnitStatus(unitId.toString());
            newCheckUnitStatus.setReviewStatus(0);
            newCheckUnitStatus.setIsPeriod(1);
            newCheckUnitStatus.setLastDangerNum(0);
            newCheckUnitStatus.setLastRestDangerNum(0);
            newCheckUnitStatus.setPeriodDangerNum(0);
            newCheckUnitStatus.setLastReviewSuccessNum(0);
            newCheckUnitStatus.setLastReviewFailedNum(0);
            newCheckUnitStatus.setHiddenState(reportResult);
            checkUnitStatusService.updateById(newCheckUnitStatus);

        }
        //维护 单位排查状态表
        checkUnitStatusService.updateCheckUnitStatus(report.getUnitId());
        CheckUnitStatus newCheckUnitStatus = checkUnitStatusService.findNewCheckUnitStatus(report.getUnitId().toString());
        newCheckUnitStatus.setHiddenState(reportResult);
        newCheckUnitStatus.setCreateBy(user.getNickname());
        checkUnitStatusService.updateById(newCheckUnitStatus);
        //额外信息维护完毕
        CheckUnitDynamics checkUnitDynamics = new CheckUnitDynamics();
        checkUnitDynamics.setEventType(2);
        checkUnitDynamics.setReportId(reportId);
        checkUnitDynamics.setUnitId(report.getUnitId());
        Integer checkResult = report.getCheckResult();
        checkUnitDynamics.setCheckResult(checkResult);
        checkUnitDynamics.setCreateTime(LocalDateTime.now().plusSeconds(2));
        checkUnitDynamicsService.insertCheck(checkUnitDynamics);
        //解锁
        checkUnitStatusService.updateTodayCheckNumber(report);
        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("checkResult", report.getCheckResult());
        messageMap.put("unitName", report.getUnitName());
        messageMap.put("submitTime", report.getSubmitTime());
        messageMap.put("createBy", user.getNickname());
        //发送websocket消息
        webSocket.sendMessage(messageMap.toString());
        unLockUnit(dto.getReport().getUnitId());
    }
}

这样我们后端WebSocket相关的业务逻辑类已全部完成。

第四步 写一个响应前端WebSocket的后端WebSocket,这也是一个Controller,但比较特殊,是用WS协议进行通信的,我们写在Service包里。

@Component
@ServerEndpoint("/webSocket")
@Slf4j
public class WebSocket {

    private Session session;

    private static CopyOnWriteArraySet<WebSocket> webSocketSet=new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(Session session){
        this.session=session;
        webSocketSet.add(this);
        log.info("【websocket消息】 有新的连接,总数:{}",webSocketSet.size());
    }

    @OnClose
    public void onClose(){
        webSocketSet.remove(this);
        log.info("【websocket消息】 连接断开,总数:{}",webSocketSet.size());
    }

    @OnMessage
    public void onMessage(String message){
        log.info("【websocket消息】 收到客户端发来的消息:{}",message);
    }

    public void sendMessage(String message){
        for(WebSocket webSocket:webSocketSet){
            log.info("【websocket消息】 广播消息,message={}",message);
            try {
                webSocket.session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

然后是前端
前端大屏页面前端界面的WebSocket如下:

<script>
    var websocket=null;
    if('WebSocket' in window){
        websocket=new WebSocket('ws://sqmax.natapp1.cc/sell/webSocket');
    }else{
        alert('该浏览器不支持websocket');
    }
    websocket.onopen=function (ev) {
        console.log('建立连接');
    }
    websocket.onclose=function (ev) {
        console.log('连接关闭');
    }
    websocket.onmessage=function (ev) {
        console.log('收到消息:'+ev.data);
        //弹窗提醒,播放消息
        $('#myModal').modal('show');

        document.getElementById('notice').play();
    }
    window.onbeforeunload=function (ev) {
        websocket.close();
    }
</script>

以下是WebSocket js代码控制HTML。

<div class="modal fade" id="myModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                <h4 class="modal-title" id="myModalLabel">
                    提醒
                </h4>
            </div>
            <div class="modal-body">
                你有新的排查信息
            </div>
            <div class="modal-footer">
                <button onclick="javascript:document.getElementById('notice').pause()" type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                <button onclick="location.reload()" type="button" class="btn btn-primary">查看详情</button>
            </div>
        </div>
    </div>
</div>
<#--播放音乐-->
<audio id="notice" loop="loop">
    <source src="/sell/mp3/song.mp3" type="audio/mpeg" />
</audio>

当前端收到后端的WebSocket消息后,会弹出一个对话框,并播放音乐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值