会计数字档案馆系统从零到一部署实操手册

一、环境准备与依赖安装

在开始构建会计数字档案馆系统之前,必须先准备好基础运行环境。本系统采用Java作为后端核心语言,MySQL存储结构化数据,MinIO存储非结构化会计凭证文件。请严格按照以下步骤操作,确保环境版本一致,避免兼容性问题。

1. 基础软件安装

首先安装JDK 17和Maven 3.8+。在CentOS 7系统下,执行以下命令直接安装:

sudo yum install -y java-17-openjdk java-17-openjdk-devel

sudo yum install -y maven

安装完成后,验证版本:

java -version

mvn -v

2. 数据库与对象存储部署

为了实现快速落地,我们使用Docker容器化部署MySQL和MinIO。若未安装Docker,请先执行curl -fsSL https://get.docker.com | bash启动Docker服务。

创建一个docker-compose.yml文件,内容如下,直接复制保存:

```yaml

version: '3.8'

services:

mysql:

image: mysql:8.0

container_name: archive_mysql

environment:

MYSQL_ROOT_PASSWORD: root123456

MYSQL_DATABASE: accounting_archive

ports:

- "3306:3306"

volumes:

- mysql_data:/var/lib/mysql

minio:

image: minio/minio:latest

container_name: archive_minio

command: server /data --console-address ":9001"

environment:

MINIO_ROOT_USER: minioadmin

MINIO_ROOT_PASSWORD: minioadmin123

ports:

- "9000:9000"

- "9001:9001"

volumes:

- minio_data:/data

volumes:

mysql_data:

minio_data:

```

在文件所在目录执行启动命令:

docker-compose up -d

等待约30秒,待容器完全启动。此时MySQL已监听3306端口,MinIO控制台可通过http://服务器IP:9001访问,API端口为9000。

二、数据库表结构设计

会计数字档案馆的核心在于对电子会计凭证的结构化存储。我们需要设计一张表来记录文件元数据、会计期间以及凭证号等关键信息。请登录MySQL数据库创建表结构。

执行以下命令连接数据库:

docker exec -it archive_mysql mysql -uroot -proot123456 accounting_archive

在数据库命令行中执行以下SQL脚本,建立核心业务表:

```sql

CREATE TABLE `digital_archive` (

`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',

`original_filename` varchar(255) NOT NULL COMMENT '原始文件名',

`storage_path` varchar(500) NOT NULL COMMENT 'MinIO存储路径',

`file_hash` varchar(64) NOT NULL COMMENT '文件SHA256哈希值,用于去重',

`file_size` bigint NOT NULL COMMENT '文件大小(字节)',

`account_period` varchar(7) NOT NULL COMMENT '会计期间,格式YYYY-MM',

`voucher_no` varchar(50) DEFAULT NULL COMMENT '凭证号',

`subject_code` varchar(20) DEFAULT NULL COMMENT '会计科目编码',

`upload_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '归档时间',

PRIMARY KEY (`id`),

UNIQUE KEY `uk_file_hash` (`file_hash`),

KEY `idx_period` (`account_period`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会计数字档案表';

```

此表包含了会计档案特有的account_period(会计期间)和subject_code(科目编码),并利用file_hash建立唯一索引,防止同一份凭证重复归档。

三、后端项目搭建与配置

使用Spring Boot 3.x快速搭建后端服务。为了方便管理,我们创建一个Maven项目。

1. 项目初始化

创建项目目录结构,并编写pom.xml引入必要依赖。请确保包含Web、MyBatis、MinIO及Lombok。

以下是完整的pom.xml依赖部分:

```xml

org.springframework.boot

spring-boot-starter-web

org.mybatis.spring.boot

mybatis-spring-boot-starter

3.0.3

mysql

mysql-connector-java

8.0.32

io.minio

minio

8.5.7

org.projectlombok

lombok

true

```

2. 配置文件编写

src/main/resources/application.yml中配置数据库连接及MinIO参数。请替换IP地址为你本机的实际IP(Docker环境通常用宿主机IP)。

```yaml

server:

port: 8080

spring:

datasource:

url: jdbc:mysql://192.168.1.100:3306/accounting_archive?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

username: root

password: root123456

driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:

configuration:

map-underscore-to-camel-case: true

minio:

endpoint: http://192.168.1.100:9000

accessKey: minioadmin

secretKey: minioadmin123

bucketName: accounting-files

```

四、核心业务代码实现

本部分实现文件上传、自动计算哈希值、写入对象存储及保存元数据到数据库的全流程逻辑。

1. MinIO配置类

创建MinioConfig.java,初始化MinIO客户端并自动创建存储桶(Bucket)。

```java

import io.minio.MinioClient;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MinioConfig {

@Value("${minio.endpoint}")

private String endpoint;

@Value("${minio.accessKey}")

会计数字档案馆系统从零到一部署实操手册

private String accessKey;

@Value("${minio.secretKey}")

private String secretKey;

@Value("${minio.bucketName}")

private String bucketName;

@Bean

public MinioClient minioClient() {

return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();

}

@Bean

public String initBucket(MinioClient client) throws Exception {

boolean found = client.bucketExists(bucketName);

if (!found) {

client.makeBucket(bucketName);

}

return bucketName;

}

}

```

2. 实体类与Mapper

创建DigitalArchive.java实体类及对应的Mapper接口。

```java

import lombok.Data;

import java.util.Date;

@Data

public class DigitalArchive {

private Long id;

private String originalFilename;

private String storagePath;

private String fileHash;

private Long fileSize;

private String accountPeriod;

private String voucherNo;

private String subjectCode;

private Date uploadTime;

}

```

Mapper接口DigitalArchiveMapper.java

```java

import org.apache.ibatis.annotations.Insert;

import org.apache.ibatis.annotations.Mapper;

@Mapper

public interface DigitalArchiveMapper {

@Insert("INSERT INTO digital_archive(original_filename, storage_path, file_hash, file_size, account_period, voucher_no, subject_code) " +

"VALUES({originalFilename}, {storagePath}, {fileHash}, {fileSize}, {accountPeriod}, {voucherNo}, {subjectCode})")

int insert(DigitalArchive archive);

}

```

3. 文件上传与归档逻辑

创建ArchiveController.java,实现核心上传接口。此处包含SHA256计算和MinIO上传逻辑。

```java

import io.minio.MinioClient;

import io.minio.PutObjectArgs;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.web.bind.annotation.;

import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

import java.math.BigInteger;

import java.security.MessageDigest;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

@RestController

@RequestMapping("/api/archive")

public class ArchiveController {

@Autowired

private MinioClient minioClient;

@Autowired

private DigitalArchiveMapper mapper;

@Value("${minio.bucketName}")

private String bucketName;

@PostMapping("/upload")

public String uploadFile(@RequestParam("file") MultipartFile file,

@RequestParam("accountPeriod") String period,

@RequestParam(value = "voucherNo", required = false) String voucherNo,

@RequestParam(value = "subjectCode", required = false) String subjectCode) {

try {

String hash = calculateSHA256(file.getInputStream());

String fileName = file.getOriginalFilename();

String objectName = period + "/" + hash + "-" + fileName;

minioClient.putObject(PutObjectArgs.builder()

.bucket(bucketName)

.object(objectName)

.stream(file.getInputStream(), file.getSize(), -1)

.contentType(file.getContentType())

.build());

DigitalArchive archive = new DigitalArchive();

archive.setOriginalFilename(fileName);

archive.setStoragePath(objectName);

archive.setFileHash(hash);

archive.setFileSize(file.getSize());

archive.setAccountPeriod(period);

archive.setVoucherNo(voucherNo);

archive.setSubjectCode(subjectCode);

archive.setUploadTime(LocalDateTime.now());

mapper.insert(archive);

return "归档成功,文件ID: " + objectName;

} catch (Exception e) {

e.printStackTrace();

return "归档失败: " + e.getMessage();

}

}

private String calculateSHA256(InputStream is) throws Exception {

MessageDigest digest = MessageDigest.getInstance("SHA-256");

byte[] buffer = new byte[8192];

int read;

while ((read = is.read(buffer)) != -1) {

digest.update(buffer, 0, read);

}

byte[] hash = digest.digest();

return new BigInteger(1, hash).toString(16);

}

}

```

五、系统启动与实操验证

代码编写完毕后,进行编译打包和运行测试。

1. 编译与启动

在项目根目录下执行Maven打包命令:

mvn clean package -DskipTests

打包成功后,执行以下命令启动Spring Boot应用:

java -jar target/你的项目名-0.0.1-SNAPSHOT.jar

看到控制台输出Started Application in x.xxx seconds即表示启动成功。

2. 接口测试验证

使用curl命令模拟前端上传一份会计凭证文件。假设你当前目录有一份名为2023-10-voucher.pdf的文件。

执行以下命令进行测试:

curl -F "file=@2023-10-voucher.pdf" -F "accountPeriod=2023-10" -F "voucherNo=记-001" -F "subjectCode=6602" http://localhost:8080/api/archive/upload

预期结果:

若返回“归档成功,文件ID: 2023-10/xxxxx-2023-10-voucher.pdf”,说明文件已成功存入MinIO,且元数据已写入MySQL。

数据校验:

再次执行相同的上传命令。由于数据库中file_hash字段设有唯一索引,且代码逻辑中未处理重复异常,第二次上传会报错提示主键冲突。这证明了系统的去重机制已生效,符合会计档案“不可篡改、不重复归档”的严格要求。

AI咨询
热线电话

028-85154420

15388110056

全国售前咨询电话

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

微信扫码关注安答联动

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

安答联动档案管理系统