Browse Source

下载订单功能优化

xian 4 years ago
parent
commit
2bba36e9c6

+ 64 - 73
watero-rst-web/src/main/java/com/iamberry/rst/controllers/order/AdminOrderController.java

@@ -41,6 +41,7 @@ import com.iamberry.wechat.tools.ObjectExcelView;
 import com.iamberry.wechat.tools.ResponseJson;
 import com.iamberry.wechat.tools.payUtil.DatetimeUtil;
 import com.iamberry.wechat.tools.payUtil.StringUtil;
+import org.apache.commons.collections.list.SynchronizedList;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.Logical;
@@ -61,6 +62,12 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * 订单 handler
@@ -111,6 +118,11 @@ public class AdminOrderController {
     private DealerProductService dealerProductService;
 
     /**
+     * 缓存物流公司名称和变的规则
+     */
+    private static final Map<String, String> LOGISTICE_CACHE = Collections.<String, String>synchronizedMap(new WeakHashMap<String, String>(30));
+
+    /**
      * 进入更换滤芯页面
      *
      * @return
@@ -752,8 +764,8 @@ public class AdminOrderController {
     public ResponseJson valDownloadOrderExcel(HttpServletRequest request,SalesOrder so) throws Exception {
         ResponseJson rj = ResponseJson.getFAILURE();
         Integer num = salesOrderService.listSalesOrderAndItemNum(so);
-        if(num > 5000){
-            rj.setResultMsg("下载订单超过5000条,请精确查询条件");
+        if(num > 20000){
+            rj.setResultMsg("下载订单超过20000条,请精确查询条件");
             return rj;
         }
         return ResponseJson.getSUCCESS();
@@ -768,19 +780,15 @@ public class AdminOrderController {
     @RequestMapping("/download_order_excel")
     @RequiresPermissions("salesOrder:download:Logistics")
     public ModelAndView downloadOrderExcel(HttpServletRequest request,SalesOrder so) throws Exception {
-
+        // 查询数据
         List<SalesOrder> temporarySalesOrderList = salesOrderService.listSalesOrderAndItem(so);
-
-        if(temporarySalesOrderList.size() > 5000){
-            return new ModelAndView().addObject("下载出错");
-        }
-
+        long ctrStart = System.currentTimeMillis();
         // 准备model
-        Map<String, Object> model = new HashMap<String, Object>(5);
+        Map<String, Object> model = new HashMap<String, Object>(3);
         model.put("fileName", "订单列表");
 
         // 标题
-        List<String> titles = new ArrayList<String>();
+        List<String> titles = new ArrayList<String>(22);
         titles.add("订单创建日期");
         titles.add("订单编号");
         titles.add("交易号");
@@ -803,78 +811,57 @@ public class AdminOrderController {
         titles.add("邮费成本");
         titles.add("发货仓库");
         model.put("titles", titles);
-        List<List<Object>> countexts = new ArrayList<List<Object>>();
+        List<List<Object>> countexts = Collections.synchronizedList(new ArrayList<>(temporarySalesOrderList.size()));
         if(temporarySalesOrderList.size() > 0){
-            for (SalesOrder salesOrder : temporarySalesOrderList) {
-                List<Object> row = new ArrayList<Object>();
-                SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
-                row.add(salesOrder.getSalesCreateTime() == null ? null:formatter.format(salesOrder.getSalesCreateTime()));
-                row.add(salesOrder.getSalesOrderId());
-                row.add(salesOrder.getSalesDealCode());
-                if(salesOrder.getSalesCustomerId() == null){
-                    row.add("正常订单");
-                }else{
-                    String typeName = salesOrder.getProcTypeName() == null ? "":salesOrder.getProcTypeName();
-                    row.add("售后订单("+  typeName +")");
-                }
-                row.add(salesOrder.getSalesAddressName());
-                row.add(salesOrder.getSalesAddressTel());
-                //分割省市
-                if(salesOrder.getSalesAddressInfo() == null){
-                    row.add(null);
-                    row.add(null);
-                }else{
-                    String[] strarray=salesOrder.getSalesAddressInfo().split(" ");
-                    row.add(strarray[0]);
-                    row.add(strarray[1]);
+            // 同步两个线程
+            Lock lock = new ReentrantLock();
+            Condition condition = lock.newCondition();
+            // 并发的线程
+            int threadSize = temporarySalesOrderList.size() >= 5000 ? 5 : 1;
+            // 每个线程处理的数量
+            int size = temporarySalesOrderList.size()/threadSize;
+            final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadSize, new Runnable() {
+                @Override
+                public void run() {
+                    // 尝试获取Lock
+                    lock.lock();
+                    // 通知一个正在等待队列的线程,此处为下载线程
+                    condition.signal();
+                    // 释放锁
+                    lock.unlock();
                 }
-                row.add(salesOrder.getSalesAddressInfo());
-                if(salesOrder.getSalesPostFirm() != null){
-                    String frim = replace(salesOrder.getSalesPostFirm());
-                    row.add(frim);
-                }else{
-                    row.add(null);
-                }
-                row.add(salesOrder.getSalesPostNum());
-                row.add(salesOrder.getItemProductName() == null ? null:salesOrder.getItemProductName()+(salesOrder.getItemProductColor() == null ? null:"-"+salesOrder.getItemProductColor()));
-                row.add(salesOrder.getItemNum());
-                row.add(salesOrder.getItemReturnNum());
-                row.add(salesOrder.getCompanyName());
-                row.add(salesOrder.getStoreName());
-                row.add(salesOrder.getSalesDeliverTime() == null ? null:formatter.format(salesOrder.getSalesDeliverTime()));
-                if(salesOrder.getSalesDistributionTime() == null){
-                    if(salesOrder.getSalesSendTime() != null){
-                        row.add(formatter.format(salesOrder.getSalesSendTime()));
-                    }else{
-                        row.add(null);
-                    }
-                }else{
-                    row.add(formatter.format(salesOrder.getSalesDistributionTime()));
-                }
-                row.add(salesOrder.getProcMethodName());
-                row.add(salesOrder.getSalesPostageCost() == null ? 0 : salesOrder.getSalesPostageCost()/100);
-                String temp = "京东仓";
-                if (salesOrder.getSalesSendType() != 3) {
-                    if (salesOrder.getSalesWarehouseId() == null) {
-                        temp = null;
-                    } else {
-                        if (salesOrder.getSalesWarehouseId() == 1) {
-                            temp = "正常仓库";
-                        } else {
-                            temp = "维修仓库";
-                        }
-                    }
+            });
+
+            // 分组提交数据
+            for (int i = 0; i < threadSize; i++) {
+                int start = size * i;
+                int stop = 0;
+                if (i == (threadSize-1)) {
+                    stop = temporarySalesOrderList.size()-1;
+                } else {
+                    stop = (i+1) * size - 1;
                 }
-                row.add(temp);
-                countexts.add(row);
+                // 此处会有一个问题:如果当线程池的数量都被占用,那么此处将会一直无法完成,如果线程池的数量小于本次提交的,则会导致此操作永远无法完成,所以需要将线程池大小设置为>=6,即其他线程完成后,此功能可以使用
+                AdminSalesOrderController.THREAD_POOL.execute(new DownOrderRunnable(cyclicBarrier, start, stop, temporarySalesOrderList, this, countexts));
             }
+            /**
+             * 等待所有数据完成
+             */
+            // 获取锁对象 lock
+            lock.lock();
+            // 将当前下载线程加入等待队列,并释放锁,为回调线程提供锁
+            condition.await();
+            // 释放锁
+            lock.unlock();
         }
+
+        System.out.println("组装数据共花费:" + (System.currentTimeMillis()-ctrStart));
+
         model.put("varList", countexts);
         ObjectExcelView erv = new ObjectExcelView();
         return new ModelAndView(erv,model);
     }
 
-
     /**
      * 保存交易号
      * @param filePath
@@ -922,13 +909,17 @@ public class AdminOrderController {
 
     /**物流名称替换**/
     public String replace(String code) {
-        String name = "";
         if(code == null || "".equals(code)){
             return "";
         }
+        String firm = LOGISTICE_CACHE.get("LOGISTICS_" + code);
+        if (firm != null) {
+            return firm;
+        }
         List<LogisticsInfo> logisticsInfoList = logisticsInfoService.getLogisticsInfoList(new LogisticsInfo());
         for (LogisticsInfo logistics:logisticsInfoList) {
             if(code .equalsIgnoreCase(logistics.getLogisticsRstCode())){
+                LOGISTICE_CACHE.put("LOGISTICS_" + code, logistics.getLogisticsName());
                 return logistics.getLogisticsName();
             }
         }

+ 3 - 3
watero-rst-web/src/main/java/com/iamberry/rst/controllers/order/AdminSalesOrderController.java

@@ -398,7 +398,7 @@ public class AdminSalesOrderController {
         res.reset();
         res.setContentType("application/vnd.ms-excel;charset=utf-8");
         res.setHeader("Content-Disposition", "attachment;filename="
-                + new String((fileName + ".xls").getBytes(), "iso-8859-1"));
+                + new String((fileName + ".xls").getBytes(), "ISO-8859-1"));
         ServletOutputStream out = res.getOutputStream();
         BufferedInputStream bis = null;
         BufferedOutputStream bos = null;
@@ -457,7 +457,7 @@ public class AdminSalesOrderController {
      * @return
      */
     public String getPostCode(String firm) {
-        if (firm == null || firm.equals("")) {
+        if (firm == null || "".equals(firm)) {
             return "01";
         }
         LogisticsInfo logisticsInfo = new LogisticsInfo();
@@ -2163,7 +2163,7 @@ public class AdminSalesOrderController {
         return "上传完成,请稍后,大约5分钟后执行完成!";
     }
     private static final ThreadFactory POST_POOL_THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("POST-POOL-%d").build();
-    private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(1, 5, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(20), POST_POOL_THREAD_FACTORY, new ThreadPoolExecutor.AbortPolicy());
+    public static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(20), POST_POOL_THREAD_FACTORY, new ThreadPoolExecutor.AbortPolicy());
 
     /**
      * 进入添加拉货数量

+ 1 - 1
watero-rst-web/src/main/java/com/iamberry/rst/controllers/order/AwaitSendController.java

@@ -157,7 +157,7 @@ public class AwaitSendController {
         }
         int errorOrderNum = 0;
         // 聚合打单方式
-        Map<String, Integer> postMap = new HashMap<>();
+        Map<String, Integer> postMap = new HashMap<>(10);
         List<PostInfo> postInfos = salesOrderService.listWaitPrintOrderNum(orderWarehouse.getWarehouseId());
         if (postInfos != null && !postInfos.isEmpty()) {
             for (PostInfo temp : postInfos) {

+ 128 - 0
watero-rst-web/src/main/java/com/iamberry/rst/controllers/order/DownOrderRunnable.java

@@ -0,0 +1,128 @@
+package com.iamberry.rst.controllers.order;
+
+import com.iamberry.rst.core.cm.SalesOrder;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+public class DownOrderRunnable implements Runnable {
+
+    /** 准备一个时间获取器 */
+    private Calendar cal = Calendar.getInstance();
+    /** 线程栏杆 */
+    private final CyclicBarrier barrier;
+    /** 当前线程需要处理的数量 */
+    private int start;
+    /** 当前线程的编号 */
+    private int stop;
+    /** 需要遍历的数据 */
+    private List<SalesOrder> salesOrders;
+    /** 调用对象 */
+    private AdminOrderController orderController;
+    /** 接受数据的对象 */
+    private List<List<Object>> contexts;
+
+    public DownOrderRunnable(CyclicBarrier barrier, int start ,int stop, List<SalesOrder> salesOrders, AdminOrderController orderController, List<List<Object>> contexts) {
+        this.barrier = barrier;
+        this.start = start;
+        this.stop = stop;
+        this.salesOrders = salesOrders;
+        this.orderController = orderController;
+        this.contexts = contexts;
+    }
+
+    @Override
+    public void run() {
+        System.out.println("执行代码....");
+        try {
+            for (;start <= stop; start++) {
+                SalesOrder salesOrder = salesOrders.get(start);
+                // 准备接受行的数据
+                List<Object> row = new ArrayList<Object>(22);
+                // 时间
+                if (salesOrder.getSalesCreateTime() != null) {
+                    cal.setTime(salesOrder.getSalesCreateTime());
+                    row.add("年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
+                } else {
+                    row.add(null);
+                }
+                row.add(salesOrder.getSalesOrderId());
+                row.add(salesOrder.getSalesDealCode());
+                if(salesOrder.getSalesCustomerId() == null){
+                    row.add("正常订单");
+                }else{
+                    String typeName = salesOrder.getProcTypeName() == null ? "":salesOrder.getProcTypeName();
+                    row.add("售后订单("+  typeName +")");
+                }
+                row.add(salesOrder.getSalesAddressName());
+                row.add(salesOrder.getSalesAddressTel());
+                //分割省市
+                if(salesOrder.getSalesAddressInfo() == null){
+                    row.add(null);
+                    row.add(null);
+                }else{
+                    String[] strarray=salesOrder.getSalesAddressInfo().split(" ");
+                    row.add(strarray[0]);
+                    row.add(strarray[1]);
+                }
+                row.add(salesOrder.getSalesAddressInfo());
+                if(salesOrder.getSalesPostFirm() != null){
+                    row.add(orderController.replace(salesOrder.getSalesPostFirm()));
+                }else{
+                    row.add(null);
+                }
+                row.add(salesOrder.getSalesPostNum());
+                row.add(salesOrder.getItemProductName() == null ? null:salesOrder.getItemProductName()+(salesOrder.getItemProductColor() == null ? null:"-"+salesOrder.getItemProductColor()));
+                row.add(salesOrder.getItemNum());
+                row.add(salesOrder.getItemReturnNum());
+                row.add(salesOrder.getCompanyName());
+                row.add(salesOrder.getStoreName());
+                if (salesOrder.getSalesDeliverTime() != null) {
+                    cal.setTime(salesOrder.getSalesDeliverTime());
+                    row.add("年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
+                } else {
+                    row.add(null);
+                }
+                if(salesOrder.getSalesDistributionTime() == null){
+                    if(salesOrder.getSalesSendTime() != null){
+                        cal.setTime(salesOrder.getSalesSendTime());
+                        row.add("年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
+                    }else{
+                        row.add(null);
+                    }
+                }else{
+                    cal.setTime(salesOrder.getSalesDistributionTime());
+                    row.add("年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
+                }
+                row.add(salesOrder.getProcMethodName());
+                row.add(salesOrder.getSalesPostageCost() == null ? null : salesOrder.getSalesPostageCost()/100);
+                String temp = "京东仓";
+                if (salesOrder.getSalesSendType() != 3) {
+                    // 方式sendType=3表示京东仓发货,不等于3表示自有仓库发货,需要根据warehouseId判断是哪个仓库发货
+                    if (salesOrder.getSalesWarehouseId() == null) {
+                        temp = null;
+                    } else {
+                        if (salesOrder.getSalesWarehouseId() == 1) {
+                            temp = "正常仓库";
+                        } else {
+                            temp = "维修仓库";
+                        }
+                    }
+                }
+                row.add(temp);
+                contexts.add(row);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                barrier.await();
+            } catch (InterruptedException | BrokenBarrierException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}