基于SpringBoot构建数据交换文书档案系统实战

一、环境准备与依赖搭建

在开始构建数据交换文书档案系统之前,我们需要准备好基础运行环境。为了保证零门槛落地,本指南采用Docker容器化技术来部署数据库和文件存储服务,避免繁琐的手动安装配置。

1.1 基础服务容器化部署

请确保服务器已安装Docker和Docker Compose。创建一个docker-compose.yml文件,直接复制以下内容。该配置将启动PostgreSQL数据库(用于存储文书元数据)和MinIO对象存储服务(用于存储PDF、Word等文书实体文件)。

version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: archive_db
environment:
POSTGRES_DB: archive_system
POSTGRES_USER: admin
POSTGRES_PASSWORD: StrongPassword123
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
minio:
image: minio/minio:latest
container_name: archive_storage
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- miniodata:/data
volumes:
pgdata:
miniodata:

在终端执行以下命令启动服务:

docker-compose up -d

1.2 项目初始化与Maven依赖

使用Spring Initializr生成项目,或者直接在已有的Maven项目中配置pom.xml。我们需要引入Web、JPA、PostgreSQL驱动、MinIO客户端以及Lombok依赖。请确保pom.xml包含以下完整依赖配置:



org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-data-jpa


org.postgresql
postgresql
runtime


io.minio
minio
8.5.7


org.projectlombok
lombok
true


二、数据库设计与持久化层

数据交换的核心在于对文书元数据的精准管理。我们需要设计一张表来记录文书的标题、发送方、接收方、文件哈希值以及存储路径。

2.1 数据表结构SQL

连接到PostgreSQL数据库(可使用DBeaver或命令行),执行以下SQL脚本初始化数据表。这里使用UUID作为主键,确保分布式环境下的唯一性。

CREATE TABLE doc_archive (
id UUID PRIMARY KEY,
title VARCHAR(255) NOT NULL,
sender_unit VARCHAR(100) NOT NULL,
receiver_unit VARCHAR(100) NOT NULL,
file_name VARCHAR(255) NOT NULL,
file_size BIGINT,
file_path VARCHAR(500),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) DEFAULT 'EXCHANGED'
);
COMMENT ON TABLE doc_archive IS '数据交换文书档案表';
COMMENT ON COLUMN doc_archive.sender_unit IS '发送单位代码';
COMMENT ON COLUMN doc_archive.receiver_unit IS '接收单位代码';

2.2 实体类与Repository

在Java项目中创建对应的实体类DocArchive.java和Repository接口。注意,JPA会自动映射下划线命名风格到驼峰命名风格。

package com.archive.entity;
import jakarta.persistence.;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.UUID;
@Data
@Entity
@Table(name = "doc_archive")
public class DocArchive {
@Id
@Column(name = "id", updatable = false, nullable = false)
private UUID id = UUID.randomUUID();
@Column(name = "title", nullable = false)
private String title;
@Column(name = "sender_unit", nullable = false)
private String senderUnit;
@Column(name = "receiver_unit", nullable = false)
private String receiverUnit;
@Column(name = "file_name", nullable = false)
private String fileName;
@Column(name = "file_size")
private Long fileSize;
@Column(name = "file_path")
private String filePath;
@Column(name = "create_time", updatable = false)
private LocalDateTime createTime;
@Column(name = "status")
private String status;
}
package com.archive.repository;
import com.archive.entity.DocArchive;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.UUID;
@Repository
public interface DocArchiveRepository extends JpaRepository {
}

三、对象存储服务配置

MinIO作为高性能的对象存储,将负责实际的文件落盘。我们需要配置MinIO客户端,并封装文件上传和下载的底层逻辑。

3.1 配置文件与客户端Bean

application.yml中添加数据库和MinIO的连接配置。请确保端点地址与Docker Compose配置一致。

spring:
datasource:
url: jdbc:postgresql://localhost:5432/archive_system
username: admin
password: StrongPassword123
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: none
show-sql: true
minio:
endpoint: http://localhost:9000
access-key: minioadmin
secret-key: minioadmin
bucket-name: archive-docs

创建配置类MinioConfig.java,初始化MinIO客户端并检查存储桶是否存在。

基于SpringBoot构建数据交换文书档案系统实战

package com.archive.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}

3.2 文件操作服务层

创建MinioService.java,封装上传文件和获取文件流的逻辑。上传时使用UUID重命名文件以防止冲突,同时保留原始扩展名。

package com.archive.service;
import com.archive.config.MinioConfig;
import io.minio.;
import io.minio.messages.PutObjectArgs;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class MinioService {
private final MinioClient minioClient;
private final MinioConfig minioConfig;
public String uploadFile(MultipartFile file) throws Exception {
String bucketName = minioConfig.getBucketName();
// 确保存储桶存在
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
// 生成唯一文件名:UUID + 原始扩展名
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = UUID.randomUUID() + extension;
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
return objectName;
}
public InputStream downloadFile(String objectName) throws Exception {
return minioClient.getObject(
GetObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(objectName)
.build()
);
}
}

四、业务接口实现

我们需要编写Controller层来对外提供RESTful API。系统需要提供两个核心接口:文书归档上传文书档案下载

4.1 文书归档上传接口

该接口接收文件流以及相关的业务元数据(标题、发送方、接收方)。操作逻辑为:先将文件上传至MinIO获取存储路径,再将元数据保存至PostgreSQL。

package com.archive.controller;
import com.archive.entity.DocArchive;
import com.archive.repository.DocArchiveRepository;
import com.archive.service.MinioService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/api/archive")
@RequiredArgsConstructor
public class ArchiveController {
private final MinioService minioService;
private final DocArchiveRepository repository;
@PostMapping("/upload")
public ResponseEntity uploadArchive(
@RequestParam("file") MultipartFile file,
@RequestParam("title") String title,
@RequestParam("senderUnit") String senderUnit,
@RequestParam("receiverUnit") String receiverUnit) {
try {
// 1. 上传文件到对象存储
String storedObjectName = minioService.uploadFile(file);
// 2. 构建数据库实体
DocArchive archive = new DocArchive();
archive.setTitle(title);
archive.setSenderUnit(senderUnit);
archive.setReceiverUnit(receiverUnit);
archive.setFileName(file.getOriginalFilename());
archive.setFileSize(file.getSize());
archive.setFilePath(storedObjectName);
archive.setCreateTime(LocalDateTime.now());
archive.setStatus("EXCHANGED");
// 3. 保存元数据
repository.save(archive);
return ResponseEntity.ok("文书归档成功,ID: " + archive.getId());
} catch (Exception e) {
return ResponseEntity.internalServerError().body("归档失败: " + e.getMessage());
}
}
}

4.2 文书档案下载接口

该接口根据文书ID查询元数据,获取对象存储中的文件路径,并将文件流输出给前端。

    @GetMapping("/download/{id}")
public ResponseEntity downloadArchive(@PathVariable UUID id) {
try {
DocArchive archive = repository.findById(id)
.orElseThrow(() -> new RuntimeException("文书不存在"));
InputStream inputStream = minioService.downloadFile(archive.getFilePath());
byte[] content = inputStream.readAllBytes();
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=\"" + archive.getFileName() + "\"")
.body(content);
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
}

五、系统验证与测试

完成代码编写后,启动Spring Boot应用。使用curl命令进行零代码界面测试,验证数据交换流程是否通畅。

1. 模拟发送单位上传文书:

准备一个测试文件test_doc.pdf,执行以下命令:

curl -X POST "http://localhost:8080/api/archive/upload" \
-F "file=@/path/to/test_doc.pdf" \
-F "title=2023年度技术交接文档" \
-F "senderUnit=UNIT_A" \
-F "receiverUnit=UNIT_B"

成功后将返回:文书归档成功,ID: [具体UUID]。请记录下返回的UUID。

2. 模拟接收单位下载文书:

使用上一步返回的UUID替换下方的{YOUR_UUID}

curl -X GET "http://localhost:8080/api/archive/download/{YOUR_UUID}" --output downloaded_file.pdf

执行完毕后,检查当前目录下生成的downloaded_file.pdf,确保文件内容完整且可打开。至此,一个基于SpringBoot的数据交换文书档案系统已完全落地。

AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

扫码咨询
安答联动微信公众号二维码

微信扫码关注安答联动

申请试用
热线电话
申请试用

安答联动档案管理系统