一、系统架构设计
1.1 整体架构图
┌─────────────────────────────────────────────────────────────┐ │ 全球化动态配置系统架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 前端应用 │ │ 移动端 │ │ 后端服务 │ │ │ │ (Vue/React) │ │ (iOS/Android) │ │ (Spring Boot) │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │ │ │ CDN网络 │◄───┤ CDN网络 │◄───┤ CDN网络 │ │ │ │ (国际化资源) │ │ (国际化资源) │ │ (国际化资源) │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ ┌──────▼──────────────────▼──────────────────▼──────┐ │ │ │ XXL-JOB定时同步任务 │ │ │ │ (数据库 → 文件生成 → CDN上传 → 缓存刷新) │ │ │ └───────────────────────┬────────────────────────────┘ │ │ │ │ │ ┌───────────────────────▼────────────────────────────┐ │ │ │ 配置管理中心 (Admin UI) │ │ │ │ (Mybatis-Plus + Spring Boot 3.x) │ │ │ └───────────────────────┬────────────────────────────┘ │ │ │ │ │ ┌───────────────────────▼────────────────────────────┐ │ │ │ MySQL数据库 │ │ │ │ (国际化配置存储 + 版本管理) │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘
1.2 核心流程
-
配置管理:通过Admin UI管理多语言资源
-
定时同步:XXL-JOB定时同步资源到CDN
-
动态加载:应用从CDN加载最新资源
-
版本控制:支持灰度发布和回滚
二、数据库设计
2.1 表结构设计
sql
-- 国际化应用表
CREATE TABLE `i18n_app` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`app_code` VARCHAR(64) NOT NULL COMMENT '应用编码',
`app_name` VARCHAR(128) NOT NULL COMMENT '应用名称',
`description` VARCHAR(512) COMMENT '应用描述',
`status` TINYINT DEFAULT 1 COMMENT '状态: 0-禁用, 1-启用',
`created_by` VARCHAR(64),
`created_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated_by` VARCHAR(64),
`updated_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_app_code` (`app_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='国际化应用表';
-- 国际化资源表
CREATE TABLE `i18n_resource` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`app_id` BIGINT NOT NULL COMMENT '应用ID',
`resource_key` VARCHAR(512) NOT NULL COMMENT '资源键',
`module` VARCHAR(128) COMMENT '模块名称',
`description` VARCHAR(512) COMMENT '资源描述',
`status` TINYINT DEFAULT 1 COMMENT '状态: 0-禁用, 1-启用',
`created_by` VARCHAR(64),
`created_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated_by` VARCHAR(64),
`updated_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_app_resource` (`app_id`, `resource_key`),
KEY `idx_module` (`module`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='国际化资源表';
-- 国际化翻译表
CREATE TABLE `i18n_translation` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`resource_id` BIGINT NOT NULL COMMENT '资源ID',
`locale` VARCHAR(16) NOT NULL COMMENT '语言环境',
`translation` TEXT NOT NULL COMMENT '翻译内容',
`version` INT DEFAULT 1 COMMENT '版本号',
`status` TINYINT DEFAULT 1 COMMENT '状态: 0-禁用, 1-启用',
`created_by` VARCHAR(64),
`created_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`updated_by` VARCHAR(64),
`updated_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_resource_locale` (`resource_id`, `locale`),
KEY `idx_locale` (`locale`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='国际化翻译表';
-- 同步任务记录表
CREATE TABLE `i18n_sync_task` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`task_id` VARCHAR(64) NOT NULL COMMENT '任务ID',
`app_id` BIGINT NOT NULL COMMENT '应用ID',
`env` VARCHAR(32) NOT NULL COMMENT '环境',
`locale` VARCHAR(16) COMMENT '语言环境',
`file_type` VARCHAR(16) DEFAULT 'JSON' COMMENT '文件类型: JSON, PROPERTIES',
`status` TINYINT DEFAULT 0 COMMENT '状态: 0-执行中, 1-成功, 2-失败',
`cdn_url` VARCHAR(1024) COMMENT 'CDN地址',
`file_size` BIGINT COMMENT '文件大小',
`start_time` DATETIME,
`end_time` DATETIME,
`error_msg` TEXT COMMENT '错误信息',
`created_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_task_app` (`task_id`, `app_id`),
KEY `idx_status_time` (`status`, `created_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='同步任务记录表';
-- 版本发布记录表
CREATE TABLE `i18n_release` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`release_version` VARCHAR(64) NOT NULL COMMENT '发布版本',
`app_id` BIGINT NOT NULL COMMENT '应用ID',
`env` VARCHAR(32) NOT NULL COMMENT '环境',
`locales` TEXT NOT NULL COMMENT '包含的语言',
`file_count` INT DEFAULT 0 COMMENT '文件数量',
`status` TINYINT DEFAULT 0 COMMENT '状态: 0-待发布, 1-发布中, 2-已发布, 3-已回滚',
`release_time` DATETIME COMMENT '发布时间',
`rollback_time` DATETIME COMMENT '回滚时间',
`created_by` VARCHAR(64),
`created_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_version_app_env` (`release_version`, `app_id`, `env`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='版本发布记录表';
三、后端服务实现
3.1 Maven依赖配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>i18n-dynamic-config</artifactId>
<version>1.0.0</version>
<properties>
<java.version>21</java.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<xxl-job.version>2.4.0</xxl-job.version>
<aliyun-oss.version>3.17.4</aliyun-oss.version>
</properties>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Mybatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- XXL-JOB -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>${xxl-job.version}</version>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-oss.version}</version>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- 热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2 实体类定义
java
// I18nApp.java
package com.example.i18n.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("i18n_app")
public class I18nApp {
@TableId(type = IdType.AUTO)
private Long id;
private String appCode;
private String appName;
private String description;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedTime;
}
// I18nResource.java
package com.example.i18n.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("i18n_resource")
public class I18nResource {
@TableId(type = IdType.AUTO)
private Long id;
private Long appId;
private String resourceKey;
private String module;
private String description;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedTime;
}
// I18nTranslation.java
package com.example.i18n.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("i18n_translation")
public class I18nTranslation {
@TableId(type = IdType.AUTO)
private Long id;
private Long resourceId;
private String locale;
private String translation;
private Integer version;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updatedBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedTime;
}
3.3 Mybatis-Plus配置和Mapper
java
// MybatisPlusConfig.java
package com.example.i18n.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public MyMetaObjectHandler metaObjectHandler() {
return new MyMetaObjectHandler();
}
}
// MyMetaObjectHandler.java
package com.example.i18n.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createdTime", LocalDateTime::now, LocalDateTime.class);
this.strictInsertFill(metaObject, "updatedTime", LocalDateTime::now, LocalDateTime.class);
// 获取当前用户(实际项目从SecurityContext获取)
String currentUser = "system";
this.strictInsertFill(metaObject, "createdBy",

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



