Go-Spring 入門篇(六)

李輕水 發表於 2021-12-04
Spring Go

序言

示例程式碼後續會提交到 Github 上

上章 Go-Spring 入門篇(五) 講到對上傳服務的抽象,完成了 controlerservice 的解耦。

本章我們實現一個物件儲存和本地檔案儲存能力的更換,通過 go-spring 提供的 Condition 來限制 Bean 的註冊以及動態設定配置項。

Minio

使用 minio 作為遠端物件儲存服務。

docker-compose

這裡我們通過 docker 快速的建立一個本地 minio 服務。

version: "3"
services:
  minio:
    image: bitnami/minio:latest
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      - MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE
      - MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
      - BITNAMI_DEBUG=true

config/application.properties

新增 minio 配置。

# minio
minio.enable=true
minio.host=127.0.0.1
minio.port=9000
minio.access=AKIAIOSFODNN7EXAMPLE
minio.secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
minio.secure = false
minio.bucket=gs-demo

modules/minio/minio.go

註冊 minio 啟動器。

package minio

import (
    "context"
    "fmt"
    "github.com/go-spring/spring-base/log"
    "github.com/go-spring/spring-core/gs"
    "github.com/go-spring/spring-core/gs/cond"
    "github.com/minio/minio-go/v7"
    "github.com/minio/minio-go/v7/pkg/credentials"
)

type MinioConfig struct {
    Enable bool   `value:"${minio.enable:=true}"`    // 是否啟用 HTTP
    Host   string `value:"${minio.host:=127.0.0.1}"` // HTTP host
    Port   int    `value:"${minio.port:=9000}"`      // HTTP 埠
    Access string `value:"${minio.access:=}"`        // Access
    Secret string `value:"${minio.secret:=}"`        // Secret
    Secure bool   `value:"${minio.secure:=true}"`    // Secure
    Bucket string `value:"${minio.bucket:=}"`
}

func init() {

    gs.Provide(clientMinio).
        // Bean 名稱
        Name("minio-client").
        // cond.OnProperty 會檢查配置項
        On(cond.OnProperty("minio.enable", cond.HavingValue("true")))
}

func clientMinio(config MinioConfig) *minio.Client {
    // 建立 minio 物件
    client, err := minio.New(fmt.Sprintf("%s:%d", config.Host, config.Port), &minio.Options{
        Creds:  credentials.NewStaticV4(config.Access, config.Secret, ""),
        Secure: config.Secure,
    })

    if err != nil {
        panic("minio client error" + err.Error())
    }

    // 建立儲存桶
    err = client.MakeBucket(context.Background(), config.Bucket, minio.MakeBucketOptions{
        // 嘻嘻,這個桶是外太空的
        Region:        "waitaikong",
        ObjectLocking: false,
    })

    if err != nil {
        panic(fmt.Sprintf("make %s bucket error: %v", config.Bucket, err))
    }

    log.Infof("%v", client.EndpointURL())
    return client
}

記得收集匯入到 main.go

services/services.go

本地儲存 service 需要在沒有註冊 minio-client 的情況才註冊。

package services

import (
    "github.com/minio/minio-go/v7"
    "learn/services/filesystem/local"
    fminio "learn/services/filesystem/minio"
    "learn/types"

    "github.com/go-spring/spring-core/gs"
    "github.com/go-spring/spring-core/gs/cond"
)

func init() {

    gs.Object(new(local.Service)).
        Export((*types.FileProvider)(nil)).
        // 本地儲存,當 minio 不存在時才註冊
        // 可以新增其它判斷條件,例如 aliyun 等
        On(cond.Group(cond.And, cond.OnMissingBean((*minio.Client)(nil))))

    gs.Object(new(fminio.Service)).
        Export((*types.FileProvider)(nil)).
        // 當 minio-client 物件存在時
        On(cond.OnBean((*minio.Client)(nil)))
}

services/filesystem/minio/minio.go

package minio

import (
    // ...
    "github.com/minio/minio-go/v7"
)

type Service struct {
    // 自動注入 minio-client
    Client *minio.Client `autowire:""`
    // 儲存桶
    Bucket string `value:"${minio.bucket}"`
    // 儲存路徑
    Dir string `value:"${file.dir}"`
}

func (s *Service) PutObject(name string, r io.Reader, size int64) (string, error) {
    // ...
}

func (s *Service) ExistsObject(name string) bool {
    // ...
}

然後啟動 docker-compose up -d minio 啟動 minio 服務。
重新執行 go run main.go 並測試,功能正常。

$ curl -F "[email protected]/1.jpg" http://127.0.0.1:8080/upload
$ {"code":0,"data":{"url":"temp/1.jpg"},"msg":"上傳檔案成功"}

$ curl -F "[email protected]/1.jpg" http://127.0.0.1:8080/upload
$ {"code":-1,"msg":"檔案已存在,請勿重複上傳"}

上傳後,通過 127.0.0.1:9001 在瀏覽器開啟 minio 的管理介面,可以發現檔案已經上傳成功。

Go-Spring 入門篇(六)

修改 config/application.propertiesminio.enable 可以切換儲存能力。

到此我們的入門篇就結束了。

謝謝大家,嘻嘻!

官網及交流

Go-Spring 官網
Github

本作品採用《CC 協議》,轉載必須註明作者和本文連結