Self - file

file

字段类型说明
idlong, primary key自增主键
file_idvarchar, business key业务主键,文件Id
fs_keyvarchar文件存储key
file_md5varchar文件md5
create_timedatetime创建时间
update_timedatetime更新时间

file_owner

字段类型说明
idlong, primary key自增主键
file_idvarchar, business key业务主键,文件Id
file_namevarchar文件名
file_typevarchar文件类型
statusinteger状态;0失效,1有效,2排队中,3上传中,4下载中,-3上传失败,-4下载失败
owner_idvarchar拥有者Id
create_timedatetime创建时间
update_timedatetime更新时间

file_download

字段类型说明
idlong, primary key自增主键
file_download_idvarchar, business key业务主键,文件下载Id
file_idvarchar, business key业务主键,文件Id
file_origin_pathvarchar原始文件路径
download_retry_timesinteger重试次数
callback_requiredinteger是否需要回调
callback_urlvarchar回调URL
callback_retry_timeinteger回调重试次数
callback_statusinteger回调状态;0等待回调,1回调成功,-1回调失败
callback_resultvarchar回调结果
create_timedatetime创建时间
update_timedatetime更新时间

注意的点

  1. 封装SDK
  2. 客户端登记文件,直传存储引擎,再次确认状态

流程图

  1. 客户端上传

  1. 客户端提交

新建项目

init

1
    spring init --groupId=com.weasley --artifactId=file-center --name=file-center --description="file-center" file-center

module

根目录 setting.gradle

1
2
3
4
    include 'file-center-common'
    include 'file-center-domain'
    include 'file-center-application'
    include 'file-center-interface'

根目录 build.gradle

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// 定义项目构建所需的仓库和依赖项
// 定义项目构建所需的仓库和依赖项
buildscript {

	repositories {
		mavenCentral()
	}

	dependencies {
		classpath('org.springframework.boot:spring-boot-gradle-plugin:3.0.4')
	}
}

plugins {
	id 'java'
	id 'groovy'
	id 'java-library'
	id 'org.springframework.boot' version '3.0.4'
	id 'io.spring.dependency-management' version '1.1.0'
}


allprojects{
	group = 'com.weasley'
	version = '0.0.1-SNAPSHOT'
	sourceCompatibility = '17'

	repositories {
		mavenCentral()
	}

	dependencyManagement {
		imports {
			mavenBom 'org.springframework.boot:spring-boot-dependencies:3.0.4'
		}
	}
}

subprojects {

	apply plugin: 'java'
	apply plugin: 'java-library'
	apply plugin: 'groovy'
	apply plugin: 'org.springframework.boot'
	apply plugin: 'io.spring.dependency-management'

	dependencies {

		implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web'

		implementation 'org.springframework.boot:spring-boot-starter'
		testImplementation 'org.springframework.boot:spring-boot-starter-test'

		// devtools
		compileOnly 'org.springframework.boot:spring-boot-devtools'

		// lombok
		compileOnly 'org.projectlombok:lombok:1.18.26'
		annotationProcessor 'org.projectlombok:lombok:1.18.26'

		// spring-boot-configuration-processor
		annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
		// spring-boot-starter-validation
		implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '3.0.4'
		// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator
		implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '3.0.5'


		// mapstruct
		implementation 'org.mapstruct:mapstruct:1.5.3.Final'
		annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'

		// knife4j
		implementation group: 'com.github.xiaoymin', name: 'knife4j-openapi3-jakarta-spring-boot-starter', version: '4.1.0'

		// mybatis plus
		implementation group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.5.3.1'
		implementation group: 'com.baomidou', name: 'mybatis-plus-generator', version: '3.5.3.1'
		implementation group: 'org.freemarker', name: 'freemarker', version: '2.3.31'
		implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.32'

		// spock
		testImplementation group: 'org.spockframework', name: 'spock-core', version: '2.3-groovy-4.0'
		testImplementation group: 'org.spockframework', name: 'spock-spring', version: '2.3-groovy-4.0'

		// h2
		testImplementation group: 'com.h2database', name: 'h2', version: '2.1.214'

		// embedded-redis
		testImplementation (group: 'it.ozimov', name: 'embedded-redis', version: '0.7.3' ) {
			exclude group: 'org.slf4j', module: 'slf4j-simple'
		}

		// redission
		implementation group: 'org.redisson', name: 'redisson-spring-boot-starter', version: '3.20.0'

		// https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine
		implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '3.1.5'

		// hutool-core
		implementation group: 'cn.hutool', name: 'hutool-core', version: '5.8.15'
		implementation group: 'cn.hutool', name: 'hutool-extra', version: '5.8.16'


		// minio
		implementation group: 'io.minio', name:'minio', version: '8.4.3'

		// vavr
		implementation group: 'io.vavr', name: 'vavr', version: '0.10.4'

		implementation group: 'org.apache.skywalking', name: 'apm-toolkit-logback-1.x', version: '8.15.0'

		// https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path
		implementation group: 'com.jayway.jsonpath', name: 'json-path', version: '2.8.0'
	}

	tasks.named('test') {
		useJUnitPlatform()
	}
}

file-center-common

1
2
3
    1) mkdir file-center-common
    2) mkdir -p src/main/java/com/weasley/common
    3) mkdir -p src/main/resources 

file-center-domain

1
2
3
    1) mkdir file-center-domain
    2) mkdir -p src/main/java/com/weasley/domain
    3) mkdir -p src/main/resources 

file-center-application

1
2
3
    1) mkdir file-center-application
    2) mkdir -p src/main/java/com/weasley/application
    3) mkdir -p src/main/resources 

file-center-interface

1
2
3
    1) mkdir file-center-interface
    2) mkdir -p src/main/java/com/weasley/interface
    3) mkdir -p src/main/resources 

file-center-infrastructure

1
2
3
    1) mkdir file-center-infrastructure
    2) mkdir -p src/main/java/com/weasley/infrastructure
    3) mkdir -p src/main/resources 

boot scripts

logback

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <springProperty scope="context" name="spring.application.name" source="spring.application.name"/>


    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="logging.path" value="log"/>

    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${PID:- }]){magenta} %clr([%X{tid}]){magenta} %clr([%X{requestId}]){magenta} %clr([%X{requestPath}]){magenta} %clr([%X{requestIp}]){magenta} %clr(---){faint} %clr([%15.15t]){faint}%clr([%X{chainId}]){faint}%clr([%X{stageId}]){faint} %clr(%-50.50logger{49}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

    <property name="ROLL_FILE_LOG_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} [${PID:- }] [%X{tid}] [%X{requestId}] [%X{requestPath}] [%X{requestIp}] --- [%t][%X{chainId}][%X{stageId}] %-50.50logger{49} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 日志输出编码 -->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 控制台异步输出 -->
    <appender name="STDOUTASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACTDEBUGINFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>512</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="STDOUT"/>
    </appender>

    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logging.path}/${spring.application.name}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${logging.path}/${spring.application.name}.log.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <MaxHistory>7</MaxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <!--格式化输出:%d表示日期%thread表示线程名%msg:日志消息,%n是换行符-->
                <pattern>${ROLL_FILE_LOG_PATTERN}</pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 日志文件异步输出 -->
    <appender name="FILEASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACTDEBUGINFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>512</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="FILE"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUTASYNC"/>
        <appender-ref ref="FILEASYNC"/>
    </root>

</configuration>

docs

SQL generate

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.junit.jupiter.api.Test;

import java.util.Collections;

public class CodeGenerator {

    @Test
    public void generator() {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/file_center?serverTimezone=Asia/Shanghai", "", "")
                .globalConfig(builder -> {
                    builder.author("baomidou") // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("/Users/disco/Downloads/outputFileCenter"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
                            .moduleName("system") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml, "/Users/disco/Downloads/outputFileCenter")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude(Collections.emptyList()); // 设置需要生成的表名
//                            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

7.application.yml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
spring:
  application:
    name: file_center
  profiles:
    active: test
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  datasource:
    url: jdbc:mysql://localhost:3306/file_center?serverTimezone=Asia/Shanghai
    username: root
    password: platform123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  servlet:
    multipart:
      enabled: true
      max-file-size: 100MB
      max-request-size: 200MB
  data:
    redis:
      timeout: 1000
      host: 127.0.0.1
      port: 6379
      password: YpWcTLkW
      lettuce:
        pool:
          max-active: 100
          max-wait: 500
          max-idle: 10
          min-idle: 10
          time-between-eviction-runs: 10s
lock:
  engine: lock-caffeine
  timeout-seconds: 1
  expire-seconds: 120
  caffeine:
    capacity: 10000
    maximum-size: 20000
storage:
  engine: storage-minio
  local:
    enabled: true
    region: asia
    bucket: file-center
  minio:
    enabled: true
    region: zh-cn-beijing
    bucket: file-center
    endpoint: http://127.0.0.1:9000
    sslEnable: false
    accessKey: 4MrQwqp2WyeAh33S
    secretKey: DCA3sYbWHZlAcwcEHD1foRRVcbiSqqrX
custom:
  executor:
    configs:
      stage-download:
        executor-name: stage-download
        queue-capacity: 100
        core-pool-size: 40
        max-pool-size: 100
        allow-core-Thread-time-out: false
        keep-alive-seconds: 20
        await-termination: false
        await-termination-seconds: 5000
        abort-policy: block
      stage-upload:
        executor-name: stage-upload
        queue-capacity: 200
        core-pool-size: 40
        max-pool-size: 100
        allow-core-Thread-time-out: false
        keep-alive-seconds: 20
        await-termination: false
        await-termination-seconds: 5000
        abort-policy: block
      stage-callback:
        executor-name: stage-callback
        queue-capacity: 300
        core-pool-size: 40
        max-pool-size: 100
        allow-core-Thread-time-out: false
        keep-alive-seconds: 20
        await-termination: false
        await-termination-seconds: 5000
        abort-policy: block
      http-callback:
        executor-name: dispatcher-http-callback
        queue-capacity: 400
        core-pool-size: 40
        max-pool-size: 100
        allow-core-Thread-time-out: false
        keep-alive-seconds: 20
        await-termination: false
        await-termination-seconds: 5000
        abort-policy: block
  http:
    configs:
      http-callback:
        client-name: http-callback
        dispatcher-executor-name: dispatcher-http-callback
        call-timeout-milliseconds: 1000
        connect-timeout-milliseconds: 1000
        readTimeoutMilliseconds: 1000
        writeTimeoutMilliseconds: 1000
        connectionMaxPoolSize: 100
        keepAliveSeconds: 20
        maxRequests: 300
        maxRequestsPerHost: 50
mybatis-plus:
  mapper-locations: classpath:mappers/*.xml
  type-aliases-package: com.weasley.infrastructure.db.model
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
swagger:
  enable: true
knife4j:
  enable: true
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,threadpool
        exclude: shutdown
monitor:
  log:
    enable: true
  report:
    enable: true

file-center-common

ErrorCode

Response

Global Exception

Response advice

Submodule build.gradle

1
2
3
4
## unittest
tasks.named('test') {
	useJUnitPlatform()
}
comments powered by Disqus