爲項目編寫Readme.MD文件

瞭解一個項目,恐怕首先都是經過其Readme文件瞭解信息。若是你覺得Readme文件都是隨便寫寫的那你就錯了。github,oschina git gitcafe的代碼託管平臺上的項目的Readme.MD文件都是有其特有的語法的。稱之爲Markdown語法。基本規則以下:html

Markdown 語法速查表
1 標題與文字格式
標題
# 這是 H1 <一級標題>
## 這是 H2 <二級標題>
###### 這是 H6 <六級標題>
文字格式
**這是文字粗體格式**
*這是文字斜體格式*
~~在文字上添加刪除線~~
2 列表
無序列表
* 項目1
* 項目2
* 項目3
有序列表
1. 項目1
2. 項目2
3. 項目3
   * 項目1
   * 項目2
3 其它
圖片
![圖片名稱](http://gitcafe.com/image.png)
連接
[連接名稱](http://gitcafe.com)
引用
> 第一行引用文字
> 第二行引用文字
水平線
***
代碼
`<hello world>`
代碼塊高亮
「`ruby
  def add(a, b)
    return a + b
  end
「`
表格
  表頭  | 表頭
  ————- | ————-
 單元格內容  | 單元格內容
 單元格內容l  | 單元格內容前端

若是直接記語法,那彷佛困難了些。這裏OneCoder推薦兩個Markdown的編輯器。java

在線編輯器:stackedit
網址:https://stackedit.io/git

Mac下離線編輯器Mou
下載地址:http://mouapp.com/github


OneCoder這裏使用的是後者爲本身的shurnim-storage項目寫Readme。至於這個項目是什麼,見Readme文檔,OneCoder也會在另外的博文作一些補充說明。成品Readme以下:web

# shurnim-storage後端

![Shurnim icon](http://onecoder.qiniudn.com/8wuliao/DLPii2Jx/rEBO.jpg)api

## 目錄
* [背景介紹](#背景介紹)
* [項目介紹](#項目介紹)
* [使用說明](#使用說明)
  * [獲取代碼](#獲取代碼)
  * [開發插件](#開發插件)
  * [使用ShurnimStorage接口](#使用ShurnimStorage接口)
       * [接口介紹](#接口介紹)
       * [使用樣例](#使用樣例)
* [其餘](#其餘)七牛雲存儲

<a name="背景介紹"></a>
## 背景介紹ruby

*Shurnim*,是我和我老婆曾經養過的一隻倉鼠的名字。<br/>
*shurnim-storage*,是一個插件式雲存儲/網盤同步管理工具。是在參加又拍雲開發大賽的過程當中設計並開發。

<a name="項目介紹"></a>
## 項目介紹

*shurnim-storage* 的設計初衷是給你們提供一個可方便擴展的雲存儲/網盤同步工具。分後端接口和前端UI界面兩部分。<br>

因爲目前各類雲存儲和網盤系統層出不窮,單一工具每每支持支持某幾個特定存儲之間的同步,如**又拍雲**到**七牛雲存儲**的同步工具,此時如若想同步到其餘存則可能須要新的工具,給用戶帶來不便。*shurnim-storage*  正是爲了解決此問題而設計的。

在*shurnim-storage*中,用戶使用的固定的統一的後端接口。而全部雲存儲/網盤API的支持則是以插件的形式部署到系統中的。如此,若是用戶想要一個從**又拍雲**到**Dropbox**的同步工具,則只須要在原有基礎上,增長**Dropbox**的插件,便可實現互通,方便快捷。<br/>

同時,後端統一接口的設計也考慮到界面開發的需求,可直接經過後端提供的接口開發具備上述擴展功能的雲存儲UI工具。<br>

目前,後端總體框架的核心部分已經基本開發完成。只需逐步補充後端接口和插件開發接口的定義便可。但因爲我的時間和能力所限,UI部分沒有開發,有興趣的同窗能夠一試。

<a name="使用說明"></a>
## 使用說明

<a name="獲取代碼"></a>
### 獲取代碼

* gitcafe項目主頁: <https://gitcafe.com/onecoder/shurnim-storage-for-UPYUN>
* OSChina項目主頁: <http://git.oschina.net/onecoder/shurnim-storage><br>
OSChina上的會持續更新。

另外你也能夠經過OSChina的Maven庫獲取依賴,或者本身編譯jar包。

* maven

     1. 加入OSC倉庫
   
                    <repositories>
                      <repository>
                           <id>nexus</id>
                           <name>local private nexus</name>
                           <url>http://maven.oschina.net/content/groups/public/</url>
                           <releases>
                                <enabled>true</enabled>
                           </releases>
                           <snapshots>
                                <enabled>false</enabled>
                           </snapshots>
                      </repository>
                 </repositories>

     2. 加入依賴
   
               <dependency>
                 <groupId>com.coderli</groupId>
                 <artifactId>shurnim-storage</artifactId>
                  <version>0.1-alpha</version>
               </dependency>
* Gradle 編譯Jar

在項目目錄執行
   
     gradle jar
   
<a name="開發插件"></a>
### 開發插件

在*shurnim-storage*中,插件就像一塊一塊的積木,不但支撐着框架的功能,也是框架可擴展性的基石。開發一個插件,僅需兩步:

1. 實現PluginAPI接口

「`
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);
}
「`

目前插件的接口列表僅爲同步資源設計,若是想要支持更多操做(如刪除,查找等),可擴展該接口定義。<br/><br/>
接口中,全部的參數和返回值均爲*shurnim-storage*框架中定義的通用模型。所以,您在開發插件過程當中須要將特定SDK中的模型轉換成接口中提供的模型。<br/><br/>
插件實現類只要與*shurnim-storage*工程在同一個classpath便可使用。您既能夠直接在源碼工程中開發插件,就如工程裏提供的*upyun*和*qiniu*插件同樣,也能夠做爲獨立工程開發,打成jar,放置在同一個classpath下。<br/><br/>
*upyun*插件樣例(功能不完整):

「`  
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);
     }

}
「`


2. 編寫插件配置文件

「`
<?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>
「`
   * **id** 爲該插件在*shurnim-storage*框架下的惟一標識,不可重複,必填。
    * **name** 爲顯示值,爲UI開發提供可供顯示的有語義的值。
    * **className** 爲插件接口實現類的完整路徑。必填
    * **params/param** 爲插件須要用戶配置的參數列表。其中
         * *name* 表明參數名,須要與接口實現類中的參數名嚴格一致,且必須有相應的set方法的格式要求嚴格,即set+首字母大寫的參數名。例如:setAccess_key(String arg); 目前只支持*String*類型的參數。
         * *displayName* 爲參數顯示名,一樣是爲了UI開發的考慮,方便用戶開發出可根據參數列表動態顯示的UI界面。
         * 參數的值能夠直接配置在配置文件中,也能夠在運行期動態賦值。直接配置值,對於直接使用後端接口來講較爲方便。對於UI開發來講,運行期動態賦值更爲合理。<br/></br>

     在使用源碼工程時,插件配置文件統一放置在工程的*plugins*目錄下。你也能夠統一放置在任何位置。此時,在構造後端接口實例時,須要告知接口該位置。
   
<a name="使用ShurnimStorage接口"></a>
### 使用*ShurnimStorage*接口

<a name="接口介紹"></a>
#### 接口介紹

**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開發時較爲有用。<br/><br/>
一樣,您也能夠擴展開發該接口增長更多的您喜歡的特性。例如,同時刪除給定存儲上的文件。固然,這須要插件接口的配合支持。<br/><br/>

這裏,*sycnResource*設計成插件間一對一的形式,是考慮到獲取同步是否成功的結果的需求。若是您想開發一次同步到多個存儲的功能,建議您從新開發您本身的接口實現類,由於默認實現會屢次下次資源(每次同步後刪除),形成網絡資源的浪費。

接口的默認實現類是: **DefaultShurnimStorageImpl**

<a name="使用樣例"></a>
#### 使用樣例
「`      
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();
          }
     }
}
「`
<a name="其餘"></a>
## 其餘

時間倉促,功能簡陋,望您包涵。OneCoder(Blog:[http://www.coderli.com](http://www.coderli.com))特別但願看到該項目對您哪怕一點點的幫助。任意的意見和建議,歡迎隨意與我溝通,聯繫方式:

* Email: <wushikezuo@gmail.com>
* QQ:57959968
* Blog:[OneCoder](http://www.coderli.com)

項目的Bug和改進點,可在OSChina上以issue的方式直接提交給我。

效果預覽:

 

如非特別註明,本站內容均爲OneCoder原創,轉載請務必註明做者和原始出處。
本文地址:http://www.coderli.com/write-readme-for-your-project

相關文章
相關標籤/搜索