在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:shurnim-storage开源软件地址:https://gitee.com/onecoder/shurnim-storage开源软件介绍:shurnim-storage目录背景介绍Shurnim (鼠尼玛),是我和我老婆曾经养过的一只仓鼠的名字。 项目介绍shurnim-storage 的设计初衷是给大家提供一个可方便扩展的云存储/网盘同步工具。分后端接口和前端UI界面两部分。 由于目前各种云存储和网盘系统层出不穷,单一工具往往支持支持某几个特定存储之间的同步,如又拍云到七牛云存储的同步工具,此时如若想同步到其他存则可能需要新的工具,给用户带来不便。shurnim-storage 正是为了解决此问题而设计的。 在shurnim-storage中,用户使用的固定的统一的后端接口。而所有云存储/网盘API的支持则是以插件的形式部署到系统中的。如此,如果用户想要一个从又拍云到Dropbox的同步工具,则只需要在原有基础上,增加Dropbox的插件,即可实现互通,方便快捷。 同时,后端统一接口的设计也考虑到界面开发的需求,可直接通过后端提供的接口开发具有上述扩展功能的云存储UI工具。 目前,后端整体框架的核心部分已经基本开发完成。只需逐步补充后端接口和插件开发接口的定义即可。但由于个人时间和能力所限,UI部分没有开发,有兴趣的同学可以一试。 使用说明获取代码
另外你也可以通过OSChina的Maven库获取依赖,或者自己编译jar包。
在项目目录执行 gradle jar 开发插件在shurnim-storage中,插件就像一块一块的积木,不但支撑着框架的功能,也是框架可扩展性的基石。开发一个插件,仅需两步:
package com.coderli.shurnim.storage.plugin;import java.io.File;import java.util.List;import com.coderli.shurnim.storage.plugin.model.Resource;/** * 各种云存储插件需要实现的通用接口 * * @author OneCoder * @date 2014年4月22日 下午9:43:41 * @website http://www.coderli.com */public interface PluginAPI { /** * 初始化接口 * * @author OneCoder * @date 2014年5月19日 下午10:47:40 */ void init(); /** * 获取子资源列表 * * @param parentPath * @return * @author OneCoder * @date 2014年4月24日 下午11:29:14 */ List<Resource> getChildResources(String parentPath); /** * 下载特定的资源 * * @param parentPath * 目录路径 * @param name * 资源名称 * @param storePath * 下载资源保存路径 * @return * @author OneCoder * @date 2014年4月24日 下午11:30:19 */ Resource downloadResource(String parentPath, String name, String storePath); /** * 创建文件夹 * * @param path * 文件夹路径 * @param auto * 是否自动创建父目录 * @return * @author OneCoder * @date 2014年5月15日 下午10:10:04 */ boolean mkdir(String path, boolean auto); /** * 上传资源 * * @param parentPath * 父目录路径 * @param name * 资源名称 * @param uploadFile * 待上传的本地文件 * @return * @author OneCoder * @date 2014年5月15日 下午10:40:13 */ boolean uploadResource(String parentPath, String name, File uploadFile);} 目前插件的接口列表仅为同步资源设计,如果想要支持更多操作(如删除,查找等),可扩展该接口定义。 package com.coderli.shurnim.storage.upyun.plugin;import java.io.File;import java.util.List;import com.coderli.shurnim.storage.plugin.AbstractPluginAPI;import com.coderli.shurnim.storage.plugin.model.Resource;import com.coderli.shurnim.storage.plugin.model.Resource.Type;import com.coderli.shurnim.storage.upyun.api.UpYun;public class UpYunPlugin extends AbstractPluginAPI { private UpYun upyun; private String username; private String password; private String bucketName; public UpYun getUpyun() { return upyun; } public void setUpyun(UpYun upyun) { this.upyun = upyun; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getBucketName() { return bucketName; } public void setBucketName(String bucketName) { this.bucketName = bucketName; } /* * (non-Javadoc) * * @see * com.coderli.shurnim.storage.plugin.PluginAPI#getChildResources(java.lang * .String) */ @Override public List<Resource> getChildResources(String parentPath) { return null; } /* * (non-Javadoc) * * @see * com.coderli.shurnim.storage.plugin.PluginAPI#downloadResource(java.lang * .String, java.lang.String, java.lang.String) */ @Override public Resource downloadResource(String parentPath, String name, String storePath) { File storeFile = new File(storePath);// if (!storeFile.exists()) {// try {// storeFile.createNewFile();// } catch (IOException e) {// e.printStackTrace();// }// } String filePath = getFullPath(parentPath, name); upyun.readDir("/api"); if (upyun.readFile(filePath, storeFile)) { Resource result = new Resource(); result.setName(name); result.setPath(parentPath); result.setType(Type.FILE); result.setLocalFile(storeFile); return result; } return null; } String getFullPath(String parentPath, String name) { if (!parentPath.endsWith(File.separator)) { parentPath = parentPath + File.separator; } return parentPath + name; } /* * (non-Javadoc) * * @see com.coderli.shurnim.storage.plugin.PluginAPI#mkdir(java.lang.String, * boolean) */ @Override public boolean mkdir(String path, boolean auto) { // TODO Auto-generated method stub return false; } /* * (non-Javadoc) * * @see * com.coderli.shurnim.storage.plugin.PluginAPI#uploadResource(java.lang * .String, java.lang.String, java.io.File) */ @Override public boolean uploadResource(String parentPath, String name, File uploadFile) { // TODO Auto-generated method stub return false; } /* * (non-Javadoc) * * @see com.coderli.shurnim.storage.plugin.AbstractPluginAPI#init() */ @Override public void init() { upyun = new UpYun(bucketName, username, password); }}
<?xml version="1.0" encoding="UTF-8"?><plugin> <id>qiniu</id> <name>七牛云存储</name> <api> <className>com.coderli.shurnim.storage.qiniu.QiniuPlugin</className> <params> <param name="access_key" displayName="ACCESS_KEY">EjREKHI_GFXbQzyrKdVhhXrIRyj3fRC1s9UmZPZO </param> <param name="secret_key" displayName="SECRET_KEY">88NofFWUvkfJ6T6rGRxlDSZOQxWkIxY2IsFIXJLX </param> <param name="bucketName" displayName="空间名">onecoder </param> </params> </api></plugin>
在使用源码工程时,插件配置文件统一放置在工程的*plugins*目录下。你也可以统一放置在任何位置。此时,在构造后端接口实例时,需要告知接口该位置。 使用ShurnimStorage接口接口介绍ShurnimStorage接口是shurinm-storage框架全局的也是唯一的接口,目前定义如 package com.coderli.shurnim.storage;import java.util.List;import java.util.Map;import com.coderli.shurnim.storage.plugin.model.Plugin;import com.coderli.shurnim.storage.plugin.model.Resource;/** * 后台模块的全局接口<br> * 通过该接口使用后台的全部功能。<br> * 使用方式:<br> * <li> * 1.先通过{@link #getSupportedPlugins()}方法获取所有支持的平台/插件列表。 <li> * 2.将列表中返回的ID传入对应的接口参数中,进行对应的平台的相关操作。<br> * 需要注意的是,不同平台的插件需要给不同的参数赋值,该值可以直接配置在配置文件中。<br> * 也可以在运行期动态赋值。(会覆盖配置文件中的值。)<br> * * 参数列表的设计,方便UI开发人员动态的根据参数列表生成可填写的控件。并给参数赋值。增强了可扩展性。 * * @author OneCoder * @date 2014年4月22日 下午9:21:58 * @website http://www.coderli.com */public interface ShurnimStorage { /** * 获取当前支持的插件列表<br> * 没有支持的插件的时候可能返回null * * @return * @author OneCoder * @date 2014年5月7日 下午8:53:25 */ List<Plugin> getSupportedPlugins(); /** * 给指定的插件的对应参数赋值<br> * 此处赋值会覆盖配置文件中的默认值 * * @param pluginId * 插件ID * @param paramsKV * 参数键值对 * @author OneCoder * @date 2014年5月9日 上午12:41:53 */ void setParamValues(String pluginId, Map<String, String> paramsKV); /** * 获取插件对应目录下的资源列表 * * @param pluginId * 插件ID * @param path * 指定路径 * @return * @author OneCoder * @date 2014年5月11日 上午8:52:00 */ List<Resource> getResources(String pluginId, String path); /** * 同步资源 * * @param fromPluginId * 待同步的插件Id * @param toPluginIds * 目标插件Id * @param resource * 待同步的资源 * @return 同步结果 * @author OneCoder * @date 2014年5月11日 上午11:41:24 */ boolean sycnResource(String fromPluginId, String toPluginId, Resource resource) throws Exception;} 当前接口实际仅包含了获取资源列表getResources和同步资源sycnResource功能,getSupportedPlugins和setParamValues实际为辅助接口,在UI开发时较为有用。 这里,sycnResource设计成插件间一对一的形式,是考虑到获取同步是否成功的结果的需求。如果您想开发一次同步到多个存储的功能,建议您重新开发您自己的接口实现类,因为默认实现会多次下次资源(每次同步后删除),造成网络资源的浪费。 接口的默认实现类是: DefaultShurnimStorageImpl 使用样例package com.coderli.shurnim.test.shurnimstorage;import org.junit.Assert;import org.junit.BeforeClass;import org.junit.Test;import com.coderli.shurnim.storage.DefaultShurnimStorageImpl;import com.coderli.shurnim.storage.ShurnimStorage;import com.coderli.shurnim.storage.plugin.model.Resource;import com.coderli.shurnim.storage.plugin.model.Resource.Type;/** * 全局接口测试类<br> * 时间有限,目前仅作整体接口测试。细粒度的单元测试,随开发补充。 * * @author OneCoder * @date 2014年5月19日 下午10:50:27 * @website http://www.coderli.com */public class ShurnimStorageTest { private static ShurnimStorage shurnim; @BeforeClass public static void init() { shurnim = new DefaultShurnimStorageImpl( "/Users/apple/git/shurnim-storage-for-UPYUN/plugins"); } @Test public void testSycnResource() { Resource syncResource = new Resource(); syncResource.setPath("/api"); syncResource.setName("api.html"); syncResource.setType(Type.FILE); try { Assert.assertTrue(shurnim.sycnResource("upyun", "qiniu", syncResource)); } catch (Exception e) { e.printStackTrace(); } }} 其他时间仓促,功能简陋,望您包涵。OneCoder(Blog:http://www.coderli.com)特别希望看到该项目对您哪怕一点点的帮助。任意的意见和建议,欢迎随意与我沟通,联系方式:
|
请发表评论