Просмотр исходного кода

开发组件热更新问题处理

wuxw лет назад: 6
Родитель
Сommit
59ce81c19b

+ 1 - 1
WebService/src/main/resources/components/pageFramePackage/login/login.html

@@ -2,7 +2,7 @@
     <div>
         <h1 class="logo-name">HC</h1>
     </div>
-    <h3>请登录</h3>
+    <h3>请登录123</h3>
     <p style="color: red;">{{loginInfo.errorInfo}}</p>
     <div class="m-t" role="form">
         <div class="form-group">

+ 1 - 0
WebService/src/main/resources/java110.properties

@@ -1,3 +1,4 @@
 java110.mappingPath=
+java110.autoReloadComponent=true
 
 

+ 10 - 0
java110-config/src/main/java/com/java110/config/properties/code/Java110Properties.java

@@ -18,6 +18,8 @@ public class Java110Properties {
 
     private String wxAppSecret;
 
+    private boolean autoReloadComponent = false;
+
     public String getMappingPath() {
         return mappingPath;
     }
@@ -41,4 +43,12 @@ public class Java110Properties {
     public void setWxAppSecret(String wxAppSecret) {
         this.wxAppSecret = wxAppSecret;
     }
+
+    public boolean getAutoReloadComponent() {
+        return autoReloadComponent;
+    }
+
+    public void setAutoReloadComponent(boolean autoReloadComponent) {
+        this.autoReloadComponent = autoReloadComponent;
+    }
 }

+ 13 - 0
java110-front/src/main/java/com/java110/front/core/VueComponentTemplate.java

@@ -1,5 +1,6 @@
 package com.java110.front.core;
 
+import com.java110.front.listener.ReloadComponentFileListenerFactory;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.util.StringUtils;
 
@@ -51,6 +52,9 @@ public class VueComponentTemplate extends PackageScanner {
         vueComponentTemplate.packageScanner(scanPath, COMPONENT_JS);
         vueComponentTemplate.packageScanner(scanPath, COMPONENT_HTML);
         vueComponentTemplate.packageScanner(scanPath, COMPONENT_CSS);
+
+        //启动 组件热加载功能
+        ReloadComponentFileListenerFactory.startReloadComponentFileListener();
     }
 
 
@@ -111,4 +115,13 @@ public class VueComponentTemplate extends PackageScanner {
             }
         }
     }
+
+    /**
+     * 刷入 组件内容
+     * @param componentKey
+     * @param componentContext
+     */
+    public static void refreshComponent(String componentKey,String componentContext){
+        componentTemplate.put(componentKey, componentContext);
+    }
 }

+ 141 - 0
java110-front/src/main/java/com/java110/front/listener/ReloadComponentFileListener.java

@@ -0,0 +1,141 @@
+package com.java110.front.listener;
+
+import com.java110.front.core.PackageScanner;
+import com.java110.front.core.VueComponentTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.util.StringUtils;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ReloadComponentFileListener extends PackageScanner implements Runnable {
+
+    private Logger logger = LoggerFactory.getLogger(ReloadComponentFileListener.class);
+
+    /**
+     * 默认扫描组件路径
+     */
+    private static final String DEFAULT_COMPONENT_PACKAGE_PATH = "components";
+
+
+    /**
+     * js 文件
+     */
+    public static final String COMPONENT_JS = "js";
+
+    /**
+     * css 文件
+     */
+    public static final String COMPONENT_CSS = "css";
+
+    /**
+     * html 文件
+     */
+    public static final String COMPONENT_HTML = "html";
+
+
+    private static final Map<String,Long> commentInfo = new HashMap<String,Long>();
+
+    /**
+     * 心跳加载组件信息 标志 true 为定时加载组件信息
+     */
+    private static boolean RELOAD_COMPONENT_FLAG = false;
+
+    /**
+     * 心跳时间,默认为5秒
+     */
+    private static long HEARTBEAT_TIME = 5 * 1000;
+
+    public ReloadComponentFileListener() {
+
+    }
+
+    public ReloadComponentFileListener(boolean flag) {
+        RELOAD_COMPONENT_FLAG = flag;
+    }
+
+    public ReloadComponentFileListener(boolean flag, long time) {
+        RELOAD_COMPONENT_FLAG = flag;
+        HEARTBEAT_TIME = time;
+    }
+
+    @Override
+    public void run() {
+        while (RELOAD_COMPONENT_FLAG) {
+            try {
+                reloadComponent();
+                Thread.sleep(HEARTBEAT_TIME);//线程休息
+            } catch (Throwable e) {
+                logger.error("加载组件失败:", e);
+            }
+        }
+
+    }
+
+    private void reloadComponent() {
+        logger.debug("开始扫描是否有组件添加或修改");
+        VueComponentTemplate vueComponentTemplate = new VueComponentTemplate();
+        vueComponentTemplate.packageScanner(DEFAULT_COMPONENT_PACKAGE_PATH, COMPONENT_JS);
+        vueComponentTemplate.packageScanner(DEFAULT_COMPONENT_PACKAGE_PATH, COMPONENT_HTML);
+        vueComponentTemplate.packageScanner(DEFAULT_COMPONENT_PACKAGE_PATH, COMPONENT_CSS);
+        logger.debug("扫描完成是否有组件添加或修改");
+
+    }
+
+    @Override
+    protected void handleResource(String filePath) {
+
+        File componentFile = new File(filePath);
+        Long lastModified = componentFile.lastModified();
+        if(!commentInfo.containsKey(componentFile.getName())){
+            commentInfo.put(componentFile.getName(), lastModified);
+            reloadComponentContext(filePath);
+        }
+        Long prevModified = commentInfo.get(componentFile.getName());
+        if (lastModified > prevModified) {
+            reloadComponentContext(filePath);
+            commentInfo.put(componentFile.getName(), lastModified);
+        }
+    }
+
+    private void reloadComponentContext(String filePath){
+        Reader reader = null;
+        String sb = "";
+        try {
+            InputStream inputStream = new ClassPathResource(filePath).getInputStream();
+            //InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(File.separator + filePath);
+            reader = new InputStreamReader(inputStream, "UTF-8");
+            int tempChar;
+            StringBuffer b = new StringBuffer();
+            while ((tempChar = reader.read()) != -1) {
+                b.append((char) tempChar);
+            }
+            sb = b.toString();
+            if (StringUtils.isEmpty(sb)) {
+                return;
+            }
+            String componentKey = "";
+            //这里在window 读取jar包中文件时,也是 / 但是直接启动时 为\这个 所以不能用 File.separator
+            if (filePath.contains("/")) {
+                componentKey = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length());
+            } else {
+                componentKey = filePath.substring(filePath.lastIndexOf("\\") + 1, filePath.length());
+            }
+            VueComponentTemplate.refreshComponent(componentKey, sb);
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}

+ 25 - 0
java110-front/src/main/java/com/java110/front/listener/ReloadComponentFileListenerFactory.java

@@ -0,0 +1,25 @@
+package com.java110.front.listener;
+
+import com.java110.config.properties.code.Java110Properties;
+import com.java110.utils.factory.ApplicationContextFactory;
+
+/**
+ * 只用于开发时组件 自动加载,无需自动启动服务去加载组件
+ * 可能会影响性能
+ * add by wuxw 2019-11-21
+ */
+public class ReloadComponentFileListenerFactory {
+
+    public static void startReloadComponentFileListener() {
+        Java110Properties java110Properties = ApplicationContextFactory.getBean("java110Properties", Java110Properties.class);
+        boolean autoReloadComponent = java110Properties.getAutoReloadComponent();
+        //如果不是开发环境则不启用 自动加载组件功能
+        if (!"dev".equals(ApplicationContextFactory.getActiveProfile())) {
+            autoReloadComponent = false;
+        }
+        ReloadComponentFileListener reloadComponentFileListener = new ReloadComponentFileListener(autoReloadComponent);
+        Thread componentThread = new Thread(reloadComponentFileListener, "thread-ReloadComponentFileListener");
+        componentThread.start();
+    }
+
+}

+ 16 - 0
java110-utils/src/main/java/com/java110/utils/factory/ApplicationContextFactory.java

@@ -3,6 +3,8 @@ package com.java110.utils.factory;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 
+import java.util.Locale;
+
 /**
  * Created by wuxw on 2017/4/25.
  */
@@ -32,4 +34,18 @@ public class ApplicationContextFactory {
 
         return null;
     }
+
+
+    // 国际化使用
+    public static String getMessage(String key) {
+        return applicationContext.getMessage(key, null, Locale.getDefault());
+    }
+
+
+    /// 获取当前环境
+    public static String getActiveProfile() {
+        return applicationContext.getEnvironment().getActiveProfiles()[0];
+    }
+
+
 }