数字档案馆系统“最多跑一次”架构设计与技术落地指南
一、系统核心架构设计
“最多跑一次”理念在数字档案馆的落地,本质是通过技术手段实现数据多跑路、用户零跑腿。其核心是构建一个以统一数据中台为中枢、标准化服务接口为桥梁、全流程线上化为表现的系统。
1.1 技术架构蓝图
系统采用分层微服务架构,确保高内聚、低耦合,便于迭代和扩展。
- 接入层:统一门户(Web/移动端)、API网关(Kong或Spring Cloud Gateway)。
- 应用服务层:拆分为档案查询、在线借阅、证明开具、归档接收等独立微服务。
- 数据中台层:核心组件,负责元数据管理、电子档案全文检索、非结构化文件存储。
- 基础设施层:基于Docker和Kubernetes的容器化部署,使用MinIO或FastDFS进行对象存储。
1.2 关键数据流设计
用户从发起请求到获取结果的完整数据流必须无缝衔接:
- 用户通过门户或API发起请求(如查档)。
- API网关进行身份认证、路由至对应微服务。
- 微服务调用数据中台的统一数据服务接口。
- 数据中台从关系型数据库(如PostgreSQL)、搜索引擎(如Elasticsearch)、对象存储中聚合数据。
- 结果经微服务处理(如生成带电子签章的PDF)后,通过网关返回给用户。
二、环境搭建与基础服务部署
以下部署均假设在CentOS 7.9或Ubuntu 20.04 LTS服务器上进行。
2.1 依赖中间件安装
首先安装Docker和Docker Compose,这是快速部署其他服务的基础。
安装Docker Engine:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo systemctl start docker && sudo systemctl enable docker
安装Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
2.2 核心服务一键部署
创建 `docker-compose.yml` 文件,定义PostgreSQL、Elasticsearch、MinIO和Redis服务。
version: '3.8' services: postgres: image: postgres:15-alpine environment: POSTGRES_DB: digital_archive POSTGRES_USER: archivist POSTGRES_PASSWORD: YourStrong@Pass123 volumes: - pg_data:/var/lib/postgresql/data ports: - "5432:5432" elasticsearch: image: elasticsearch:8.10.2 environment: - discovery.type=single-node - xpack.security.enabled=false - "ES_JAVA_OPTS=-Xms512m -Xmx512m" volumes: - es_data:/usr/share/elasticsearch/data ports: - "9200:9200" minio: image: minio/minio:latest command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin123 volumes: - minio_data:/data ports: - "9000:9000" API端口 - "9001:9001" 控制台端口 redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data volumes: pg_data: es_data: minio_data: redis_data:
在文件所在目录执行 docker-compose up -d 启动所有服务。通过 `docker-compose ps` 检查状态。
三、数据中台与统一服务接口开发
数据中台是打破数据孤岛、实现“一窗受理”的关键。
3.1 统一元数据模型设计
在PostgreSQL中创建核心档案元数据表,这是所有服务的数据基石。
CREATE TABLE archive_metadata ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), archive_code VARCHAR(100) NOT NULL UNIQUE, -- 档案号 title VARCHAR(500) NOT NULL, -- 题名 fonds VARCHAR(200), -- 全宗 year INTEGER, -- 年度 security_level SMALLINT DEFAULT 0, -- 密级 digital_status SMALLINT DEFAULT 0, -- 数字化状态:0未数字化,1已数字化 storage_path TEXT, -- 在MinIO中的存储路径 created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_archive_code ON archive_metadata(archive_code); CREATE INDEX idx_fonds_year ON archive_metadata(fonds, year);
3.2 全文检索服务集成
使用Logstash或应用层双写,将档案元数据及OCR文本同步到Elasticsearch,实现毫秒级检索。
创建一个Spring Boot服务,集成Elasticsearch REST Client。关键配置 `application.yml`:
spring: elasticsearch: uris: http://your-server-ip:9200 digital: archive: index: name: archive_docs
实现一个简单的索引服务类:
@Service
public class ArchiveIndexService {
@Autowired
private ElasticsearchClient client;
public void indexDocument(ArchiveDoc doc) throws IOException {
IndexRequest request = IndexRequest.of(i -> i
.index("archive_docs")
.id(doc.getId())
.document(doc)
);
client.index(request);
}
public List search(String keyword) throws IOException {
SearchRequest request = SearchRequest.of(s -> s
.index("archive_docs")
.query(q -> q
.multiMatch(m -> m
.fields("title^2", "content", "fonds")
.query(keyword)
)
)
);
SearchResponse response = client.search(request, ArchiveDoc.class);
return response.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
}
}
3.3 文件存储服务封装
封装MinIO操作,为所有微服务提供统一的文件上传、下载、预览接口。

@Configuration
public class MinIOConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
@Service
public class FileStorageService {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucket-name}")
private String bucketName;
public String uploadFile(MultipartFile file, String objectName) throws Exception {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
return endpoint + "/" + bucketName + "/" + objectName;
}
}
四、关键业务微服务实现
基于上述中台能力,快速构建具体业务服务。
4.1 在线查档与证明开具服务
该服务整合检索、文件获取、电子签章和PDF生成,实现“一键办理”。
核心控制器方法:
@PostMapping("/apply/certificate")
public ResponseEntity applyCertificate(@RequestBody CertApplyRequest request, Principal principal) throws Exception {
// 1. 身份与权限验证(集成统一身份认证)
// 2. 调用数据中台服务,检索并验证档案信息
ArchiveDoc doc = dataPlatformService.retrieveArchive(request.getArchiveCode());
// 3. 从MinIO获取原文文件(如需要)
byte[] originalFile = fileStorageService.download(doc.getStoragePath());
// 4. 使用IText或Apache PDFBox生成标准证明文件,并嵌入电子签章图片或数字签名
byte[] certificatePdf = pdfGenerateService.generateCertificate(doc, originalFile, principal.getName());
// 5. 将生成的证明文件回传至MinIO存档,并记录流水
String certPath = fileStorageService.uploadCertificate(certificatePdf, generateCertFileName());
archivePlatformService.logAccess(principal.getName(), request.getArchiveCode(), "CERT_APPLY", certPath);
// 6. 将PDF字节流直接返回给前端,实现浏览器直接下载
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDisposition(ContentDisposition.attachment().filename("档案证明.pdf").build());
return new ResponseEntity<>(certificatePdf, headers, HttpStatus.OK);
}
4.2 统一网关与API管理
使用Spring Cloud Gateway配置路由、认证和限流,确保前端只有一个入口。
spring: cloud: gateway: routes: - id: archive-query-service uri: lb://archive-query-service predicates: - Path=/api/query/ filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 - StripPrefix=1 - id: certificate-service uri: lb://certificate-service predicates: - Path=/api/cert/ filters: - StripPrefix=1 globalcors: cors-configurations: '[/]': allowedOrigins: "" allowedMethods: - GET - POST
五、前端统一门户快速集成
前端采用Vue 3 + Element Plus,通过调用统一的API网关地址与后端交互。
5.1 核心查档功能组件实现
创建一个 `ArchiveSearch.vue` 组件,实现实时搜索和结果展示。
查看 申请证明
六、部署上线与运维要点
将开发完成的所有微服务打包为Docker镜像,通过编排文件部署。
6.1 应用Docker化
为每个Spring Boot服务创建 `Dockerfile`。
FROM openjdk:17-jdk-slim
VOLUME /tmp
ARG JAR_FILE=target/.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
在项目根目录执行 docker build -t archive-query-service:v1 .
6.2 生产环境编排
创建生产环境的 `docker-compose.prod.yml`,集成所有微服务、网关和配置中心。
version: '3.8' services: api-gateway: image: archive-gateway:v1 ports: - "80:8080" depends_on: - archive-query - certificate-service environment: - SPRING_PROFILES_ACTIVE=prod archive-query: image: archive-query-service:v1 environment: - DB_HOST=postgres - ES_HOST=elasticsearch certificate-service: image: certificate-service:v1 ... 其他服务类似 之前定义的基础设施服务(PostgreSQL, Elasticsearch等)也需要包含在内
使用 docker-compose -f docker-compose.prod.yml up -d 启动整个生产环境栈。
6.3 核心运维监控配置
在Spring Boot应用中集成Actuator和Prometheus监控。
在 `pom.xml` 中添加依赖:
org.springframework.boot spring-boot-starter-actuator io.micrometer micrometer-registry-prometheus
在 `application-prod.yml` 中开启端点:
management: endpoints: web: exposure: include: health,info,prometheus,metrics metrics: export: prometheus: enabled: true
访问 `http://你的服务IP:端口/actuator/prometheus` 即可获取监控指标,将其配置到Prometheus Server中进行抓取,再通过Grafana展示。