档案应急处置:别让文件变成一锅粥
老铁们,今天咱不聊风花雪月,聊聊咱办公室里那些“沉默的祖宗”——档案。平时它们躺在那岁月静好,可一旦出点幺蛾子,比如水管爆了、服务器抽风了,或者哪个新来的小同事手一抖咖啡泼了上去,那场面,简直比过年家...
2026年06月26日 01:20:20
本系统采用微服务架构,确保高可用性与可扩展性。前端使用Vue 3 + Element Plus构建响应式界面,后端采用Spring Boot 2.7 + Spring Cloud Alibaba 2021.0.4,数据库使用MySQL 8.0.33与MongoDB 6.0.8,文件存储采用MinIO 2023.9.4。
安装JDK 17.0.8:
``` wget https://download.oracle.com/java/17/archive/jdk-17.0.8_linux-x64_bin.tar.gz tar -xzf jdk-17.0.8_linux-x64_bin.tar.gz export JAVA_HOME=/path/to/jdk-17.0.8 export PATH=$JAVA_HOME/bin:$PATH ```安装Node.js 18.17.1:
``` curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs ```创建数据库并导入初始数据:
``` CREATE DATABASE archive_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'archive_user'@'%' IDENTIFIED BY 'YourSecurePassword123!'; GRANT ALL PRIVILEGES ON archive_system. TO 'archive_user'@'%'; FLUSH PRIVILEGES; ```执行DDL初始化脚本:
``` -- 档案元数据表 CREATE TABLE archive_metadata ( id BIGINT AUTO_INCREMENT PRIMARY KEY, archive_code VARCHAR(50) NOT NULL UNIQUE, archive_name VARCHAR(200) NOT NULL, archive_type VARCHAR(50) NOT NULL, storage_location VARCHAR(500), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_type (archive_type), INDEX idx_create_time (create_time) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 档案借阅记录表 CREATE TABLE borrow_records ( id BIGINT AUTO_INCREMENT PRIMARY KEY, archive_id BIGINT NOT NULL, borrower_id VARCHAR(50) NOT NULL, borrow_time DATETIME NOT NULL, expected_return_time DATETIME, actual_return_time DATETIME, borrow_status VARCHAR(20) DEFAULT 'BORROWED', FOREIGN KEY (archive_id) REFERENCES archive_metadata(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ```安装并配置MongoDB:
``` 安装MongoDB wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add - echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list sudo apt-get update sudo apt-get install -y mongodb-org 启动服务 sudo systemctl start mongod sudo systemctl enable mongod ```创建Spring Boot项目,pom.xml核心依赖:
```创建档案管理Controller:
``` @RestController @RequestMapping("/api/archive") @Slf4j public class ArchiveController { @Autowired private ArchiveService archiveService; @PostMapping("/upload") public ResponseResultapplication.yml配置文件:
``` minio: endpoint: http://minio.yourdomain.com:9000 access-key: your-access-key secret-key: your-secret-key bucket-name: archive-bucket spring: datasource: url: jdbc:mysql://localhost:3306/archive_system?useUnicode=true&characterEncoding=utf8&useSSL=false username: archive_user password: YourSecurePassword123! driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect format_sql: true ```MinIO配置类:
``` @Configuration public class MinioConfig { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.access-key}") private String accessKey; @Value("${minio.secret-key}") private String secretKey; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } ```
创建Vue项目并安装依赖:
``` npm create vue@latest archive-system-frontend cd archive-system-frontend npm install element-plus @element-plus/icons-vue axios vue-router pinia ```创建ArchiveUpload.vue组件:
```创建Dockerfile:
``` FROM openjdk:17-jdk-slim VOLUME /tmp COPY target/archive-system.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"] ```创建docker-compose.yml:
``` version: '3.8' services: mysql: image: mysql:8.0.33 environment: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: archive_system MYSQL_USER: archive_user MYSQL_PASSWORD: YourSecurePassword123! ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql mongodb: image: mongo:6.0.8 ports: - "27017:27017" volumes: - mongo_data:/data/db minio: image: minio/minio:RELEASE.2023-09-04T19-57-37Z command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin123 ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data archive-service: build: . ports: - "8080:8080" depends_on: - mysql - mongodb - minio environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/archive_system SPRING_DATA_MONGODB_URI: mongodb://mongodb:27017/archive volumes: mysql_data: mongo_data: minio_data: ```创建nginx.conf:
``` server { listen 80; server_name archive.yourdomain.com; 前端静态文件 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } 后端API代理 location /api/ { proxy_pass http://archive-service:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; 文件上传大小限制 client_max_body_size 50M; } MinIO代理 location /minio/ { proxy_pass http://minio:9000/; proxy_set_header Host $http_host; } } ```添加Spring Boot Actuator监控:
```配置application-monitor.yml:
``` management: endpoints: web: exposure: include: health,info,metrics,prometheus metrics: export: prometheus: enabled: true endpoint: health: show-details: always ```添加Spring Security配置:
``` @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests(authz -> authz .antMatchers("/api/auth/").permitAll() .antMatchers("/api/archive/download/").permitAll() .anyRequest().authenticated() ) .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public JwtAuthenticationFilter jwtAuthenticationFilter() { return new JwtAuthenticationFilter(); } } ```实现基于角色的权限注解:
``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @PreAuthorize("hasRole('ARCHIVE_ADMIN') or @archivePermissionChecker.hasAccess(archiveId)") public @interface ArchiveAccess { } @Service public class ArchivePermissionChecker { public boolean hasAccess(Long archiveId) { // 实现具体的权限检查逻辑 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); UserDetails userDetails = (UserDetails) authentication.getPrincipal(); // 检查用户是否有权限访问该档案 return archiveRepository.checkUserAccess(archiveId, userDetails.getUsername()); } } ```启动所有服务:执行docker-compose up -d命令启动所有容器服务,访问http://localhost查看系统运行状态。