Ver código fonte

add plugin doc

AE86 3 anos atrás
pai
commit
12a885391f

+ 7 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/PluginService.java

@@ -25,6 +25,13 @@ public interface PluginService {
      */
     String getPluginPath();
 
+    /**
+     * 获取开发包路径
+     *
+     * @return
+     */
+    String getLibraryPath();
+
     /**
      * 加载插件
      */

+ 5 - 0
dbsyncer-biz/src/main/java/org/dbsyncer/biz/impl/PluginServiceImpl.java

@@ -37,6 +37,11 @@ public class PluginServiceImpl implements PluginService {
         return manager.getPluginPath();
     }
 
+    @Override
+    public String getLibraryPath() {
+        return manager.getLibraryPath();
+    }
+
     @Override
     public void loadPlugins() {
         manager.loadPlugins();

+ 1 - 1
dbsyncer-common/src/main/java/org/dbsyncer/common/spi/ConvertService.java

@@ -24,7 +24,7 @@ public interface ConvertService {
     /**
      * 增量同步
      *
-     * @param event  事件(新增INSERT/修改UPDATE/删除DELETE)
+     * @param event  事件(INSERT/UPDATE/DELETE)
      * @param source 数据源
      * @param target 目标源
      */

+ 2 - 0
dbsyncer-manager/src/main/java/org/dbsyncer/manager/Manager.java

@@ -128,5 +128,7 @@ public interface Manager extends Executor {
 
     String getPluginPath();
 
+    String getLibraryPath();
+
     void loadPlugins();
 }

+ 5 - 0
dbsyncer-manager/src/main/java/org/dbsyncer/manager/ManagerFactory.java

@@ -300,6 +300,11 @@ public class ManagerFactory implements Manager, ApplicationListener<ClosedEvent>
         return pluginFactory.getPluginPath();
     }
 
+    @Override
+    public String getLibraryPath() {
+        return pluginFactory.getLibraryPath();
+    }
+
     @Override
     public void loadPlugins() {
         pluginFactory.loadPlugins();

+ 10 - 0
dbsyncer-plugin/src/main/java/org/dbsyncer/plugin/PluginFactory.java

@@ -32,6 +32,12 @@ public class PluginFactory {
     private final String PLUGIN_PATH = new StringBuilder(System.getProperty("user.dir")).append(File.separatorChar).append("plugins")
             .append(File.separatorChar).toString();
 
+    /**
+     * 依赖路径dbsyncer/lib/
+     */
+    private final String LIBRARY_PATH = new StringBuilder(System.getProperty("user.dir")).append(File.separatorChar).append("lib")
+            .append(File.separatorChar).toString();
+
     private final List<Plugin> plugins = new LinkedList<>();
 
     private final Map<String, ConvertService> service = new ConcurrentHashMap<>();
@@ -55,6 +61,10 @@ public class PluginFactory {
         return PLUGIN_PATH;
     }
 
+    public String getLibraryPath() {
+        return LIBRARY_PATH;
+    }
+
     public List<Plugin> getPluginAll() {
         return plugins;
     }

+ 41 - 2
dbsyncer-web/src/main/java/org/dbsyncer/web/controller/upload/UploadController.java

@@ -1,18 +1,23 @@
 package org.dbsyncer.web.controller.upload;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.dbsyncer.biz.PluginService;
 import org.dbsyncer.biz.vo.RestResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.File;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
 
 @Controller
 @RequestMapping("/upload")
@@ -20,16 +25,23 @@ public class UploadController {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
+    /**
+     * 版本号
+     */
+    @Value(value = "${info.app.version}")
+    private String version;
+
     @RequestMapping("")
     public String index(ModelMap model) {
         model.put("plugins", pluginService.getPluginAll());
+        model.put("version", version);
         return "upload/upload";
     }
 
     @Autowired
     private PluginService pluginService;
 
-    @RequestMapping(value = "/upload")
+    @PostMapping(value = "/upload")
     @ResponseBody
     public RestResult upload(MultipartFile[] files) {
         try {
@@ -55,4 +67,31 @@ public class UploadController {
         }
     }
 
+    @GetMapping("/download")
+    public void download(HttpServletResponse response) {
+        String fileName = String.format("dbsyncer-common-%s.jar", version);
+        response.setHeader("content-type", "application/octet-stream");
+        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
+        response.setContentType("application/octet-stream");
+        BufferedInputStream bis = null;
+        OutputStream outputStream = null;
+        try {
+            outputStream = response.getOutputStream();
+            String filePath = pluginService.getLibraryPath();
+            bis = new BufferedInputStream(new FileInputStream(new File(filePath + fileName)));
+            byte[] buff = new byte[2048];
+            int read = bis.read(buff);
+            while (read != -1) {
+                outputStream.write(buff, 0, buff.length);
+                outputStream.flush();
+                read = bis.read(buff);
+            }
+        } catch (IOException e) {
+            logger.error(e.getMessage());
+        } finally {
+            IOUtils.closeQuietly(bis);
+            IOUtils.closeQuietly(outputStream);
+        }
+    }
+
 }

+ 1 - 1
dbsyncer-web/src/main/resources/application.properties

@@ -24,7 +24,7 @@ management.endpoints.web.exposure.include=*
 management.endpoint.health.show-details=always
 info.app.name=DBSyncer
 info.app.version=1.0.9-Alpha
-info.app.copyright=&copy;2021 ${info.app.name}(${info.app.version})<br />Designed By <a href='https://gitee.com/ghi/dbsyncer' target='_blank' >AE86</a>
+info.app.copyright=&copy;2021 ${info.app.name}(${info.app.version})<footer>Designed By <a href='https://gitee.com/ghi/dbsyncer' target='_blank' >AE86</a></footer>
 
 #All < Trace < Debug < Info < Warn < Error < Fatal < OFF
 logging.level.root=info

+ 127 - 33
dbsyncer-web/src/main/resources/public/upload/upload.html

@@ -2,50 +2,140 @@
 <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
 
-<div class="container">
-    <form id="uploadForm" class="form-horizontal" role="form">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-md-12">
+            <!-- 插件文档 -->
+            <div class="col-md-5">
+                <blockquote>
+                    <p>插件有什么用?</p>
+                    <small class="text-muted">插件是一种可扩展全量同步和增量同步实现数据转换的技术方式。通过插件可以接收同步数据,自定义同步到目标源的行数据,也能消费数据并实现更多业务场景。</small>
+                </blockquote>
 
-        <div class="page-header">
-            <h3>上传插件 <small>只支持 "jar" 的文件扩展名.</small></h3>
-        </div>
+                <p>如何开发插件?</p>
+                <ol>
+                    <li>新建java或maven工程,比如app</li>
+                    <li>导入开发包:
+                        <ul>
+                            <li>方式1:导入jar <a onClick="downLoad()" href="javascript:;" title="下载开发包">dbsyncer-common-[[${version}]].jar</a></li>
+                            <li>方式2:引入pom(需要安装到本地)
+                                <pre>&lt;dependency&gt;<br/>&nbsp;&nbsp;&lt;groupId>org.ghi&lt;/groupId&gt;<br/>&nbsp;&nbsp;&lt;artifactId>dbsyncer-common&lt;/artifactId&gt;<br/>&nbsp;&nbsp;&lt;version>[[${version}]]&lt;/version&gt;<br/>&lt;/dependency&gt;</pre>
+                            </li>
+                        </ul>
+                    </li>
+                    <li>
+                        <simple>新建一个类,比如MyPlugin,实现接口ConvertService方法</simple>
+                        <pre>
+package org.test;
+
+import java.util.List;
+import java.util.Map;
+
+public class MyPlugin implements ConvertService{
+
+    /**
+    * 全量同步
+    *
+    * @param source 数据源
+    * @param target 目标源
+    */
+    @Override
+    public void convert(List&lt;Map&gt; source, List&lt;Map&gt; target) {
+        // TODO 消费或处理数据
+    }
+
+    /**
+    * 增量同步
+    *
+    * @param event  事件(INSERT/UPDATE/DELETE)
+    * @param source 数据源
+    * @param target 目标源
+    */
+    @Override
+    public void convert(String event, Map source, Map target) {
+        // TODO 消费或处理数据
+    }
+
+    /**
+    * 重写方法:设置版本号
+    *
+    * @return
+    */
+    @Override
+    public String getVersion() {
+        return "1.0.0";
+    }
 
-        <div class="form-group">
-            <div class="file-loading">
-                <input id="filePlugin" type="file" name="files" multiple="multiple" />
+    /**
+    * 重写方法:设置插件名称
+    *
+    * @return
+    */
+    @Override
+    public String getName() {
+        return "MyPlugin";
+    }
+}
+                        </pre>
+                    </li>
+                    <li>
+                        <simple>/META-INF/新建services文件夹,并在services下新建一个文件,命名为org.dbsyncer.common.spi.ConvertService,文件写入实现类路径org.test.MyPlugin,如果有多个实现就换行再写入</simple>
+                        <p><img th:src="@{'/img/plugin/spi.png'}"></p>
+                    </li>
+                    <li>
+                        <simple>打包jar</simple>
+                        <p><img th:src="@{'/img/plugin/jar.png'}"></p>
+                    </li>
+                </ol>
             </div>
-        </div>
 
-        <div class="form-group">
-            <table class="table table-hover">
-                <caption>插件列表([[${plugins?.size()} ?: 0]])</caption>
-                <thead>
-                <tr>
-                    <th>名称</th>
-                    <th>类名</th>
-                    <th>版本</th>
-                    <th>文件</th>
-                    <th>操作</th>
-                </tr>
-                </thead>
-                <tbody id="pluginList">
-                <tr th:id="${p?.name}" th:each="p,state : ${plugins}">
-                    <td th:text="${p?.name}"/>
-                    <td th:text="${p?.className}"/>
-                    <td th:text="${p?.version}"/>
-                    <td th:text="${p?.fileName}"/>
-                    <td><a th:id="${p?.name}" class='fa fa-remove fa-2x pluginDelete dbsyncer_pointer' title='暂不支持' aria-disabled="true"></a></td>
-                </tr>
-                </tbody>
-            </table>
+            <!-- 插件列表 -->
+            <div class="col-md-7">
+                <form id="uploadForm" class="form-horizontal" role="form">
+                    <div class="page-header">
+                        <h3>上传插件 <small>只支持 "jar" 的文件扩展名.</small></h3>
+                    </div>
+
+                    <div class="form-group">
+                        <div class="file-loading">
+                            <input id="filePlugin" type="file" name="files" multiple="multiple" />
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <table class="table table-hover">
+                            <caption>插件列表([[${plugins?.size()} ?: 0]])</caption>
+                            <thead>
+                            <tr>
+                                <th>名称</th>
+                                <th>类名</th>
+                                <th>版本</th>
+                                <th>文件</th>
+                                <th>操作</th>
+                            </tr>
+                            </thead>
+                            <tbody id="pluginList">
+                            <tr th:id="${p?.name}" th:each="p,state : ${plugins}">
+                                <td th:text="${p?.name}"/>
+                                <td th:text="${p?.className}"/>
+                                <td th:text="${p?.version}"/>
+                                <td th:text="${p?.fileName}"/>
+                                <td><a th:id="${p?.name}" class='fa fa-remove fa-2x pluginDelete dbsyncer_pointer' title='暂不支持' aria-disabled="true"></a></td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </form>
+            </div>
         </div>
-    </form>
+    </div>
 </div>
 
 <script type="text/javascript">
     $("#filePlugin").fileinput({
         theme: 'fas',
         language: 'zh',
-        uploadUrl: '/upload/upload',
+        uploadUrl: $basePath + '/upload/upload',
         enctype: 'multipart/form-data',
         removeFromPreviewOnError:true, //当选择的文件不符合规则时,例如不是指定后缀文件、大小超出配置等,选择的文件不会出现在预览框中,只会显示错误信息
         allowedFileExtensions: ['jar'],
@@ -60,5 +150,9 @@
         }
         doLoader("/upload");
     });
+
+    function downLoad(){
+        window.open($basePath + "/upload/download");
+    }
 </script>
 </html>

BIN
dbsyncer-web/src/main/resources/static/img/plugin/jar.png


BIN
dbsyncer-web/src/main/resources/static/img/plugin/spi.png