java使用websocket前后端通信实现

WebSocket是客户端和服务器端的一个通信,WebSocket分为客户端和服务端,所以我们两个端都要开发,前端的WebSocket在卖家订单管理界面的js代码里,会进行一个监听,一旦微信点餐的前端对服务端产生一个新的订单,服务端WebSocket就会对含有WebSocket的前端卖家订单管理界面发送消息,收到消息的前端就可以进行一系列的动作,如弹出提醒框、播放音乐等。

后端的开发

第一步 要引入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();
    }
}
第三步 在订单业务类的的创建订单方法完成后,后端向前端商家管理系统的订单界面发送WebSocket消息。
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private ProductService productService;

    @Autowired
    private OrderDetailRepository orderDetailRepository;

    @Autowired
    private WebSocket webSocket;

    @Override
    @Transactional
    public OrderDTO create(OrderDTO orderDTO) {

        String orderId= KeyUtil.genUniqueKey();
        BigDecimal orderAmount=new BigDecimal(BigInteger.ZERO);
//        List<CartDTO> cartDTOList=new ArrayList<>();

        //1.查询商品(数量,价格)
        for(OrderDetail orderDetail:orderDTO.getOrderDetailList()){
            ProductInfo productInfo=productService.findOne(orderDetail.getProductId());
            if(productInfo==null){
//                throw new SellException(ResultEnum.PRODUCT_NOT_EXIT);
                throw new ResponseBankException();
            }
            //2.计算订单总价
            orderAmount=productInfo.getProductPrice()
                    .multiply(new BigDecimal(orderDetail.getProductQuantity()))
                    .add(orderAmount);
            //订单详情入库
            orderDetail.setDetailId(KeyUtil.genUniqueKey());
            orderDetail.setOrderId(orderId);
            BeanUtils.copyProperties(productInfo,orderDetail);
            orderDetailRepository.save(orderDetail);

//            CartDTO cartDTO=new CartDTO(orderDetail.getProductId(),orderDetail.getProductQuantity());
//            cartDTOList.add(cartDTO);

        }

        //3,写入订单数据库(orderMaster和orderDetail)
        OrderMaster orderMaster=new OrderMaster();
        orderDTO.setOrderId(orderId);
        BeanUtils.copyProperties(orderDTO,orderMaster);
//        orderMaster.setOrderId(orderId);
        orderMaster.setOrderAmount(orderAmount);
        orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
        orderMasterRepository.save(orderMaster);

        //4.扣库存
        List<CartDTO> cartDTOList=orderDTO.getOrderDetailList().stream().map(e->
                new CartDTO(e.getProductId(),e.getProductQuantity()))
                .collect(Collectors.toList());
        productService.decreaseStock(cartDTOList);

        //发送websocket消息(重点)
        webSocket.sendMessage(orderDTO.getOrderId());

        return orderDTO;
    }
这样我们后端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消息后,会弹出一个对话框,并播放音乐。

最后我们来测试一下代码。

我们用Postman这个工具代替前端微信点餐,向指定url发送一个如下的post请求。
这里写图片描述
在前端的商家管理界面可以看到如下的效果:
这里写图片描述

出处:https://github.com/sqmax/springboot-project/wiki/WebSocket%E6%B6%88%E6%81%AF%E6%8E%A8%E9%80%81

猜你喜欢

转载自blog.csdn.net/sihai12345/article/details/80924937