瞭解一個項目,恐怕首先都是經過其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