• websocket通讯


    第一步:前段js代码 黄线根据个人所需配置

    <html>
    <#include "../common/header.ftl">
    
    <body>
    <div id="wrapper" class="toggled">
    
        <#--边栏sidebar-->
        <#include "../common/nav.ftl">
    
        <#--主要内容content-->
        <div id="page-content-wrapper">
            <div class="container-fluid">
                <div class="row clearfix">
                    <div class="col-md-12 column">
                        <table class="table table-bordered table-condensed">
                            <thead>
                            <tr>
                                <th>订单id</th>
                                <th>姓名</th>
                                <th>手机号</th>
                                <th>地址</th>
                                <th>金额</th>
                                <th>订单状态</th>
                                <th>支付状态</th>
                                <th>创建时间</th>
                                <th colspan="2">操作</th>
                            </tr>
                            </thead>
                            <tbody>
    
                            <#list orderDTOPage.content as orderDTO>
                            <tr>
                                <td>${orderDTO.orderId}</td>
                                <td>${orderDTO.buyerName}</td>
                                <td>${orderDTO.buyerPhone}</td>
                                <td>${orderDTO.buyerAddress}</td>
                                <td>${orderDTO.orderAmount}</td>
                                <td>${orderDTO.getOrderStatusEnum().message}</td>
                                <td>${orderDTO.getPayStatusEnum().message}</td>
                                <td>${orderDTO.createTime}</td>
                                <td><a href="/sell/seller/order/detail?orderId=${orderDTO.orderId}">详情</a></td>
                                <td>
                                    <#if orderDTO.getOrderStatusEnum().message == "新订单">
                                        <a href="/sell/seller/order/cancel?orderId=${orderDTO.orderId}">取消</a>
                                    </#if>
                                </td>
                            </tr>
                            </#list>
                            </tbody>
                        </table>
                    </div>
    
                <#--分页-->
                    <div class="col-md-12 column">
                        <ul class="pagination pull-right">
                        <#if currentPage lte 1>
                            <li class="disabled"><a href="#">上一页</a></li>
                        <#else>
                            <li><a href="/sell/seller/order/list?page=${currentPage - 1}&size=${size}">上一页</a></li>
                        </#if>
    
                        <#list 1..orderDTOPage.getTotalPages() as index>
                            <#if currentPage == index>
                                <li class="disabled"><a href="#">${index}</a></li>
                            <#else>
                                <li><a href="/sell/seller/order/list?page=${index}&size=${size}">${index}</a></li>
                            </#if>
                        </#list>
    
                        <#if currentPage gte orderDTOPage.getTotalPages()>
                            <li class="disabled"><a href="#">下一页</a></li>
                        <#else>
                            <li><a href="/sell/seller/order/list?page=${currentPage + 1}&size=${size}">下一页</a></li>
                        </#if>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    
    </div>
    
    <#--弹窗-->
    
    
                <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>
    
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script>
        var websocket = null;
        if('WebSocket' in window) {
            websocket = new WebSocket('ws://127.0.0.1:8080/sell/webSocket');
        }else {
            alert('该浏览器不支持websocket!');
        }
    
        websocket.onopen = function (event) {
            console.log('建立连接');
        }
    
        websocket.onclose = function (event) {
            console.log('连接关闭');
        }
    
        websocket.onmessage = function (event) {
            console.log('收到消息:' + event.data)
            //弹窗提醒, 播放音乐
            $('#myModal').modal('show');
    
            document.getElementById('notice').play();
        }
    
        websocket.onerror = function () {
            alert('websocket通信发生错误!');
        }
    
        window.onbeforeunload = function () {
            websocket.close();
        }
    
    </script>
    
    </body>
    </html>

    第二步:pom文件引入依赖 websocket

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

    第三步:建立文件WebSocketConfig

    package com.payease.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     * Created by liuxiaoming
     * 2017-12-11 下午03:12
     */
    @Component
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }

    第四步:建立后台业务代码

    package com.payease.service;
    
    import lombok.extern.slf4j.Slf4j;
    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.util.concurrent.CopyOnWriteArraySet;
    
    /**
     * @Created By liuxiaoming
     * @CreateTime 2017/12/5 下午5:55
     **/
    @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);
                try {
                    webSocket.session.getBasicRemote().sendText(message);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
    
    
        }
    }

     第五步:Service,controller 调用

    package com.payease.service.impl;
    
    import com.payease.converter.OrderMaster2OrderDTOConverter;
    import com.payease.dataobject.OrderDetail;
    import com.payease.dataobject.OrderMaster;
    import com.payease.dataobject.ProductInfo;
    import com.payease.dto.CartDTO;
    import com.payease.dto.OrderDTO;
    import com.payease.enums.OrderStatusEnum;
    import com.payease.enums.PayStatusEnum;
    import com.payease.enums.ResultEnum;
    import com.payease.exception.SellException;
    import com.payease.repository.OrderDetailRepository;
    import com.payease.repository.OrderMasterRepository;
    import com.payease.service.OrderService;
    import com.payease.service.ProductService;
    import com.payease.service.PushMessageService;
    import com.payease.service.WebSocket;
    import com.payease.utils.KeyUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.Pageable;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.util.CollectionUtils;
    
    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * 订单Service
     * liuxiaoming
     * 2017-11-20
     */
    @Service
    @Slf4j
    public class OrderServiceImpl implements OrderService {
    
        @Autowired
        private ProductService productService;
    
        @Autowired
        private OrderDetailRepository orderDetailRepository;
    
        @Autowired
        private OrderMasterRepository orderMasterRepository;
    
        @Autowired
        private WebSocket webSocket;
    
        @Autowired
        private PushMessageService pushMessageService;
        /**
         * 创建订单
         * liuxiaoming
         * 2017-11-20
         *
         */
        @Override
        @Transactional
        public OrderDTO create(OrderDTO orderDTO) {
    
            String orderId = KeyUtil.getUniqueKey();
            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_EXIST);
                }
                //2. 计算订单总价
                orderAmount = productInfo.getProductPrice()
                        .multiply(new BigDecimal(orderDetail.getProductQuantity())).add(orderAmount);
                //订单详情入库
                orderDetail.setDetailId(KeyUtil.getUniqueKey());
                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.setOrderAmount(orderAmount);
            orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
            orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
            orderMasterRepository.save(orderMaster);
    
    
            //4. 扣库存 :   循环遍历 OrderDetailList,把OrderDetail封装到CartDTO,最后存入orderDTO中的OrderDetailList
            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;
        }
        /**
         * 查询单个订单
         * liuxiaoming
         * 2017-11-21
         *
         */
        @Override
        public OrderDTO findOne(String orderId) {
    
            OrderMaster orderMaster = orderMasterRepository.findOne(orderId);
            if(orderMaster == null ){
                throw new SellException(ResultEnum.ORDER_NOT_EXIST);
            }
            List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderId(orderId);
            if(CollectionUtils.isEmpty(orderDetailList)){
                throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST);
            }
    
            OrderDTO orderDTO = new OrderDTO();
            BeanUtils.copyProperties(orderMaster, orderDTO);
            orderDTO.setOrderDetailList(orderDetailList);
            return orderDTO;
        }
    
        /**
         * 查询订单列表
         * liuxiaoming
         * 2017-11-21
         *
         */
        @Override
        public Page<OrderDTO> findList(String buyerOpenid, Pageable pageable) {
    
            Page<OrderMaster> orderMasterPage = orderMasterRepository.findByBuyerOpenid(buyerOpenid, pageable);
    
            List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterPage.getContent());
    
            return new PageImpl<OrderDTO>(orderDTOList, pageable, orderMasterPage.getTotalElements());
        }
    
        /**
         * 订单取消
         * liuxiaoming
         * 2017-11-23
         *
         */
        @Override
        @Transactional
        public OrderDTO cancel(OrderDTO orderDTO) {
            OrderMaster orderMaster = new OrderMaster();
    
            //判断订单状态
            if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
                log.error("【取消订单】订单状态不正确, orderId={}, orderStatus={}", orderDTO.getOrderId(), orderDTO.getOrderStatus());
                throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
            }
            //修改订单状态
            orderDTO.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
            BeanUtils.copyProperties(orderDTO, orderMaster);
            OrderMaster updateResult = orderMasterRepository.save(orderMaster);
            if(updateResult == null ){
                log.error("【取消订单】更新失败, orderMaster={}", orderMaster);
                throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
            }
            //返回库存
            if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
                log.error("【取消订单】订单中无商品详情, orderDTO={}", orderDTO);
                throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
            }
            List<CartDTO> cartDTOList = orderDTO.getOrderDetailList().stream()
                    .map(e -> new CartDTO(e.getProductId(), e.getProductQuantity()))
                    .collect(Collectors.toList());
            productService.increaseStock(cartDTOList);
            //如果已支付,需要退款
            if(orderDTO.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())){
                //TODO
            }
            return orderDTO;
        }
        /**
         *  完结订单
         * liuxiaoming
         * 2017-11-24
         *
         */
        @Override
        @Transactional
        public OrderDTO finish(OrderDTO orderDTO) {
            //判断订单状态
            if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
                log.error("【完结订单】订单状态不正确, orderId={}, orderStatus={}", orderDTO.getOrderId());
                throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
            }
            //修改订单状态
            orderDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
            OrderMaster orderMaster = new OrderMaster();
            BeanUtils.copyProperties(orderDTO, orderMaster);
            OrderMaster updateResult = orderMasterRepository.save(orderMaster);
            if(updateResult == null ){
                log.error("【完结订单】更新失败, orderMaster={}", orderMaster);
                throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
            }
            //推送微信模板消息
            pushMessageService.orderStatus(orderDTO);
            return orderDTO;
        }
        /**
         *  支付订单
         * liuxiaoming
         * 2017-11-24
         *
         */
        @Override
        @Transactional
        public OrderDTO paid(OrderDTO orderDTO) {
            //判断订单状态
            if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
                log.error("【支付订单】订货状态不正确, orderId={}, orderStatus={}", orderDTO.getOrderId());
                throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
            }
            //判断支付状态
            if(!orderDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())){
                log.error("【订单支付】订单支付状态不正确, orderDTO={}", orderDTO);
                throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
            }
            //修改支付状态
            orderDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
            OrderMaster orderMaster = new OrderMaster();
            BeanUtils.copyProperties(orderDTO, orderMaster);
            OrderMaster updateResult = orderMasterRepository.save(orderMaster);
            if(updateResult == null ){
                log.error("【订单支付】更新失败, orderMaster={}", orderMaster);
                throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
            }
            return orderDTO;
        }
    
        @Override
        public Page<OrderDTO> findList(Pageable pageable) {
            Page<OrderMaster> orderMasterPage = orderMasterRepository.findAll(pageable);
    
            List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterPage.getContent());
    
            return new PageImpl<>(orderDTOList, pageable, orderMasterPage.getTotalElements());
        }
    }
    package com.payease.controller;
    
    import com.payease.VO.ResultVO;
    import com.payease.converter.OrderForm2OrderDTOConverter;
    import com.payease.dto.OrderDTO;
    import com.payease.enums.ResultEnum;
    import com.payease.exception.SellException;
    import com.payease.form.OrderForm;
    import com.payease.service.BuyerService;
    import com.payease.service.OrderService;
    import com.payease.utils.ResultVOUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.StringUtils;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.Valid;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Created by liuxiaoming
     * 2017-11-27 23:27
     */
    @RestController
    @RequestMapping("/buyer/order")
    @Slf4j
    public class BuyerOrderController {
    
        @Autowired
        private OrderService orderService;
    
        @Autowired
        private BuyerService buyerService;
    
        //创建订单
        @PostMapping("/create")
        public ResultVO<Map<String, String>> create(@Valid OrderForm orderForm,
                                                    BindingResult bindingResult) {
            if (bindingResult.hasErrors()) {
                log.error("【创建订单】参数不正确, orderForm={}", orderForm);
                throw new SellException(ResultEnum.PARAM_ERROR.getCode(),
                        bindingResult.getFieldError().getDefaultMessage());
            }
    
            OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);
            if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())) {
                log.error("【创建订单】购物车不能为空");
                throw new SellException(ResultEnum.CART_EMPTY);
            }
    
            OrderDTO createResult = orderService.create(orderDTO);
    
            Map<String, String> map = new HashMap<>();
            map.put("orderId", createResult.getOrderId());
    
            return ResultVOUtil.success(map);
        }
    
        //订单列表
        @GetMapping("/list")
        public ResultVO<List<OrderDTO>> list(@RequestParam("openid") String openid,
                                             @RequestParam(value = "page", defaultValue = "0") Integer page,
                                             @RequestParam(value = "size", defaultValue = "10") Integer size) {
            if (StringUtils.isEmpty(openid)) {
                log.error("【查询订单列表】openid为空");
                throw new SellException(ResultEnum.PARAM_ERROR);
            }
    
            PageRequest request = new PageRequest(page, size);
            Page<OrderDTO> orderDTOPage = orderService.findList(openid, request);
    
            return ResultVOUtil.success(orderDTOPage.getContent());
        }
    
    
        //订单详情
        @GetMapping("/detail")
        public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
                                         @RequestParam("orderId") String orderId) {
            //OrderDTO orderDTO = orderService.findOne(orderId);
            OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
            return ResultVOUtil.success(orderDTO);
        }
    
        //取消订单
        @PostMapping("/cancel")
        public ResultVO cancel(@RequestParam("openid") String openid,
                               @RequestParam("orderId") String orderId) {
            //OrderDTO orderDTO = orderService.findOne(orderId);
            //orderService.cancel(orderDTO);
            buyerService.cancelOrder(openid, orderId);
            return ResultVOUtil.success();
        }
    }

    第六步:postman提交

    127.0.0.1:8080/sell/buyer/order/create

  • 相关阅读:
    CodeForces 1059B
    CodeForces 714A
    浅析母函数
    CodeForces 816C 思维
    CodeForces 816B 前缀和
    CodeForces
    Java项目读取resources资源文件路径那点事
    原型模式
    一次给女朋友转账引发我对分布式事务的思考
    连续最大字段和问题
  • 原文地址:https://www.cnblogs.com/liuxiaoming123/p/8023232.html
Copyright © 2020-2023  润新知