FastDFS
- 1、分布式檔案系統
- 1.1 FastDFS簡介
- 1.2 FastDFS整體架構
- 1.3 FastDFS的存盤策略
- 1.4 FastDFS的上傳程序
- 1.5 FastDFS的檔案同步
- 1.6 FastDFS的檔案下載
- 2、FastDFS環境搭建
- 2.1 FastDFS安裝
- 2.1.1 **安裝前的準備**
- (1) 檢查Linux上是否安裝了 gcc、libevent、libevent-devel
- (2) 如果沒有安裝,則需進行安裝
- 2.1.2 **安裝 libfastcommon 庫**
- (1) 將下載好的libfastcommon檔案上傳到Linux(/home/)
- (2) 解壓下載下來的tar.gz壓縮包到當前目錄
- (3) 切換到解壓后的libfastcommon目錄
- (4) 執行make腳本進行編譯
- (5) 執行make install進行安裝
- 2.1.3 安裝FastDFS
- (1) 將下載好的FastDFS檔案上傳到Linux(/home/)
- (2) 解壓下載下來的tar.gz壓縮包到當前目錄
- (3) 切換到解壓后FastDFS的目錄
- (4) 執行make腳本進行編譯
- (5) 執行make install進行安裝
- (6) 查看安裝后的效果
- A、 查看FastDFS相關的可執行程式
- B、 查看FastDFS的組態檔
- (7) 另外注意需要把解壓后的fastdfs-5.11/conf目錄下的兩個檔案拷貝到/etc/fdfs/ ,否則后續會有很多奇怪問題不好解決
- 2.2 FastDFS組態檔詳解
- 1. 去掉/etc/fdfs/目錄下FastDFS組態檔的后綴名
- 2. 修改tracker.conf檔案
- 3. 修改storage.conf檔案
- 4. 在Linux服務器上創建上面指定的目錄
- 5. 然后啟動FastDFS
- 2.3 FastDFS啟動
- 1. 啟動FastDFS的tracker服務
- 2. 啟動FastDFS的storage服務
- 3. 查看啟動行程
- 4. 查看storage是否已經注冊到了tracker下
- 5. 首次啟動storage后,會在配置的路徑下創建存盤檔案的目錄
- 2.4 FastDFS重啟與FastDFS關閉
- 2.4.1 FastDFS重啟
- 2.4.2 FastDFS關閉
- 2.5 FastDFS測驗
- 2.5.1 測驗檔案上傳
- 2.5.2 測驗檔案洗掉
- 3、分布式檔案系統FastDFS的HTTP訪問
- 3.1 前期準備作業
- 3.2 安裝Nginx并且添加fastDFS模塊
- 1. 將Nginx的tar包上傳到Linux上
- 2. 解壓上傳的Nginx檔案
- 3. 切換至解壓后的Nginx主目錄,執行配置操作
- 4. 執行命令進行編譯
- 5. 執行命令進行安裝
- 6. 以上安裝Nginx的FastDFS擴展模塊注意事項
- 7. FastDFS擴展模塊執行流程
- 3.3 FastDFS的Nginx訪問配置
- 1. 修改mod_fastdfs.conf組態檔
- 2. 在/opt/fastdfs/目錄下創建nginx_mod目錄
- 3. 配置Nginx的組態檔
- 3.4 FastDFS的Nginx訪問啟動與測驗
- 1. 啟動帶有Fastdfs模塊的Nginx
- 2. 重啟或啟動FastDFS服務行程
- 3. 上傳一個檔案進行測驗驗證
- 4. 在瀏覽器訪問上傳的檔案
- 5. 擴展
- 4、FastDFS分布式檔案系統Java客戶端
- 4.1 FastDFS檔案系統的Java客戶端
- 1. 下載官方的源代碼
- 2. 解壓
- 3. 采用maven命令編譯成jar安裝到本地maven庫
- 4. 在Java程式中使用它提供的API來訪問FastDFS檔案系統
- 4.2 FastDFS檔案上傳功能實作
- 4.2.1 **需求**
- 4.2.2 實作步驟
- 4.3 FastDFS檔案上傳功能封裝
- 4.3.1 需求
- 4.3.2 實作步驟
- 5、FastDFS在web專案中的應用
- 1. 資料庫環境搭建
- ⒉ 開發環境搭建
- 6、FastDFS分布式檔案系統集群
- 6.1 架構圖
- 6.2 環境搭建步驟
- 1. 安裝6個迷你版的Linux
- 2. 在Xshell中創建6個連接,分別連向不同的Linux
- 3. 為迷你版的Linux安裝常用工具庫
- 4. 按照課件上安裝FastDFS的步驟在6個服務器節點安裝FastDFS
- 5. 配置兩個tracker server服務器
- 6. 配置四個storage server服務器
- 7. 部署Http訪問FastDFS上的檔案
1、分布式檔案系統
1.1 FastDFS簡介
-
分布式檔案系統 (Distributed File System) 是一個軟體/軟體服務器,這個軟體可以用來管理檔案,但這個軟體所管理的檔案通常不是在一個服務器節點上,而是在多個服務器節點上,這些服務器節點通過網路相連構成一個龐大的檔案存盤服務器集群,這些服務器都用于存盤檔案資源,通過分布式檔案系統來管理這些服務器上的檔案,
-
FastDFS 是一個開源的高性能分布式檔案系統(DFS), 它的主要功能包括:檔案存盤,檔案同步和檔案訪問,以及高容量和負載平衡,主要解決了海量資料存盤問題,特別適合以中小檔案(建議范圍:4KB < file_size <500MB)為載體的在線服務,
-
FastDFS是一個開源的輕量級分布式檔案系統,為互聯網應用量身定做,簡單、靈活、高效,采用C語言開發,由阿里巴巴開發并開源,
-
FastDFS對檔案進行管理,功能包括:檔案存盤、檔案同步、檔案訪問(檔案上傳、檔案下載、檔案洗掉)等,解決了大容量檔案存盤的問題,特別適合以檔案為載體的在線服務,如相冊網站、檔案網站、圖片網站、視頻網站等等,
-
FastDFS充分考慮了冗余備份、線性擴容等機制,并注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的檔案服務器集群提供檔案上傳、下載等服務,
-
FastDFS 系統有三個角色:跟蹤服務器(Tracker Server)、存盤服務器(Storage Server)和客戶端(Client),
Tracker Server:跟蹤服務器,主要做調度作業,起到均衡的作用;負責管理所有的 storage server和 group,每個 storage 在啟動后會連接 Tracker,告知自己所屬 group 等資訊,并保持周期性心跳,Storage Server:存盤服務器,主要提供容量和備份服務;以 group 為單位,每個 group 內可以有多臺 storage server,資料互為備份,Client:客戶端,上傳下載資料的服務器,也就是我們自己的專案所部署在的服務器,

- 常見的分布式檔案系統有:FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS等,



1.2 FastDFS整體架構
FastDFS代碼托管在github上:https://github.com/happyfish100/fastdfs
-
FastDFS檔案系統由兩大部分構成,一個是客戶端,一個是服務端
客戶端通常指我們的程式,比如我們的Java程式去連接FastDFS、操作FastDFS,那我們的Java程式就是一個客戶端,FastDFS提供專有API訪問,目前提供了C、Java和PHP幾種編程語言的API,用來訪問FastDFS檔案系統,
-
服務端由兩個部分構成:一個是跟蹤器(tracker),一個是存盤節點(storage)
- 跟蹤器(tracker)主要做調度作業,在記憶體中記錄集群中存盤節點storage的狀態資訊,是前端Client和后端存盤節點storage的樞紐,因為相關資訊全部在記憶體中,Tracker server的性能非常高,一個較大的集群(比如上百個group)中有3臺就足夠了,
- 存盤節點(storage)用于存盤檔案,包括檔案和檔案屬性(meta data)都保存到存盤服務器磁盤上,完成檔案管理的所有功能:檔案存盤、檔案同步和提供檔案訪問等,
1.3 FastDFS的存盤策略
-
為了支持大容量,存盤節點(服務器)采用了分卷(或分組)的組織方式,存盤系統由一個或多個卷組成,卷與卷之間的檔案是相互獨立的,所有卷的檔案容量累加就是整個存盤系統中的檔案容量,一個卷可以由一臺或多臺存盤服務器組成,一個卷下的存盤服務器中的檔案都是相同的,卷中的多臺存盤服務器起到了冗余備份和負載均衡的作用,
-
在卷中增加服務器時,同步已有的檔案由系統自動完成,同步完成后,系統自動將新增服務器切換到線上提供服務,當存盤空間不足或即將耗盡時,可以動態添加卷,只需要增加一臺或多臺服務器,并將它們配置為一個新的卷,這樣就擴大了存盤系統的容量,
1.4 FastDFS的上傳程序
-
FastDFS向使用者提供基本檔案訪問介面,比如upload、download、append、delete等,以客戶端庫的方式提供給用戶使用,
-
Storage Server會定期的向Tracker Server發送自己的存盤資訊,當Tracker Server Cluster中的Tracker Server不止一個時,各個Tracker之間的關系是對等的,所以客戶端上傳時可以選擇任意一個Tracker,
-
當Tracker收到客戶端上傳檔案的請求時,會為該檔案分配一個可以存盤檔案的group,當選定了group后就要決定給客戶端分配group中的哪一個storage server,當分配好storage server后,客戶端向storage發送寫檔案請求,storage將會為檔案分配一個資料存盤目錄,然后為檔案分配一個fileid,最后根據以上的資訊生成檔案名存盤檔案,

1.5 FastDFS的檔案同步
-
寫檔案時,客戶端將檔案寫至group內一個storage server即認為寫檔案成功,storage server寫完檔案后,會由后臺執行緒將檔案同步至同group內其他的storage server,
-
每個storage寫檔案后,同時會寫一份binlog,binlog里不包含檔案資料,只包含檔案名等元資訊,這份binlog用于后臺同步,storage會記錄向group內其他storage同步的進度,以便重啟后能接上次的進度繼續同步;進度以時間戳的方式進行記錄,所以最好能保證集群內所有server的時鐘保持同步,
-
storage的同步進度會作為元資料的一部分匯報到tracker上,tracke在選擇讀storage的時候會以同步進度作為參考,
1.6 FastDFS的檔案下載
- 客戶端uploadfile成功后,會拿到一個storage生成的檔案名,接下來客戶端根據這個檔案名即可訪問到該檔案,

- 跟upload file一樣,在downloadfile時客戶端可以選擇任意tracker server,tracker發送download請求給某個tracker,必須帶上檔案名資訊,tracke從檔案名中決議出檔案的group、大小、創建時間等資訊,然后為該請求選擇一個storage用來服務讀請求,
2、FastDFS環境搭建
2.1 FastDFS安裝
2.1.1 安裝前的準備
(1) 檢查Linux上是否安裝了 gcc、libevent、libevent-devel
yum list installed | grep gcc
yum list installed | grep libevent
yum list installed | grep libevent-devel
(2) 如果沒有安裝,則需進行安裝
yum install gcc libevent libevent-devel –y
2.1.2 安裝 libfastcommon 庫
- libfastcommon 庫是 FastDFS 檔案系統運行需要的公共 C 語言函式庫
注意:目前最新版本的v1.0.39和最新版的FastDFS5.11不兼容,所有我們這里使用的版本是v1.0.36 下載地址:https://github.com/happyfish100
(1) 將下載好的libfastcommon檔案上傳到Linux(/home/)
(2) 解壓下載下來的tar.gz壓縮包到當前目錄
tar -zxvf libfastcommon-1.0.36.tar.gz
(3) 切換到解壓后的libfastcommon目錄
cd libfastcommon-1.0.36
(4) 執行make腳本進行編譯
./make.sh

注意: make編譯的時候如果報錯,需解決錯誤后再次進行make,通常發生錯誤是由于Linux缺少某些依賴庫導致,根據錯誤提示解決錯誤
(5) 執行make install進行安裝
./make.sh install

2.1.3 安裝FastDFS
-
FastDFS沒有Windows版本,不能在Windows下使用,
-
FastDFS需要安裝部署在Linux環境下,我們這里使用的是fastdfs-5.11版本(201901)
-
下載地址:https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz
(1) 將下載好的FastDFS檔案上傳到Linux(/home/)
(2) 解壓下載下來的tar.gz壓縮包到當前目錄
tar -zxvf fastdfs-5.11.tar.gz
(3) 切換到解壓后FastDFS的目錄
cd fastdfs-5.11
(4) 執行make腳本進行編譯
./make.sh
(5) 執行make install進行安裝
./make.sh install

-
所有編譯出來的檔案存放在/usr/bin目錄下
-
所有組態檔存放在/etc/fdfs目錄下
(6) 查看安裝后的效果
A、 查看FastDFS相關的可執行程式
ll /usr/bin/fdfs*

- /usr/bin是Linux的環境變數,可通過echo $PATH查看
B、 查看FastDFS的組態檔
ll /etc/fdfs/

(7) 另外注意需要把解壓后的fastdfs-5.11/conf目錄下的兩個檔案拷貝到/etc/fdfs/ ,否則后續會有很多奇怪問題不好解決
cp http.conf /etc/fdfs/
cp mime.types /etc/fdfs/

2.2 FastDFS組態檔詳解
1. 去掉/etc/fdfs/目錄下FastDFS組態檔的后綴名

2. 修改tracker.conf檔案
- 默認指向的FastDFS作者余慶的目錄,因為在我們的機器上不存在,所有手動改一下
base_path=/opt/fastdfs/tracker #配置tracker存盤資料的目錄

3. 修改storage.conf檔案
base_path=/opt/fastdfs/storage #storage存盤資料目錄
store_path0=/opt/fastdfs/storage/files #真正存放檔案的目錄
tracker_server=192.168.235.128:22122 #注冊當前存盤節點的跟蹤器地址



4. 在Linux服務器上創建上面指定的目錄
/opt/fastdfs/tracker
/opt/fastdfs/storage
/opt/fastdfs/storage/files

5. 然后啟動FastDFS
2.3 FastDFS啟動
FastDFS服務啟動需要啟動兩個腳本:
1. 啟動FastDFS的tracker服務
在任意目錄下執行:fdfs_trackerd /etc/fdfs/tracker.conf

2. 啟動FastDFS的storage服務
在任意目錄下執行:fdfs_storaged /etc/fdfs/storage.conf

3. 查看啟動行程

有啟動的執行命令即為啟動成功
4. 查看storage是否已經注冊到了tracker下
fdfs_monitor /etc/fdfs/storage.conf

5. 首次啟動storage后,會在配置的路徑下創建存盤檔案的目錄

2.4 FastDFS重啟與FastDFS關閉
2.4.1 FastDFS重啟
- 重啟tracker
fdfs_trackerd /etc/fdfs/tracker.conf restart

- 重啟storage
fdfs_storaged /etc/fdfs/storage.conf restart

2.4.2 FastDFS關閉
- 關閉tracker執行命令
在任意目錄下執行:fdfs_trackerd /etc/fdfs/tracker.conf stop

- 關閉storage執行命令
在任意目錄下執行:fdfs_storaged /etc/fdfs/storage.conf stop

或者kill關閉fastdfs,但不建議在線上使用kill -9強制關閉,因為可能會導致檔案資訊不同步問題,
2.5 FastDFS測驗
FastDFS安裝完成之后,可以使用fdfs_test腳本測驗檔案上傳,
測驗之前,需要修改client.conf組態檔,修改兩個配置
base_path=/opt/fastdfs/client
tracker_server=192.168.179.128:22122


在/opt/fastdfs/目錄下創建client

2.5.1 測驗檔案上傳
- 準備需要上傳的檔案

- 執行上傳命令fdfs_test /etc/fdfs/client.conf upload /root/aa.txt

- 切換到存盤目錄查看檔案上傳情況

FastDFS生成的檔案目錄結構及名稱示例

2.5.2 測驗檔案洗掉
fdfs_delete_file /etc/fdfs/client.conf group1/要洗掉的檔案路徑

注意
● 沒有搭建集群默認只有一個組group1
● 后綴名包含-m的為屬性檔案(meta)
● 在Linux中并沒有磁盤一說,是虛擬的
3、分布式檔案系統FastDFS的HTTP訪問
概述
-
在檔案上傳的時候,上傳成功的資訊中有提示我們可以通過某個路徑去訪問上傳的檔案,但是我們直接訪問這個路徑,卻不可以,那么已經上傳到FastDFS檔案系統中的檔案,我們如何在瀏覽器中訪問呢?
-
FastDFS提供了一個Nginx擴展模塊,利用該模塊,我們可以通過Nginx訪問已經上傳到FastDFS上的檔案
3.1 前期準備作業
-
將Fastdfs的Nginx擴展模塊源代碼上傳到Linux上
-
解壓下載下來的fastdfs-nginx-module-master.zip 檔案
unzip fastdfs-nginx-module-master.zip

3.2 安裝Nginx并且添加fastDFS模塊
因為這個模塊必須在Nginx的安裝的程序中才能添加,所有我們需要重新安裝一個nginx,為了和原來已安裝的Nginx進行區分,我們把新安裝的Nginx取名為nginx_fdfs
1. 將Nginx的tar包上傳到Linux上
2. 解壓上傳的Nginx檔案

3. 切換至解壓后的Nginx主目錄,執行配置操作
cd nginx-1.14.2
./configure --prefix=/usr/local/nginx_fdfs --add-
module=/home/soft/fastdfs-nginx-module-master/src
? prefix是指定nginx安裝路徑
? add-module指定fastDFS的nginx模塊的源代碼路徑

# 常見報錯問題
①/home/dfs/fastdfs-nginx-module-master/src/common.c:351:32: error: request for member ‘path’ in something not a structure or union
g_fdfs_store_paths.paths[i].path);
解決方案:
原因:軟體不匹配!
# wget https://sourceforge.net/projects/fastdfs/files/FastDFS%20Nginx%20Module%20Source%20Code/fastdfs-nginx-module_v1.16.tar.gz
# tar -zxvf fastdfs-nginx-module_v1.16.tar.gz
②/home/dfs/fastdfs-nginx-module/src/common.c:21:25: fatal error: fdfs_define.h: No such file or directory
#include "fdfs_define.h"
解決方案:
原因:編譯安裝nginx的fastdfs插件的頭檔案沒有找到,由于編譯nginx時候系統會到/usr/local /include
編譯安裝fastdfs-nginx-module時則默認保存在了/usr/include目錄,
修復:ln -s /usr/include/fast* /usr/local/include/
③ fatal error: common_define.h: No such file or directory
解決方案:
原因:在安裝FastDFS的時候,其中的函式宣告、宏定義、函式原型被指到了 “ /usr/include/fastdfs /usr/include/fastcommon ” 目錄下
vi /home/dfs/fastdfs-nginx-module/src/config
ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/"
》》》
CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/"
4. 執行命令進行編譯
make
5. 執行命令進行安裝
make install
6. 以上安裝Nginx的FastDFS擴展模塊注意事項
我們知道,Nginx的安裝需要Linux安裝相關的幾個庫,否則編譯會出現錯誤,這幾個庫分別是:
? gcc編譯器是否安裝
檢查是否安裝:yum list installed | grep gcc
執行安裝:yum install gcc -y
? openssl庫是否安裝
檢查是否安裝:yum list installed | grep openssl
執行安裝:yum install openssl openssl-devel -y
? pcre庫是否安裝
檢查是否安裝:yum list installed | grep pcre
執行安裝:yum install pcre pcre-devel -y
? zlib庫是否安裝
檢查是否安裝:yum list installed | grep zlib
執行安裝:yum install zlib zlib-devel -y
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y
7. FastDFS擴展模塊執行流程


3.3 FastDFS的Nginx訪問配置
將/home/soft/fastdfs-nginx-module-master/src(自己實際存放Nginx擴展模塊的目錄)目錄下的mod_fastdfs.conf檔案拷貝到 /etc/fdfs/目錄下,這樣才能正常啟動Nginx
cp /home/soft/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/

1. 修改mod_fastdfs.conf組態檔
base_path=/opt/fastdfs/nginx_mod
tracker_server=192.168.235.128:22122
url_have_group_name = true
store_path0=/opt/fastdfs/storage/files
2. 在/opt/fastdfs/目錄下創建nginx_mod目錄

3. 配置Nginx的組態檔
#攔截請求路徑中包含 /group[1-9]/M0[0-9] 的請求,用 fastdfs的Nginx 模塊進行轉發
location ~ /group[1-9]/M0[0-9] {
ngx_fastdfs_module;
}

ngx_fastdfs_module; #這個指令不是Nginx本身提供的,是擴展模塊提供的,根據這個指令找到FastDFS提供的Nginx模塊組態檔,然后找到Tracker,最終找到Stroager,
3.4 FastDFS的Nginx訪問啟動與測驗
1. 啟動帶有Fastdfs模塊的Nginx

2. 重啟或啟動FastDFS服務行程
fdfs_trackerd /etc/fdfs/tracker.conf restart
fdfs_storaged /etc/fdfs/storage.conf restart

3. 上傳一個檔案進行測驗驗證
fdfs_test /etc/fdfs/client.conf upload /root/aa.txt

4. 在瀏覽器訪問上傳的檔案
當遇到400錯誤,檢查配置/etc/fdfs/mod_fastdfs.conf
url_have_group_name=true
該配置表示訪問路徑中是否需要帶有group1,改為true表示路徑中需要有group1
5. 擴展
模擬大型網站用戶頭像的處理方式,上傳一張圖片,然后自己寫一個html頁面,src指向上傳的圖片,
4、FastDFS分布式檔案系統Java客戶端
在實際專案開發中,FastDFS提供的主要功能
● upload:上傳檔案
● download:下載檔案
● delete:洗掉檔案
4.1 FastDFS檔案系統的Java客戶端
FastDFS檔案系統Java客戶端是指采用Java語言撰寫的一套程式,專門用來訪問fastDFS檔案系統,其實就是一個jar包,
注意:大家如果能連上 mvnrepository上搜索到的用友云提供的fastdfs-client,那大家就下載那個jar包使用,如果連不上,這個jar包需要我們自己來打,
1. 下載官方的源代碼
從https://codeload.github.com/happyfish100/fastdfs-client-java/zip/master上下載FastDFS源代碼到本地
2. 解壓
3. 采用maven命令編譯成jar安裝到本地maven庫
mvn clean install

4. 在Java程式中使用它提供的API來訪問FastDFS檔案系統
4.2 FastDFS檔案上傳功能實作
4.2.1 需求
使用Java客戶端,編程操作fastDFS分布式檔案系統,上傳本地檔案到FastDFS服務器上,
4.2.2 實作步驟
- 使用IDEA創建普通的maven專案,不需要使用

- 在pom.xml檔案中添加我們打包好的FastDFS本地倉庫的jar包(FastDFS的java客戶端依賴)

<!--加入FastDFS的java客戶端依賴-->
<dependencies>
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27-SNAPSHOT</version>
</dependency>
</dependencies>
- 拷貝源代碼包中的fdfs_client.conf檔案到resources目錄下,在里面主要配置tracker地址
tracker_server = 192.168.235.128:22122
- 撰寫代碼,進行上傳測驗
在com.bjpowernode.fastdfs包下創建FastDFS類,在其中撰寫上傳代碼
package com.bjpowernode.fastdfs;
import org.csource.common.MyException;
import org.csource.fastdfs.*;
import java.io.IOException;
public class FastDFS {
public static void main(String[] args) {
fileUpload();
}
//上傳檔案的方法
public static void fileUpload(){
TrackerServer trackerServer = null;
StorageServer storageServer = null;
try {
//1.加載組態檔,默認去classpath下加載
ClientGlobal.init("fdfs_client.conf");
//2.創建TrackerClient物件
TrackerClient trackerClient = new TrackerClient();
//3.創建TrackerServer物件
trackerServer = trackerClient.getConnection();
//4.創建StorageServler物件
storageServer = trackerClient.getStoreStorage(trackerServer);
//5.創建StorageClient物件,這個物件完成對檔案的操作
StorageClient storageClient = new StorageClient(trackerServer,storageServer);
//6.上傳檔案 第一個引數:本地檔案路徑 第二個引數:上傳檔案的后綴 第三個引數:檔案資訊
String [] uploadArray = storageClient.upload_file("D:/aa.txt","txt",null);
for (String str:uploadArray) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
if(storageServer != null){
try {
storageServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(trackerServer != null){
try {
trackerServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 運行程式,在Linux上,FastDFS存盤目錄下查看上傳檔案內容


4.3 FastDFS檔案上傳功能封裝
4.3.1 需求
因為使用FastDFS進行檔案操作代碼大多都是通用的,所以我們這里在FastDFS類中將通用的功能進行封裝,并提供上傳、下載、洗掉檔案的方法,
注意:這里只是簡單的封裝,如果多執行緒會有問題
4.3.2 實作步驟
- 抽取獲取StorageClient的方法
public static StorageClient getStorageClient() throws IOException, MyException {
//1.加載組態檔,默認去classpath下加載
ClientGlobal.init("fdfs_client.conf");
//2.創建TrackerClient物件
TrackerClient trackerClient = new TrackerClient();
//3.創建TrackerServer物件
trackerServer = trackerClient.getConnection();
//4.創建StorageServler物件
storageServer = trackerClient.getStoreStorage(trackerServer);
//5.創建StorageClient物件,這個物件完成對檔案的操作
StorageClient storageClient = new StorageClient(trackerServer,storageServer);
return storageClient;
}
- 定義兩個全域變數
private static TrackerServer trackerServer = null;
private static StorageServer storageServer = null;
- 抽取關閉資源的方法
public static void closeFastDFS() {
if (storageServer != null) {
try {
storageServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (trackerServer != null) {
try {
trackerServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 改造檔案上傳的方法
public static void fileUpload(){
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.上傳檔案 第一個引數:本地檔案路徑 第二個引數:上傳檔案的后綴 第三個引數:檔案資訊
String [] uploadArray = storageClient.upload_file("D:/aa.txt","txt",null);
for (String str:uploadArray) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
}
- 下載檔案的方法
/下載檔案的方法
public static void fileDownload(){
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.下載檔案 回傳0表示成功,其它均表示失敗
int num = storageClient.download_file("group1",
"M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt","E:/bb.txt");
System.out.println(num);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
}
- 洗掉檔案的方法
/洗掉檔案的方法
public static void fileDelete(){
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.洗掉檔案 回傳0表示成功,其它均表示失敗
int num = storageClient.delete_file("group1",
"M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt");
System.out.println(num);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
}
- 主方法呼叫不同的方法進行測驗
5、FastDFS在web專案中的應用
需求
對P2P專案合同進行管理,在WEB專案中實作對檔案的上傳下載和洗掉操作,
名詞解釋
● 有一些債權:投資人有該債務的權利
注:通常隱含的意思就是:一筆借款常被稱為一個債權,
● 一個債權會有一個合同
● 合同是pdf檔案
● 債權是債務的對應詞,但是在P2P專案中,我們管理的債權,以及合同一般指的是借款人的資訊,所以在我們下面創建的creditor_info表中存的是借款人資訊
目標
● 實作對pdf檔案上傳、下載、洗掉
● 熟練一下Springboot+thymeleaf
案例實作步驟
1. 資料庫環境搭建
① 創建資料庫fastdfs
② 在該庫下創建creditor_info表
CREATE TABLE `creditor_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`realName` varchar(35) DEFAULT NULL COMMENT '債權借款人姓名',
`idCard` varchar(18) DEFAULT NULL COMMENT '債權借款人身份證',
`address` varchar(150) DEFAULT NULL COMMENT '債權借款人地址',
`sex` int(1) DEFAULT NULL COMMENT '1男2女',
`phone` varchar(11) DEFAULT NULL COMMENT '債權借款人電話',
`money` decimal(10,2) DEFAULT NULL COMMENT '債權借款人借款金額',
`groupName` varchar(10) DEFAULT NULL COMMENT '債權合同所在組',
`remoteFilePath` varchar(150) DEFAULT NULL COMMENT '債權合同所在路徑',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
⒉ 開發環境搭建
① 創建SpringBoot專案10-fastdfs-web,添加Web和Thymeleaf依賴



② 在pom.xml檔案中添加Mybatis依賴及MySQL依賴
<!-- 加載mybatis整合springboot -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<!--在springboot的父工程中沒有指定版本,我們需要手動指定-->
<version>1.3.2</version>
</dependency>
<!-- MySQL的jdbc驅動包 -->
<dependency>
<groupId>mysql</groupId>
<!--在springboot的父工程中指定了版本,我們就不需要手動指定了-->
<artifactId>mysql-connector-java</artifactId>
</dependency>
③ 在pom.xml檔案中添加resources,指定編譯的位置
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
<!--如果存在jsp,需要指定jsp檔案編譯的位置-->
</resources>
④ 在SpringBoot主組態檔application.properties中添加資料庫配置資訊
#資料庫的連接配置資訊
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.235.128:3306/fastdfs?useUnicode=true&characterEncoding=utf8&useSSL=false
⑤ 使用Mybatis反向工程,生成物體類及mapper映射(參照SpringBoot附錄教程)
A、在pom.xml檔案中添加反向工程插件
<!--mybatis代碼自動生成插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!--組態檔的位置-->
<configurationFile>GeneratorMapper.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
B、 從03-springboot-web中復制GeneratorMapper.xml到當前專案下

C、 修改GeneratorMapper.xml組態檔內容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 指定連接資料庫的JDBC驅動包所在位置,指定到你本機的完整路徑 -->
<classPathEntry location="D:/repository/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar"/>
<!-- 配置table表資訊內容體,targetRuntime指定采用MyBatis3的版本 -->
<context id="tables" targetRuntime="MyBatis3">
<!-- 抑制生成注釋,由于生成的注釋都是英文的,可以不讓它生成 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 配置資料庫連接資訊 注意:使用高版本的驅動 url后面應該加屬性nullCatalogMeansCurrent=true,否則生成有問題 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://192.168.235.128:3306/fastdfs?nullCatalogMeansCurrent=true"
userId="root"
password="123456">
</jdbcConnection>
<!-- 生成model類,targetPackage指定model類的包名, targetProject指定生成的model放在eclipse的哪個工程下面-->
<javaModelGenerator targetPackage="com.bjpowernode.fastdfs.model" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="false" />
</javaModelGenerator>
<!-- 生成MyBatis的Mapper.xml檔案,targetPackage指定mapper.xml檔案的包名, targetProject指定生成的mapper.xml放在eclipse的哪個工程下面 -->
<sqlMapGenerator targetPackage="com.bjpowernode.fastdfs.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- 生成MyBatis的Mapper介面類檔案,targetPackage指定Mapper介面類的包名, targetProject指定生成的Mapper介面放在eclipse的哪個工程下面 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.bjpowernode.fastdfs.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 資料庫表名及對應的Java模型類名 -->
<table tableName="creditor_info"
domainObjectName="CreditorInfo"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false"/>
</context>
</generatorConfiguration>
D、雙擊生成

⑥ 創建相關的包和類
在com.bjpowernode.fast包下創建controller ,service 包,及其子包impl
創建CreditorInfoController類
創建CreditorInfoService介面
創建CreditorInfoServiceImpl實作類

3. 功能實作-展示所有債權資訊
① 在CreditorInfoController類中創建index方法,將CreditorInfoService注入到controller中
@Controller
public class CreditorInfoController {
@Autowired
private CreditorInfoService creditorInfoService;
@GetMapping("/fastdfs/index")
public String index(Model model){
List<CreditorInfo> creditorInfoList = creditorInfoService.getAllCreditorInfo();
model.addAttribute("creditorInfoList",creditorInfoList);
//模板頁面,不是jsp
return "index";
}
}
② 在CreditorInfoService中提供getAllCreditorInfo方法
public interface CreditorInfoService {
/**
* 獲取所有債權資訊
* @return
*/
List<CreditorInfo> getAllCreditorInfo();
}
③ 在CreditorInfoServiceImpl中對getAllCreditorInfo方法進行實作
@Service
public class CreditorInfoServiceImpl implements CreditorInfoService {
@Autowired
private CreditorInfoMapper creditorInfoMapper;
@Override
public List<CreditorInfo> getAllCreditorInfo() {
return creditorInfoMapper.selectAllCreditorInfo();
}
}
④ 因為是SpringBoot專案,所以需要在Mapper介面上加一個Mapper注解
@Mapper
public interface CreditorInfoMapper {}
⑤ 在CreditorInfoMapper類中添加selectAllCreditorInfo方法
List<CreditorInfo> selectAllCreditorInfo();
⑥ 在IDEA中安裝free Mybatis插件
該插件可以通過點擊Mapper介面中的方法,進入到.xml檔案
A、 SettingsàpluginsàBrowse repositories

B、 在插件庫中搜索,free mybatis安裝

C、 插件安裝完畢,需要重啟IDEA
⑦ 在CreditorInfoMapper.xml檔案中添加SQL陳述句
<select id="selectAllCreditorInfo" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from creditor_info
</select>
⑧ 展示頁面的設計
A、 在專案的templates目錄下創建index.html

B、 百度搜索bootstrap表格,挑選自己喜歡風格的表格,將代碼拷貝到index.html中
我這里使用的是http://www.bjpowernode.com/try/try.php?
filename=bootstrap3-table-striped表格進行改寫
C、 在html標簽上加上Thymeleaf的命名空間
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
D、 修改index.html內容
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>債權合同管理</title>
<link rel="stylesheet" th:href="@{/css/bootstrap-3.3.7.min.css}">
<script th:src="@{/js/jquery-2.1.1.min.js}"></script>
<script th:src="@{/js/bootstrap-3.3.7.min.js}"></script>
</head>
<body>
<table class="table table-striped">
<caption>債權合同資訊串列</caption>
<thead>
<tr>
<th>序號</th>
<th>債權借款人姓名</th>
<th>債權借款人身份證</th>
<th>債權借款人住址</th>
<th>債權借款人手機號</th>
<th>債權借款人性別</th>
<th>債權借款人借款金額</th>
</tr>
</thead>
<tbody>
<tr th:each="creditorInfo:${creditorInfoList}">
<td th:text="${creditorInfoStat.count}"></td>
<td th:text="${creditorInfo.realname}"></td>
<td th:text="${creditorInfo.idcard}"></td>
<td th:text="${creditorInfo.address}"></td>
<td th:text="${creditorInfo.phone}"></td>
<td th:text="${creditorInfo.sex == 1 ?'男':'女'}"></td>
<td th:text="${creditorInfo.money}"></td>
</tr>
</tbody>
</table>
</body>
</html>
注意:我們從網路上拷貝過來的內容css,js等是聯網獲取的,我們這里可以從04-FastDFS\resources獲取,并放在專案的static的相關目錄下,在頁面上參考
⑨ 向資料庫中加幾條資料

⑩ 啟動專案,訪問http://localhost:8080/fastdfs/index 查看效果

? 調整頁面樣式
<body style="margin: 50px">
- 功能實作-為某一個債權合同上傳檔案
① 在index.html中添加操作列
<th>合同管理</th>
<td>
<!--為哪個合同上傳,需要將合同的id傳遞過去-->
<a th:href="@{'/fastdfs/toUpload?id=' + ${creditorInfo.id}}">上傳</a>
下載
洗掉
</td>
② 在CreditorController中添加跳轉到上傳頁面的方法
@GetMapping("/fastdfs/toUpload")
public String toUpload(Model model, @RequestParam("id") Integer id){
model.addAttribute("id",id);
return "upload";
}
③ 在templates下創建upload.html頁面
在網上搜索bootstrap表單,并對其內容進行修改,我這里使用的是
http://www.bjpowernode.com/try/try2.php?filename=bootstrap3-form-inline
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>債權合同上傳</title>
<link rel="stylesheet" th:href="@{/css/bootstrap-3.3.7.min.css}">
<script th:src="@{/js/jquery-2.1.1.min.js}"></script>
<script th:src="@{/js/bootstrap-3.3.7.min.js}"></script>
</head>
<body>
<form th:action="@{/fastdfs/upload}" class="form-inline" role="form" method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="sr-only" for="fileName">檔案輸入</label>
<input type="file" id="fileName" name="fileName">
</div>
<input type="hidden" name="id" th:value="${id}">
<button type="submit" class="btn btn-default">提交</button>
</form>
</body>
</html>
注意:
● 檔案上傳必須是post請求
● enctype必須為multipart/form-data
● 合同的id通過隱藏域傳遞
④ 在pom.xml檔案中加入FastDFS客戶端的jar包依賴
<!--加入FastDFS的java客戶端依賴-->
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27-SNAPSHOT</version>
</dependency>
⑤ 將FastDFS客戶端的組態檔fast_client.conf拷貝到resources目錄下

⑥ 將原來我們封裝的FastDFS類拷貝到fastdfs包下,修改其中的file_upload方法,定義一些引數
去掉主方法,新的fileUpload寫法如下:
/上傳檔案的方法
public static String[] fileUpload(byte[] fileBytes,String fileExt){
String [] uploadArray = null;
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.上傳檔案 第一個引數:本地檔案路徑 第二個引數:上傳檔案的后綴 第三個引數:檔案資訊
uploadArray = storageClient.upload_file(fileBytes,fileExt,null);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
return uploadArray;
}
⑦ 在CreditorController中添加處理上傳檔案的方法
@PostMapping("/fastdfs/upload")
public @ResponseBody String upload(@RequestParam("id") Integer id, @RequestParam("fileName") MultipartFile file){
//原來檔案上傳是將檔案寫到本地或者遠程服務器的某個目錄下
//現在的檔案上傳是將檔案上傳到fastdfs檔案服務器上
//1表示上傳失敗 0表示成功
int result = 1;
//abc.txt -->txt
String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf(".") + 1);
try {
String[] uploadArray = FastDFS.fileUpload(file.getBytes(),fileExt);
if(uploadArray != null && uploadArray.length ==2){
//檔案上傳到fastDFS成功 ,將合同檔案路徑更新到債權記錄中
CreditorInfo creditorInfo = new CreditorInfo();
creditorInfo.setId(id);
creditorInfo.setGroupname(uploadArray[0]);
creditorInfo.setRemotefilepath(uploadArray[1]);
int updateRow = creditorService.updateCreditorInfo(creditorInfo);
//資料庫更新成功
if(updateRow > 0){
result = 0;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return "<script>window.parent.uploadOK('"+result+"')</script>";
}
⑧ 在CreditorInfoService中添加updateCreditorInfo方法
/**
* 更新債權資訊
* @param creditorInfo
* @return
*/
int updateCreditorInfo(CreditorInfo creditorInfo);
⑨ 在CreditorInfoServiceImpl中添加updateCreditorInfo方法實作
@Override
public int updateCreditorInfo(CreditorInfo creditorInfo) {
return creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo);
}
⑩ 在upload.html做一個類似ajax的頁面不重繪效果
● 在upload.html頁面中加一個iframe
● upload.html頁面中的form中的target設定為iframe的name
● 在iframe的父頁面中,寫一個函式,處理上傳結果
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>債權合同上傳</title>
<link rel="stylesheet" th:href="@{/css/bootstrap-3.3.7.min.css}">
<script th:src="@{/js/jquery-2.1.1.min.js}"></script>
<script th:src="@{/js/bootstrap-3.3.7.min.js}"></script>
</head>
<body>
<form th:action="@{/fastdfs/upload}" class="form-inline" role="form" method="post" target="uploadFrame" enctype="multipart/form-data">
<div class="form-group">
<label class="sr-only" for="fileName">檔案輸入</label>
<input type="file" id="fileName" name="fileName">
</div>
<input type="hidden" id="id" name="id" th:value="${id}">
<button type="submit" class="btn btn-default">提交</button>
</form>
<iframe name="uploadFrame" style="display: none;"></iframe>
<script type="text/javascript" th:inline="javascript">
function uploadOK(result){
if(result == 0){
//檔案上傳成功
alert("檔案上傳成功");
var contextPath = [[${#request.getContextPath()}]];
window.location.href = contextPath + "/fastdfs/index";
}else{
alert("檔案上傳失敗");
}
}
</script>
</body>
</html>
? 如果上傳檔案超出了1M,需要在application.properties中配置SpringBoot上傳檔案的最大限制
#SpringBoot上傳檔案的最大限制
spring.servlet.multipart.max-file-size=10MB
注意:如果提示找不到tracker_server,看看是否編譯到target中
- 功能實作-下載某一個債權合同
① 修改index.html頁面,下載加連接,并做判斷
<td>
<span th:if="${creditorInfo.getGroupname() ne null && creditorInfo.remotefilepath ne null}">
<a th:href="@{'/fastdfs/download?id=' + ${creditorInfo.id}}">下載</a>
洗掉
</span>
<span th:unless="${creditorInfo.getGroupname() ne null && creditorInfo.remotefilepath ne null}">
<!--為哪個合同上傳,需要將合同的id傳遞過去-->
<a th:href="@{'/fastdfs/toUpload?id=' + ${creditorInfo.id}}">上傳</a>
</span>
</td>
② 在CreditorController中,完成下載的請求
● ResponseEntity通常用于回傳檔案流
● @ResponseBody可以直接回傳Json結果,
● @ResponseEntity不僅可以回傳json結果,還可以定義回傳的HttpHeaders和HttpStatus
● ResponseEntity的優先級高于@ResponseBody,在不是ResponseEntity的情況下才去檢查有沒有@ResponseBody注解,如果回應型別是ResponseEntity可以不寫@ResponseBody注解,寫了也沒有關系,
@GetMapping("/fastdfs/download")
public ResponseEntity<byte[]> download(@RequestParam("id") Integer id){
//根據債權id獲取 債權物件
CreditorInfo creditorInfo = creditorInfoService.getCreditorInfoById(id);
String extName = creditorInfo.getRemotefilepath().substring(creditorInfo.getRemotefilepath().indexOf("."));
byte [] fileBytes = FastDFS.fileDownload(creditorInfo.getGroupname(),creditorInfo.getRemotefilepath());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);//流型別
httpHeaders.setContentDispositionFormData("attachment",System.currentTimeMillis() + extName);
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(fileBytes,httpHeaders, HttpStatus.OK);
return responseEntity;
}
③ 在CreditorService介面中添加getCreditorInfoById的方法
/**
* 根據合同id獲取債權資訊
* @param id
* @return
*/
CreditorInfo getCreditorInfoById(Integer id);
④ 在CreditorServiceImpl中添加getCreditorInfoById方法的實作
@Override
public CreditorInfo getCreditorInfoById(Integer id) {
return creditorInfoMapper.selectByPrimaryKey(id);
}
⑤ 修改FastDFS類中fileDown方法的實作,傳遞引數
//下載檔案的方法
public static byte[] fileDownload(String group,String remoteFile){
byte[] fileBytes = null;
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.下載檔案 回傳0表示成功,其它均表示失敗
fileBytes = storageClient.download_file(group,remoteFile);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
return fileBytes;
}
⑥ 瀏覽器訪問下載測驗效果
- 功能實作-洗掉某一個債權合同,使用ajax實作異步洗掉
① 在index.html頁面為洗掉加超鏈接
<span th:if="${creditorInfo.getGroupname() ne null && creditorInfo.remotefilepath ne null}">
<a th:href="@{'/fastdfs/download?id=' + ${creditorInfo.id}}">下載</a>
<a th:href="@{'javascript:deleteFile('+ ${creditorInfo.id} +')'}">洗掉</a>
</span>
② 在index.html頁面提供js方法,并發送ajax請求,對回應結果進行處理
<script type="text/javascript" th:inline="javascript">
function deleteFile(id){
//獲取專案的背景關系根
var contextPath = [[${#request.getContextPath()}]];
$.ajax({
url:contextPath +"/fastdfs/fileDelete",
type:"post",
data:{
"id":id
},
success:function(responseMsg){
if(responseMsg==0){
alert("洗掉成功");
window.location.reload();
}else{
alert("洗掉失敗");
}
}
});
}
</script>
③ 在CreditorController中處理洗掉請求
注意:洗掉FastDFS和清除資料庫,所以我們將這些業務都放在service中進行事務的處理
@RequestMapping("/fastdfs/fileDelete")
public @ResponseBody String fileDelete(@RequestParam("id") Integer id){
int result = 1;
try {
result = creditorService.deleteContract(id);
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(result);
}
④ 在CreditorService介面中加洗掉合同的方法deleteContract
因為目前提供的方法,如果group和remoteFilePath為空就不更新,所以我們需要自己提供
/**
* 洗掉合同
* @param id
* @return
*/
int deleteContract(Integer id);
⑤ 在CreditorServiceImpl類中對deleteContract方法進行實作
@Override
@Transactional //加上該注解控制事務
public int deleteContract(Integer id) {
// 1 洗掉失敗;0 洗掉成功
int result = 1;
//根據債權id獲取債權資訊
CreditorInfo creditorInfo = creditorInfoMapper.selectByPrimaryKey(id);
/**
* 注意:事務控制的資料庫,所以我們先對資料庫進行更新,在操作FastDFS
* 如果操作FastDFS失敗了,那么對資料庫的操作回滾
*/
//更新資料庫債權表的合同路徑及組
int updateRow = creditorInfoMapper.updateConstractById(id);
if(updateRow > 0){
//如果資料庫更新成功,那么洗掉FastDFS上的檔案
int num = FastDFS.fileDelete(creditorInfo.getGroupname(),creditorInfo.getRemotefilepath());
if(num == 0){
//如果洗掉成功,那么將整個操作結果設定為0,表示成功
result = 0;
}else{
//如果洗掉FastDFS上的檔案失敗,我們拋出一個運行例外,回滾事務
throw new RuntimeException("FastDFS檔案洗掉失敗");
}
}
return result;
}
⑥ 在CreditorMapper類中添加更新的方法
/**
* 根據債權的id,將組和合同路徑更新為null
* @param id
* @return
*/
int updateConstractById(Integer id);
⑦ 在CreditorMapper.xml中添加更新的方法
<update id="updateConstractById" parameterType="java.lang.Integer">
update creditor_info
set
groupName = NULL ,
remoteFilePath = NULL
where id = #{id,jdbcType=INTEGER}
</update>
⑧ 修改FastDFS類中的fileDelete方法,提供引數
//洗掉檔案的方法
public static int fileDelete(String group ,String remoteFile){
int num = 1;
try {
//1. 獲取StorageClient物件
StorageClient storageClient = getStorageClient();
//2.洗掉檔案 回傳0表示成功,其它均表示失敗
num = storageClient.delete_file(group,remoteFile);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
return num;
}
⑨ 在Application類上開啟事務支持
@SpringBootApplication
@EnableTransactionManagement
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 功能實作-彈層組建layer的使用(簡單介紹)
官網:https://www.layui.com
2018開源軟體排行比較靠前
6、FastDFS分布式檔案系統集群
6.1 架構圖

● 如果你公司剛好用這個,那你就會搭建集群
● 涉及到多個Linux,你可以更進一步熟悉一下Linux
● 提升自己駕馭復雜環境的能力
6.2 環境搭建步驟
建一個FastDFS分布式檔案系統集群,推薦至少部署6個服務器節點,
1. 安裝6個迷你版的Linux
迷你版Linux沒有圖形界面,占用磁盤及資源小,企業里面使用的Linux都是沒有圖形界面的Linux,在安裝的時候,最少要給每一個虛擬機分配3.5G的記憶體空間,我這里分配5G,記憶體我這里分配的是512M
① 打開Vmware,點擊創建新的虛擬機
② 選擇典型安裝
③ 選擇安裝Linux迷你版安裝檔案位置
④ 指定虛擬機名稱及安裝位置
⑤ 為虛擬機分配磁盤空間
⑥ 為虛擬機分配記憶體
我是8G記憶體,每個虛擬機分配512M,因為是迷你版,所以記憶體消耗不會太大
⑦ 開啟此虛擬機
⑧ 開始安裝
⑨ 選擇語言為English
⑩ 打開網路連接(重要)



這個選項點進去完成一下就好,其它配置都可以默認,但是網路一定要打開,否則虛擬機之間無法通訊
? 設定root用戶密碼為123456

? 安裝完畢后,重啟安裝的CentOS系統
2. 在Xshell中創建6個連接,分別連向不同的Linux

3. 為迷你版的Linux安裝常用工具庫
由于迷你版Linux缺少一些常用的工具庫,操作起來不方便,推薦安裝如下的工具庫:
? 安裝lrzsz, yum install lrzsz -y
? 安裝wget, yum install wget -y
? 安裝vim, yum install vim -y
? 安裝unzip,yum install unzip -y
? 安裝ifconfig,yum install net-tools -y
yum install lrzsz wget vim unzip net-tools –y
打開撰寫欄,方便批量執行命令

4. 按照課件上安裝FastDFS的步驟在6個服務器節點安裝FastDFS
5. 配置兩個tracker server服務器
為了方便操作,我們再啟動一次Xshell,一個Xshell操作Tracker,另一個操作Storage,將Tracker和Storage分開
? 把/etc/fdfs目錄下的組態檔.sample后綴都去掉
? 修改兩個tracker服務器的組態檔:
tracker.conf: 修改一個地方:
base_path=/opt/fastdfs/tracker #設定tracker的資料檔案和日志目錄(需預先創建)
? 創建存放資料的目錄
6. 配置四個storage server服務器
每兩個storage server為一組,共兩個組(group1 和 group2),一個組內有兩個storage server
① 修改第一組group1的第一個storage server(修改storage.conf組態檔)
group_name=group1 #組名,根據實際情況修改,值為 group1 或 group2
base_path=/opt/fastdfs/storage #設定storage的日志目錄(需預先創建)
store_path0=/opt/fastdfs/storage/files #存盤路徑
tracker_server=192.168.235.129:22122 #tracker服務器的IP地址和埠號,配2個tracker_server=192.168.235.130:22122
② 第一個組的第二個storage按照相同的步驟操作
或者將第一組的組態檔下載到桌面上,然后上傳覆寫第一組的第二個storage
③ 第二組的兩個storage也按照相同的步驟操作;唯一的區別是group_name=group2
可以在桌面上對第一個組的storage檔案進行修改,將組名修改為group2,然后上傳覆寫
至此,一個FastDFS的分布式檔案系統集群就搭建好了,
④ 注意:組態檔中不要出現中文,另外別忘了創建組態檔中指定的目錄
⑤ 啟動兩個tracker,再啟動四個storage
⑥ 關閉6個Linux防火墻,通過09-fastdfs-java的代碼進行測驗
修改組態檔為兩個tracker
測驗負載均衡:tracker.conf檔案 (修改 store_lookup=0 表示輪訓策略)
7. 部署Http訪問FastDFS上的檔案
① 先完成4個storage server的Nginx訪問
這4個Nginx需要去fastDFS找對應的檔案,所以需要安裝FastDFS的Nginx擴展模塊
A、 配置帶有FastDFS擴展模塊的Nginx
在四個storage server上安裝Nginx,并且加入FastDFS擴展模塊;
修改兩組4個storage的nginx擴展模塊組態檔 mod_fastdfs.conf
base_path=/opt/fastdfs/nginx_mod #保存日志目錄(需提前創建)
tracker_server=192.168.230.129:22122 #tracker服務器的IP地址以及埠號
tracker_server=192.168.230.130:22122
group_name=group1 #當前服務器的group名,第二組應配置為group2
url_have_group_name=true #檔案url中是否有group名
store_path_count=1 #存盤路徑個數,需要和store_path個數匹配(一般不用改)
store_path0=/opt/fastdfs/storage/files #存盤路徑
group_count = 2 #設定組的個數
在末尾增加2個組的具體資訊:
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/opt/fastdfs/storage/files
[group2]
group_name=group2
storage_server_port=23000
store_path_count=1
store_path0=/opt/fastdfs/storage/files
B、 第一組的第二臺和上面的配置一樣
C、 第二組的兩臺只需要把group_name=group2即可
D、 至此,mod_fastdfs.conf就配置好了,
② 配置兩組4個storage的nginx攔截請求路徑:
location ~ /group[1-9]/M0[0-9] {
ngx_fastdfs_module;
}
至此4個storage服務器上的Nginx就搭建配置OK了
然后可以進行測驗:
重啟storage,啟動Nginx
http://192.168.119.128:80/group1/M00/00/00/wKh3jVx6FUCARyK2AAAANaS4cxw338.txt
http://192.168.92.132:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
http://192.168.92.133:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
http://192.168.92.134:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
注意:每一臺都可以訪問到,就算是當前組中沒有改檔案,因為向瀏覽器中發送請求的時候
交給Nginx進行location匹配
匹配上之后呼叫FastDFS的擴展模塊
擴展模塊會讀取擴展模塊組態檔mod_fast.conf
通過擴展模塊組態檔,找到對應的Tracker,從而找到對應的檔案
③ 在兩個tracker server安裝Nginx
這兩個Nginx只需要做負載均衡,不要找檔案,所以不需要安裝擴展模塊
④ 配置兩個tracker server服務器上的Nginx訪問
部署配置nginx負載均衡:
upstream fastdfs_storage_server {
server 192.168.92.131:80;
server 192.168.92.132:80;
server 192.168.92.133:80;
server 192.168.92.134:80;
}
#nginx攔截請求路徑:
location ~ /group[1-9]/M0[0-9] {
proxy_pass http://fastdfs_storage_server;
}
至此,兩個tracker服務器的Nginx就搭建配置OK了,
啟動兩個tracker服務器的Nginx進行測驗,
http://192.168.92.129:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
http://192.168.92.130:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
⑤ 部署前端用戶訪問入口服務器,該Nginx負載均衡到后端2個tracker server
這個Nginx也只需要做負載均衡,不要找檔案,所以不需要安裝擴展模塊,可以對Windows上的的Nginx進行配置
部署配置nginx負載均衡:
upstream fastdfs_tracker_server {
server 192.168.92.129:80;
server 192.168.92.130:80;
}
#nginx攔截請求路徑:
location ~ /group[1-9]/M0[0-9] {
proxy_pass http://fastdfs_tracker_server;
}
訪問:http://127.0.0.1:80/group1/M00/00/00/wKhchFv7xQeAQbrBAAAALDPVPvc081.txt
至此,一個三層結構的Nginx訪問架構就搭建配置OK了,為了保證高可用性,一般在入口出,會添加一個備用Nginx上,中間通過一個keepAlive軟體連接,
最后,為了讓服務能正常連接tracker,請關閉所有機器的防火墻:
systemctl status firewalld
systemctl disable firewalld
systemctl stop firewalld
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/291826.html
標籤:其他
