一、环境容器化部署基础
为了解决传统档案管理系统环境依赖复杂、部署困难的问题,我们首先采用Docker容器化技术统一基础设施。以下操作基于CentOS 7系统,请确保已安装Docker及Docker Compose。
1. 安装Docker与Docker Compose
如果尚未安装,执行以下命令一键安装:
```bash
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
systemctl start docker && systemctl enable docker
curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```
2. 编写基础环境编排文件
创建目录/data/archives,并在其中创建docker-compose.yml文件。该文件将定义MySQL、Redis及Elasticsearch服务,为后续微服务提供数据存储与检索支持。
```yaml
version: '3.8'
services:
mysql:
image: mysql:5.7
container_name: archives-mysql
environment:
MYSQL_ROOT_PASSWORD: root@123
MYSQL_DATABASE: archives_db
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf/my.cnf:/etc/mysql/my.cnf
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
redis:
image: redis:6.2-alpine
container_name: archives-redis
ports:
- "6379:6379"
volumes:
- ./redis/data:/data
command: redis-server --appendonly yes
elasticsearch:
image: elasticsearch:7.17.5
container_name: archives-es
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
- "9300:9300"
volumes:
- ./es/data:/usr/share/elasticsearch/data
```
3. 启动基础服务
在/data/archives目录下执行:
```bash
docker-compose up -d
```
执行docker-compose ps确认所有服务状态为Up。此时,数据库、缓存及搜索引擎已就绪。
二、数据库结构迁移与优化
传统系统往往存在表结构设计不规范的问题。在升级改造中,我们需要建立符合微服务规范的Schema。这里以核心的“档案目录表”为例进行重构。
1. 创建初始化SQL脚本
在/data/archives/mysql/init目录下创建init.sql,添加以下结构化DDL语句。该设计增加了用于全文检索的content_text字段及用于逻辑删除的标记。
```sql
USE archives_db;
DROP TABLE IF EXISTS `archive_catalog`;
CREATE TABLE `archive_catalog` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`archive_no` varchar(64) NOT NULL COMMENT '档案编号',
`title` varchar(255) NOT NULL COMMENT '案卷题名',
`category_code` varchar(32) DEFAULT NULL COMMENT '分类代码',
`file_path` varchar(512) DEFAULT NULL COMMENT '电子文件存储路径',
`content_text` text COMMENT 'OCR识别后的全文内容',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除 0-未删 1-已删',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_archive_no` (`archive_no`),
KEY `idx_category` (`category_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='档案目录表';
```
2. 执行数据导入
将旧系统的数据导出为CSV,并通过以下命令导入新表(假设旧数据已清理完毕,仅演示导入新结构):
```bash
docker exec -i archives-mysql mysql -uroot -proot@123 archives_db < /data/archives/mysql/init/init.sql
```
三、核心微服务架构搭建
我们将后端重构为基于Spring Boot的微服务架构。本指南展示如何构建archive-core服务,包含档案的增删改查基础能力。
1. 项目依赖配置
创建Maven项目,pom.xml中引入核心依赖。请确保使用JDK 8或JDK 11。
```xml
org.springframework.boot
spring-boot-starter-web
2.7.14
org.springframework.boot
spring-boot-starter-data-jpa
2.7.14
mysql
mysql-connector-java
8.0.33
org.springframework.boot
spring-boot-starter-data-redis
2.7.14
org.springframework.boot
spring-boot-starter-data-elasticsearch
2.7.14
org.projectlombok
lombok
1.18.28
provided
```
2. 应用配置文件
在src/main/resources/application.yml中配置数据源连接信息,连接至第一步启动的Docker容器服务。
```yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://192.168.1.100:3306/archives_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: root@123
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
format_sql: true
redis:
host: 192.168.1.100
port: 6379
elasticsearch:
rest:
uris: http://192.168.1.100:9200
``>
3. 核心实体类与接口开发

创建ArchiveCatalog实体类,对应数据库表结构。
```java
package com.archives.entity;
import lombok.Data;
import javax.persistence.;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "archive_catalog")
public class ArchiveCatalog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "archive_no", unique = true, nullable = false, length = 64)
private String archiveNo;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "category_code", length = 32)
private String categoryCode;
@Column(name = "file_path", length = 512)
private String filePath;
@Column(name = "content_text", columnDefinition = "TEXT")
private String contentText;
@Column(name = "create_time", updatable = false)
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@Column(name = "is_deleted")
private Boolean isDeleted = false;
}
```
创建Repository接口,继承JpaRepository以获得基础CRUD能力。
```java
package com.archives.repository;
import com.archives.entity.ArchiveCatalog;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ArchiveCatalogRepository extends JpaRepository
{
}
```
4. 业务逻辑层实现
在Service层实现档案的入库逻辑,同时加入Redis缓存策略,减轻数据库压力。
```java
package com.archives.service;
import com.archives.entity.ArchiveCatalog;
import com.archives.repository.ArchiveCatalogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class ArchiveService {
@Autowired
private ArchiveCatalogRepository repository;
@Autowired
private RedisTemplate redisTemplate;
private static final String CACHE_KEY_PREFIX = "archive:";
public ArchiveCatalog saveArchive(ArchiveCatalog archive) {
ArchiveCatalog saved = repository.save(archive);
// 清除或更新缓存
redisTemplate.opsForValue().set(CACHE_KEY_PREFIX + saved.getId(), saved, 1, TimeUnit.HOURS);
return saved;
}
public ArchiveCatalog getArchiveById(Long id) {
String key = CACHE_KEY_PREFIX + id;
// 先查缓存
ArchiveCatalog cached = (ArchiveCatalog) redisTemplate.opsForValue().get(key);
if (cached != null) {
return cached;
}
// 查数据库
ArchiveCatalog archive = repository.findById(id).orElse(null);
if (archive != null) {
redisTemplate.opsForValue().set(key, archive, 1, TimeUnit.HOURS);
}
return archive;
}
}
```
四、全文检索功能集成
档案管理的核心痛点是“全文检索”。我们将利用Elasticsearch实现毫秒级的文本搜索能力。
1. 定义ES文档实体
创建ArchiveDocument类,使用@Document注解映射到Elasticsearch索引。
```java
package com.archives.document;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@Document(indexName = "archives_index")
public class ArchiveDocument {
@Id
private Long id;
@Field(type = FieldType.Keyword)
private String archiveNo;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String contentText;
}
```
2. 实现数据同步逻辑
修改ArchiveService,在保存数据到MySQL后,异步同步数据到Elasticsearch。这里演示同步调用,生产环境建议使用消息队列。
```java
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate; // 或者 Repository
public ArchiveCatalog saveArchive(ArchiveCatalog archive) {
ArchiveCatalog saved = repository.save(archive);
// 构造ES文档
ArchiveDocument document = new ArchiveDocument();
document.setId(saved.getId());
document.setArchiveNo(saved.getArchiveNo());
document.setTitle(saved.getTitle());
document.setContentText(saved.getContentText());
// 保存到ES
elasticsearchRestTemplate.save(document);
redisTemplate.opsForValue().set(CACHE_KEY_PREFIX + saved.getId(), saved, 1, TimeUnit.HOURS);
return saved;
}
``>
3. 搜索接口实现
增加搜索方法,支持对题名和全文内容的混合检索。
```java
public List searchArchives(String keyword) {
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "contentText"))
.build();
SearchHits searchHits = elasticsearchRestTemplate.search(query, ArchiveDocument.class);
return searchHits.getSearchHits().stream()
.map(SearchHit::getContent)
.collect(Collectors.toList());
}
```
五、服务打包与容器运行
我们将编写好的Spring Boot应用打包为Docker镜像,实现统一编排管理。
1. 编写Dockerfile
在项目根目录创建Dockerfile。
```dockerfile
FROM openjdk:8-jre-alpine
VOLUME /tmp
COPY target/archive-core-1.0.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
```
2. 构建镜像
执行Maven打包命令,并构建Docker镜像。
```bash
mvn clean package -DskipTests
docker build -t archives-service:1.0 .
```
3. 更新编排文件
将新服务加入到之前的docker-compose.yml中,实现一键拉起整套系统。
```yaml
... 其他服务配置
app:
image: archives-service:1.0
container_name: archives-app
ports:
- "8080:8080"
depends_on:
- mysql
- redis
- elasticsearch
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/archives_db?useUnicode=true&characterEncoding=utf8
- SPRING_REDIS_HOST=redis
- SPRING_ELASTICSEARCH_REST_URIS=http://elasticsearch:9200
```
4. 启动完整系统