Browse Source

添加了发送文件排队功能

wuweihao 4 năm trước cách đây
mục cha
commit
74959bab43

+ 1 - 1
xiaoan-application/src/main/resources/application-sit.properties

@@ -57,6 +57,6 @@ server.domian=http://192.168.0.163:8088
 # 打包文件文件存放地址
 server.package.result=/mnt/4Dkankan/scene/result/
 
-# 远程服务器地址(用来接收文件
+# 远程服务器地址(需要根据接收服务器变动ip
 remote.domian=http://127.0.0.1:8088
 remote.api=${remote.domian}/api/scene/uploadSceneHtmlData

+ 7 - 0
xiaoan-application/src/main/resources/application.properties

@@ -26,3 +26,10 @@ spring.servlet.multipart.enabled=true
 spring.servlet.multipart.max-file-size=512MB
 spring.servlet.multipart.max-request-size=512MB
 
+#线程池
+spring.task.pool.corePoolSize=10
+spring.task.pool.maxPoolSize=100
+spring.task.pool.keepAliveSeconds=100
+spring.task.pool.queueCapacity=100
+
+

+ 32 - 0
xiaoan-common/src/main/java/com/xiaoan/common/constant/ConfigConstant.java

@@ -0,0 +1,32 @@
+package com.xiaoan.common.constant;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * Created by owen on 2020/12/31 0031 14:22
+ *
+ * 全局动态参数
+ */
+@Component
+public class ConfigConstant {
+
+    /** 打包文件文件存放地址*/
+    @Value("${server.package.result}")
+    public  String SERVER_PACKAGE_RESULT;
+
+    /** 远程服务器地址(用来接收文件)*/
+    @Value("${remote.api}")
+    public  String REMOTE_API;
+
+    /** 域名*/
+    @Value("${server.domian}")
+    public  String SERVER_DOMIAN;
+
+    /** 发送文件域名*/
+    @Value("${remote.domian}")
+    public  String REMOTE_DOMIAN;
+
+
+
+}

+ 1 - 1
xiaoan-domain/src/main/java/com/xiaoan/domain/backend/SceneProEntity.java

@@ -145,7 +145,7 @@ public class SceneProEntity extends BaseModel implements Serializable {
     @ApiModelProperty(value = "调用V2还是V3的算法")
     private String buildType;
 
-    @ApiModelProperty(value = "下载场景状态,-1未生成过zip,0生成中,1生成zip完成, 2:文件发送成功, 3:文件发送失败")
+    @ApiModelProperty(value = "下载场景状态,-1未生成过zip,0生成中,1生成zip完成, 2:文件发送成功, 3:文件发送失败, 4:传输中")
     private Integer downloadStatus;
 
 

+ 4 - 0
xiaoan-service/src/main/java/com/xiaoan/service/backend/SceneService.java

@@ -23,6 +23,10 @@ public interface SceneService extends IBaseService<SceneProEntity, Long> {
 
     SceneProEntity findBySceneNum(String sceneNum);
 
+    ResultJson sendFile(Long id);
+
+//    ResultJson sendFile1(Long id);
+
 
 
 //    List<SceneResponse> findAllBySearchKey(SceneProRequest param, List<Long> ids, Long userId);

+ 47 - 1
xiaoan-service/src/main/java/com/xiaoan/service/backend/impl/SceneServiceImpl.java

@@ -2,7 +2,6 @@ package com.xiaoan.service.backend.impl;
 
 import com.github.pagehelper.PageHelper;
 import com.xiaoan.common.constant.MsgCode;
-import com.xiaoan.common.util.HttpRequestorUtil;
 import com.xiaoan.common.util.ResultJson;
 import com.xiaoan.dao.backend.IBaseMapper;
 import com.xiaoan.dao.backend.SceneRepository;
@@ -11,16 +10,20 @@ import com.xiaoan.domain.dto.request.SceneProRequest;
 import com.xiaoan.domain.dto.response.SceneResponse;
 import com.xiaoan.service.BaseServiceImpl;
 import com.xiaoan.service.backend.SceneService;
+import com.xiaoan.service.backend.listener.Variable;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Created by Hb_zzZ on 2020/3/2.
  */
+@Log4j2
 @Service
 @Transactional
 public class SceneServiceImpl extends BaseServiceImpl<SceneProEntity, Long> implements SceneService {
@@ -28,6 +31,10 @@ public class SceneServiceImpl extends BaseServiceImpl<SceneProEntity, Long> impl
     @Autowired
     private SceneRepository sceneRepository;
 
+
+    /** 原子一致性 */
+    private static AtomicInteger count = new AtomicInteger();
+
     @Override
     public IBaseMapper<SceneProEntity, Long> getBaseMapper() {
         return this.sceneRepository;
@@ -54,6 +61,45 @@ public class SceneServiceImpl extends BaseServiceImpl<SceneProEntity, Long> impl
         return sceneRepository.findBySceneNum(sceneNum);
     }
 
+    @Override
+    public ResultJson sendFile(Long id) {
+        // 设置参数
+        SceneProEntity proEntity = this.findById(id);
+        if (proEntity == null) {
+            return new ResultJson(MsgCode.e_COMMON_3001, MsgCode.msg_COMMON_3001);
+        }
+
+        if (proEntity.getDownloadStatus() < 1) {
+            return new ResultJson(MsgCode.e_COMMON_3001, "文件未打包");
+        }
+
+        String param = count.incrementAndGet() + "," + id;
+        // 入队
+        Variable.queue.offer(param);
+        log.info("入队成功: {}", param );
+
+        // 传输中
+        proEntity.setDownloadStatus(4);
+        proEntity.setUpdateTime(new Date());
+        this.update(proEntity);
+        return new ResultJson(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
+    }
+
+//    @Override
+//    public ResultJson sendFile1(Long id) {
+//
+//
+//        String param = count.incrementAndGet() + "," + id;
+//        // 入队
+//        Variable.queue.offer(param);
+//        log.info("入队成功: {}", param );
+//
+//        return new ResultJson(MsgCode.SUCCESS_CODE, param);
+//    }
+
+
+
 
 
 }
+

+ 173 - 0
xiaoan-service/src/main/java/com/xiaoan/service/backend/listener/AsyncTask.java

@@ -0,0 +1,173 @@
+package com.xiaoan.service.backend.listener;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.xiaoan.common.constant.ConfigConstant;
+import com.xiaoan.common.util.HttpRequestorUtil;
+import com.xiaoan.domain.backend.SceneProEditEntity;
+import com.xiaoan.domain.backend.SceneProEntity;
+import com.xiaoan.service.backend.SceneProEditService;
+import com.xiaoan.service.backend.SceneService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * Created by owen on 2020/12/31 0031 16:15
+ */
+@Log4j2
+@Component
+public class AsyncTask {
+
+
+    @Autowired
+    private SceneService sceneProService;
+
+    @Autowired
+    private SceneProEditService sceneProEditService;
+
+    @Autowired
+    private ConfigConstant configConstant;
+
+    /**
+     * 监听队列
+     * 当出现页面加载不了时,留意线程问题
+     */
+    @Async("taskExecutor")
+    public void sendFile() {
+        log.info("start sendFile task");
+        while (true) {
+            // 队列不为空
+            if (!Variable.queue.isEmpty()) {
+                String poll = Variable.queue.poll();
+                String id = StringUtils.substringAfterLast(poll, ",");
+                try {
+                    log.info("start process ");
+                    this.process(Long.valueOf(id));
+                    log.info("end process ");
+                } catch (Exception e) {
+                    log.error("文件发送失败");
+                    e.printStackTrace();
+                }
+                log.info("poll消费: {}", poll);
+
+                // 队列为空, 休眠
+            } else {
+                try {
+                    Thread.sleep(20000);
+                } catch (InterruptedException e) {
+                    log.error("休眠异常");
+                    e.printStackTrace();
+                }
+//                log.warn("休眠中 …… ……");
+            }
+
+        }
+
+    }
+
+    /**
+     * 处理逻辑
+     * @param id
+     * @throws Exception
+     */
+    public void process(Long id) throws Exception {
+
+        SceneProEntity proEntity = sceneProService.findById(id);
+
+
+        if (proEntity == null) {
+            log.error("对象为空");
+            return;
+        }
+
+        if (proEntity.getDownloadStatus() >= 1) {
+            String api = configConstant.REMOTE_API + "?sceneNum=" + proEntity.getNum();
+            int i = HttpRequestorUtil.fileRemote(api, configConstant.SERVER_PACKAGE_RESULT + proEntity.getNum() + ".zip");
+            if (i == 200) {
+                log.info("文件发送成功");
+
+                // 成功后还需要调用仕彬的两个接口
+                SceneProEntity sceneProEntity = new SceneProEntity();
+                BeanUtils.copyProperties(proEntity, sceneProEntity);
+
+                log.info("proEntity: {}", proEntity.toString());
+                log.info("copyProperties proEntity: {}", sceneProEntity.toString());
+
+                proEntity.setDownloadStatus(2);
+                JSONObject proJson = insertSceneProInfo(sceneProEntity);
+                String code = proJson.getString("code");
+                if (!"0".equals(code)) {
+                    log.error("发送insertSceneProInfo接口失败");
+                    proEntity.setDownloadStatus(3);
+                } else {
+                    // 成功
+                    SceneProEditEntity proEditEntity = sceneProEditService.findByProId(id);
+                    // 将返回值id更新
+                    log.info("proId 准备更新");
+                    JSONObject dataJson = proJson.getJSONObject("data");
+                    Integer proId = dataJson.getInteger("id");
+                    log.info("proId: {}", proId);
+                    proEditEntity.setProId(Long.valueOf(proId));
+                    String s = insertSceneProEditInfo(proEditEntity);
+                    if (!"0".equals(s)){
+                        log.error("发送insertSceneProEditInfo接口失败");
+                        proEntity.setDownloadStatus(3);
+                    }
+                }
+
+                proEntity.setUpdateTime(new Date());
+                log.info("proEntity: {}", proEntity.toString());
+                sceneProService.update(proEntity);
+
+            }
+
+        } else {
+            log.error("文件未打包");
+        }
+
+    }
+
+
+    private JSONObject insertSceneProInfo(SceneProEntity proEntity) throws Exception {
+        // /api/scene/insertSceneProInfo
+        String api = configConstant.REMOTE_DOMIAN + "/api/scene/insertSceneProInfo";
+
+        proEntity.setWebSite(editDomain(proEntity.getWebSite()));
+        proEntity.setThumb(editDomain(proEntity.getThumb()));
+        proEntity.setDownloadStatus(-1);
+
+        log.info("send proEntity: {}", proEntity.toString());
+        String post = HttpRequestorUtil.postJson(api, JSON.toJSONString(proEntity), "POST");
+        log.info("response proEntity: {}", post);
+        JSONObject jsonObject = JSONObject.parseObject(post);
+
+        return jsonObject;
+    }
+
+    private String insertSceneProEditInfo(SceneProEditEntity proEditEntity) throws Exception {
+        // /api/scene/insertSceneProEditInfo
+        String api = configConstant.SERVER_DOMIAN + "/api/scene/insertSceneProEditInfo";
+        log.info("send proEditEntity: {}", proEditEntity.toString());
+        String post = HttpRequestorUtil.postJson(api, JSON.toJSONString(proEditEntity), "POST");
+        log.info("response proEditEntity: {}", post);
+
+        JSONObject jsonObject = JSONObject.parseObject(post);
+
+        return jsonObject.getString("code");
+    }
+
+    // 编辑远程域名
+    private String editDomain(String url){
+//        log.info("url input: {}", url);
+        url = StringUtils.substringAfterLast(url, ":");
+        url = StringUtils.substringAfter(url, "/");
+//        log.info("url output: {}", url);
+        return configConstant.REMOTE_DOMIAN + "/" + url;
+    }
+}

+ 42 - 0
xiaoan-service/src/main/java/com/xiaoan/service/backend/listener/TaskExecutePool.java

@@ -0,0 +1,42 @@
+package com.xiaoan.service.backend.listener;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Created by owen on 2017/8/29.
+ */
+@Configuration
+@EnableAsync
+public class TaskExecutePool {
+
+    @Value("${spring.task.pool.corePoolSize}")
+    private int corePoolSize;
+    @Value("${spring.task.pool.corePoolSize}")
+    private int maxPoolSize;
+    @Value("${spring.task.pool.keepAliveSeconds}")
+    private int keepAliveSeconds;
+    @Value("${spring.task.pool.queueCapacity}")
+    private int queueCapacity;
+
+    @Bean
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(corePoolSize);
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveSeconds);
+        executor.setThreadNamePrefix("MyExecutor-");
+        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
+        // CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+}

+ 36 - 0
xiaoan-service/src/main/java/com/xiaoan/service/backend/listener/TaskService.java

@@ -0,0 +1,36 @@
+package com.xiaoan.service.backend.listener;
+
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * Created by owen on 2020/12/31 0031 12:20
+ */
+@Log4j2
+@Component
+public class TaskService {
+
+
+
+    @Autowired
+    private AsyncTask asyncTask;
+
+
+    /**
+     * 启动监听队列
+     * 因为有启动顺序的问题,需要加上线程池,而且不能在这个类里面写
+     */
+    @PostConstruct
+    public void init()  {
+        log.info("start task init");
+        asyncTask.sendFile();
+    }
+
+
+
+
+}

+ 21 - 0
xiaoan-service/src/main/java/com/xiaoan/service/backend/listener/Variable.java

@@ -0,0 +1,21 @@
+package com.xiaoan.service.backend.listener;
+
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * 多线程参数类, 全局
+ */
+public class Variable {
+
+	// 队列
+	public static ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
+//	public static BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
+	
+
+	//计算模型的线程的最大数量
+//	public static ComputerModelThread[] thread_computers = null;
+
+
+
+}

+ 11 - 146
xiaoan-web/src/main/java/com/xiaoan/web/backend/PersonalCenterController.java

@@ -25,6 +25,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.junit.Test;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import tk.mybatis.mapper.entity.Condition;
@@ -34,6 +35,10 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Created by Hb_zzZ on 2020/3/2.
@@ -50,14 +55,15 @@ public class PersonalCenterController extends BaseController {
     private SceneService sceneService;
 
     @Autowired
-    private SceneProEditService sceneProEditService;
-
-    @Autowired
     private CameraService cameraService;
 
     @Autowired
     private CameraDetailService cameraDetailService;
 
+    @Autowired
+    ApplicationContext applicationContext;
+
+
 
     /**
      * 2020-12-22
@@ -67,152 +73,11 @@ public class PersonalCenterController extends BaseController {
     @WebControllerLog(description = "个人中心-我的场景/发送文件")
     @ApiOperation("发送文件")
     @GetMapping("scene/send/{id}")
-    public ResultJson send(@PathVariable Long id) throws Exception {
-
-        SceneProEntity proEntity = sceneService.findById(id);
-
-        if (proEntity == null) {
-            return new ResultJson(MsgCode.e_COMMON_3001, MsgCode.msg_COMMON_3001);
-        }
-
-        saveLog("我的场景", "发送文件:"+ proEntity.getSceneName());
-
-        if (proEntity.getDownloadStatus() == 1) {
-            String api = REMOTE_API + "?sceneNum=" + proEntity.getNum();
-            int i = HttpRequestorUtil.fileRemote(api, SERVER_PACKAGE_RESULT + proEntity.getNum() + ".zip");
-            if (i == 200) {
-                log.info("文件发送成功");
-                proEntity.setDownloadStatus(2);
-
-                // 成功后还需要调用仕彬的两个接口
-                JSONObject proJson = insertSceneProInfo(proEntity);
-                String code = proJson.getString("code");
-                if (!"0".equals(code)) {
-                    log.error("发送insertSceneProInfo接口失败");
-                    return new ResultJson(MsgCode.e_COMMON_3001, "发送insertSceneProInfo接口失败");
-                }
-
-
-                SceneProEditEntity proEditEntity = sceneProEditService.findByProId(id);
-                // 将返回值id更新
-                log.info("proId 准备更新");
-                JSONObject dataJson = proJson.getJSONObject("data");
-                Integer proId = dataJson.getInteger("id");
-                log.info("proId: {}", proId);
-                proEditEntity.setProId(Long.valueOf(proId));
-                String s = insertSceneProEditInfo(proEditEntity);
-                if (!"0".equals(s)){
-                    log.error("发送insertSceneProEditInfo接口失败");
-                    return new ResultJson(MsgCode.e_COMMON_3001, "发送insertSceneProEditInfo接口失败");
-                }
-
-                proEntity.setUpdateTime(new Date());
-                sceneService.update(proEntity);
-
-            } else {
-                log.error("发送失败");
-                return new ResultJson(MsgCode.e_COMMON_3001, "文件发送失败");
-            }
-
-        } else {
-            return new ResultJson(MsgCode.e_COMMON_3001, "文件未打包");
-        }
-
-
-
-
-
-        return new ResultJson(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
-    }
-
-
-        private JSONObject insertSceneProInfo(SceneProEntity proEntity) throws Exception {
-        // /api/scene/insertSceneProInfo
-        String api = REMOTE_DOMIAN + "/api/scene/insertSceneProInfo";
-
-        proEntity.setWebSite(editDomain(proEntity.getWebSite()));
-        proEntity.setThumb(editDomain(proEntity.getThumb()));
-
+    public ResultJson sendFile(@PathVariable Long id) {
 
-            String post = HttpRequestorUtil.postJson(api, JSON.toJSONString(proEntity), "POST");
-            log.info("response: {}", post);
-            JSONObject jsonObject = JSONObject.parseObject(post);
-
-            return jsonObject;
+        return sceneService.sendFile(id);
     }
 
-        private String insertSceneProEditInfo(SceneProEditEntity proEditEntity) throws Exception {
-        // /api/scene/insertSceneProEditInfo
-        String api = SERVER_DOMIAN + "/api/scene/insertSceneProEditInfo";
-
-            String post = HttpRequestorUtil.postJson(api, JSON.toJSONString(proEditEntity), "POST");
-            log.info("response: {}", post);
-
-            JSONObject jsonObject = JSONObject.parseObject(post);
-
-            return jsonObject.getString("code");
-    }
-
-    // 编辑远程域名
-    private String editDomain(String url){
-        url = StringUtils.substringAfterLast(url, ":");
-        url = StringUtils.substringAfter(url, "/");
-        return REMOTE_DOMIAN + "/" + url;
-    }
-
-
-    @Test
-    public void tes(){
-     String aa = "http://192.168.0.163:8088/smobile.html?m=xa-JHoB90HUS";
-
-        String s = StringUtils.substringAfterLast(aa, ":");
-        String s1 = StringUtils.substringAfterLast(s, "/");
-        System.out.println(s);
-        System.out.println(s1);
-    }
-
-//    private String insertSceneProInfo(SceneProEntity proEntity) throws Exception {
-//        // /api/scene/insertSceneProInfo
-//        String api = SERVER_DOMIAN + "/api/scene/insertSceneProInfo";
-//
-//        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(proEntity);
-//        log.info("map: {}", stringObjectMap);
-//
-//        String post = HttpUtil.post(api, stringObjectMap);
-//        log.info("s: {}", post);
-//        JSONObject jsonObject = JSONObject.parseObject(post);
-//
-//        return jsonObject.getString("code");
-//    }
-//
-//
-//    private String insertSceneProEditInfo(SceneProEditEntity proEditEntity) throws Exception {
-//        // /api/scene/insertSceneProEditInfo
-//        String api = SERVER_DOMIAN + "/api/scene/insertSceneProEditInfo";
-//
-//        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(proEditEntity);
-//        log.info("map: {}", stringObjectMap);
-//
-//        String post = HttpUtil.post(api, stringObjectMap);
-//        log.info("s: {}", post);
-//        JSONObject jsonObject = JSONObject.parseObject(post);
-//
-//        return jsonObject.getString("code");
-//    }
-
-
-//    @RequiresPermissions("admin:scene:list")
-//    @WebControllerLog(description = "个人中心-我的场景/搜索")
-//    @ApiOperation("测试用户")
-//    @PostMapping("scene/testUser")
-//    public ResultJson testUser() throws Exception {
-//
-//        insertSceneProInfo();
-//        return new ResultJson(MsgCode.SUCCESS_CODE, MsgCode.msg_SUCCESS);
-//    }
-
-
-
 
 
     @RequiresPermissions("admin:scene:list")