SpringBoot2.0集成FastDFS

SpringBoot2.0集成FastDFS

前兩篇總體上介紹了經過 Nginx 和 FastDFS 的整合來實現文件服務器。可是,在實際開發中對圖片或文件的操做都是經過應用程序來完成的,所以,本篇將介紹 Spring Boot 整合 FastDFS 客戶端來實現對圖片/文件服務器的訪問。html

若是有不瞭解 FastDFS 的讀者能夠先瀏覽《CentOS7 安裝FastDFS分佈式文件系統》或是另行查閱網上相關資料。java

1、整合編碼

項目總體的代碼結構圖以下:mysql

添加依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
  <groupId>com.sql.tools</groupId>
  <artifactId>springboot-sql-tools</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <mybatis.spring.version>1.3.2</mybatis.spring.version>
        <com.alibaba.druid.version>1.1.10</com.alibaba.druid.version>
        <log4j.version>1.2.17</log4j.version>
        <pagehelper.version>1.2.5</pagehelper.version>
        <docker.image.prefix>kitty</docker.image.prefix>
        <fastjson.version>1.2.48</fastjson.version>
        <commons-lang3>3.4</commons-lang3>
        <oracle.version>11.2.0.4.0</oracle.version>
        <spring.boot.admin.version>2.0.0</spring.boot.admin.version>
    </properties>
    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- spring aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.oracle/ojdbc6 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>${oracle.version}</version>
        </dependency>
                
        <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid-spring-boot-starter</artifactId>
           <version>${com.alibaba.druid.version}</version>
        </dependency>
        <!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
        </dependency>
        <!-- pagehelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>
        <!-- fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/net.oschina.zcx7878/fastdfs-client-java -->
        <!-- fastdfs-client-java -->
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.5</version>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <!-- 打包時拷貝MyBatis的映射文件 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/sqlmap/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>  
                <directory>src/main/resources</directory>  
                    <includes> 
                        <include>**/*.*</include>  
                    </includes> 
                    <filtering>true</filtering>  
            </resource> 
        </resources>
    </build>
</project>

 

我在裏面添加了Mybatis和數據鏈接驅動,使用的日誌系統是Solf4j,log4j2git

配置文件以下:github

application.ymlweb

# Tomcat
server:
    tomcat:
        uri-encoding: UTF-8
        max-threads: 1000
        min-spare-threads: 30
    port: 8001
    session:
        timeout:7200
    context-path: /lion-admin
# DataSource
spring:
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: oracle.jdbc.driver.OracleDriver
      url: jdbc:oracle:thin:@192.168.0.205:1521:orcl
      username: gcloud_check
      password: gcloud_check
      filters: stat,wall,log4j,config
      max-active: 100
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x' FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20
# FastDFS
# ===================================================================
# 分佈式文件系統FDFS配置
# ===================================================================
fdfs:
  so-timeout: 1501
  connect-timeout: 601 
  thumb-image:             #縮略圖生成參數
    width: 150
    height: 150
  web-server-url: 192.168.0.137/
  tracker-list: 192.168.0.137:22122

 

端口:8001spring

數據使用的是:Oraclesql

注意: FastDFS的第三方客戶端包引入的時候要去除logback的包,否則與log4j2衝突,啓動會報錯docker

<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.26.5</version>
    <exclusions>
        <exclusion>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>

 

上邊的 fastdfs-client 是並不是 FastDFS Client 原做者編寫的整合包,具體詳情能夠訪問 https://github.com/tobato/FastDFS_Clientapache

log4j2-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--設置log4j2的自身log級別爲warn-->
<!--日誌級別以及優先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration後面的status,這個用於設置log4j2自身內部的信息輸出,能夠不設置,
    當設置成trace時,你會看到log4j2內部各類詳細輸出-->
<!--monitorInterval:Log4j可以自動檢測修改配置 文件和從新配置自己,設置間隔秒數-->
<configuration status="warn" monitorInterval="30">
    <!--先定義全部的appender-->
    <appenders>
        <!--這個輸出控制檯的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--輸出日誌的格式-->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </console>
        <!--文件會打印出全部信息,這個log每次運行程序會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用-->
        <File name="log" fileName="log/test.log" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>
        <!-- 這個會打印出全部的info及如下級別的信息,每次大小超過size,
        則這size大小的日誌會自動存入按年份-月份創建的文件夾下面並進行壓縮,做爲存檔-->
        <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/hpaasvc/info.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <!--控制檯只輸出level及以上級別的信息(onMatch),其餘的直接拒絕(onMismatch)-->
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
 
        <RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/hpaasvc/warn.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy屬性如不設置,則默認爲最多同一文件夾下7個文件,這裏設置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
 
        <RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/hpaasvc/error.log"
                     filePattern="${sys:user.home}/logs/hpaasvc/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="ERROR"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
 
    </appenders>
    <!--而後定義logger,只有定義了logger並引入的appender,appender纔會生效-->
    <loggers>
        <!--過濾掉spring和hibernate的一些無用的debug信息-->
        <logger name="org.springframework" level="INFO">
        </logger>
        <logger name="org.mybatis" level="INFO">
        </logger>
        <root level="INFO">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
    </loggers>
 
</configuration>

 

或者看這邊配置log4j2的整合文章SpringBoot 2.0 的Log4j2日誌信息配置

代碼

/**   
 * @author lr
 * @date 2018年12月26日 下午4:28:14 
 * @version V1.0.0   
 */
package com.louis.sql.tools;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.jmx.support.RegistrationPolicy;

@Configuration
@ComponentScan
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
@SpringBootApplication
public class ToolsApplication {

    public static void main(String[] args) {
        SpringApplication.run(ToolsApplication.class, args);
    }
}

 

FastDFSClient.java

/**   
 * @author lr
 * @date 2019年1月28日 下午1:41:39 
 * @version V1.0.0   
 */
package com.louis.sql.tools.config;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.service.FastFileStorageClient;

@Component
public class FastDFSClient {

    private final Logger logger = LoggerFactory.getLogger(FastDFSClient.class);

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    /**
     * 上傳文件
     * @param file 文件對象
     * @return 文件訪問地址
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        StorePath storePath = storageClient.uploadFile(file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
        return getResAccessUrl(storePath);
    }

    /**
     * 上傳文件
     * @param file 文件對象
     * @return 文件訪問地址
     * @throws IOException
     */
    public String uploadFile(File file) throws IOException {
        FileInputStream inputStream = new FileInputStream (file);
        StorePath storePath = storageClient.uploadFile(inputStream,file.length(), FilenameUtils.getExtension(file.getName()),null);
        return getResAccessUrl(storePath);
    }

    /**
     * 將一段字符串生成一個文件上傳
     * @param content 文件內容
     * @param fileExtension
     * @return
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream,buff.length, fileExtension,null);
        return getResAccessUrl(storePath);
    }

    // 封裝圖片完整URL地址
    private String getResAccessUrl(StorePath storePath) {
        String fileUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
        return fileUrl;
    }
    
    /**
     * 下載文件
     * @param fileUrl 文件url
     * @return
     */
    public byte[]  download(String fileUrl) {
         String group = fileUrl.substring(0, fileUrl.indexOf("/"));
         String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
         byte[] bytes = storageClient.downloadFile(group, path, new DownloadByteArray());
         return bytes;
    }

    /**
     * 刪除文件
     * @param fileUrl 文件訪問地址
     * @return
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            logger.warn(e.getMessage());
        }
    }

}

 

controller

/**   
 * @author lr
 * @date 2019年1月28日 下午1:50:47 
 * @version V1.0.0   
 */
package com.louis.sql.tools.controller;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.louis.sql.tools.config.FastDFSClient;

@RestController
@RequestMapping("/fdfs")
public class FastDFSController {
        
        @Autowired
        private FastDFSClient fdfsClient;

        /**
         * 文件上傳
         * @param file
         * @return
         * @throws Exception
         */
        @RequestMapping("/upload")
        public Map<String,Object> upload(MultipartFile file) throws Exception{
                
                String url = fdfsClient.uploadFile(file);
                
                Map<String,Object> result = new HashMap<>();
                result.put("code", 200);
                result.put("msg", "上傳成功");
                result.put("url", url);
                
                return result;
        }
        
        /**
         * 文件下載
         * @param fileUrl  url 開頭從組名開始
         * @param response
         * @throws Exception
         */
        @RequestMapping("/download")
        public void  download(String fileUrl, HttpServletResponse response) throws Exception{
                
                byte[] data = fdfsClient.download(fileUrl);
                
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("test.jpg", "UTF-8"));
        
                // 寫出
                ServletOutputStream outputStream = response.getOutputStream();
                IOUtils.write(data, outputStream);
        }
}

 

測試效果

而後經過swagger-ui的接口直接測試文件上傳功能

訪問地址:[swagger-ui首頁]http://localhost:8001/swagger-ui.html#

若是須要看源碼:https://github.com/PlayTaoist/SpringBoot2-FastDFS

新博客地址:https://www.codepeople.cn/

=======================================================================================

微信公衆號:

相關文章
相關標籤/搜索