CMS内容管理系统的设计与实现:架构设计

一、整体架构方案

(一)架构方案选择(根据项目规模)

1. 中小型项目推荐方案(团队<10人)

管理前端 Vue3+Ruoyi-UI
Spring Boot单体应用
门户前端 Nuxt3+SSR
统一数据库
  • 技术要点
    • 使用 模块化单体架构(非微服务)
    • 通过 package划分 隔离管理/门户API
    • 利用 Profile 实现环境隔离
    • 无需Spring Cloud,保持简单

2. 大型项目方案(团队>20人)

管理前端
API Gateway
门户前端
Admin服务集群
Portal服务集群
管理数据库
门户数据库
  • 技术要点
    • 采用 Spring Cloud Alibaba
    • 通过 Nacos 实现服务发现
    • 使用 Sentinel 做流量控制
    • 需要独立 DBA团队 支持

3.部署方案对比

方案优点缺点适用阶段
单体部署运维简单,成本低扩展性受限初期(<5万UV)
模块分离部署部分服务可独立伸缩需要基础监控能力中期(5-50万UV)
全微服务弹性扩展,故障隔离运维复杂,成本高后期(>50万UV)

(二)演进路线实施建议

2024-01-01 2024-02-01 2024-03-01 2024-04-01 2024-05-01 2024-06-01 基础内容管理 评论模块开发 数据统计模块 服务拆分准备 独立部署门户服务 管理端微服务化 初期阶段 中期阶段 后期阶段 CMS架构演进路线
# 初期:单体模块化
src/
└── main└── java└── com└── company└── cms├── content├── comment└── statistics# 中期:子模块拆分
cms-system/
├── cms-content
├── cms-comment
└── cms-statistics# 后期:微服务化
cms-admin-service/
cms-portal-service/
cms-comment-service/
  1. 初期采用模块化单体

    • 使用 Maven多模块 而非微服务
    • 通过 @Profile(“admin”) 隔离配置
    • 使用 Flyway 管理多环境数据库
  2. 渐进式演进路径

    单体
    模块独立部署
    核心微服务化
    全微服务架构
  3. 监控准备

    • 即使单体架构也要配置 Prometheus+Granfana
    • 日志系统使用 ELK Stack
    • 关键业务指标埋点

可根据实际用户量增长逐步升级架构,避免早期过度设计。

二、模块化分层架构设计

(一)总体划分架构

1.后端目录划分

采用 「业务垂直切分 + 客户端横向隔离 + 技术纵向分层」 的三维结构,具体实现如下:

src/main/java/com/company/cms
├── content                  # 内容业务模块
│   ├── admin               # 管理端实现
│   │   ├── controller
│   │   ├── service
│   │   └── mapper
│   ├── portal              # 门户端实现
│   │   ├── controller
│   │   ├── service
│   │   └── mapper
│   └── domain              # 公共领域对象
│       ├── entity
│       ├── dto
│       └── vo
├── comment                 # 评论业务模块
│   ├── admin
│   ├── portal
│   └── domain
├── statistics              # 统计业务模块
│   ├── admin
│   ├── portal
│   └── domain
└── common                  # CMS公共模块├── config             # 专有配置├── interceptor        # 拦截器└── utils              # 工具类

2. 业务垂直切分

CMS系统
内容模块
评论模块
统计模块
管理端
门户端
  • 隔离性:各业务模块可独立开发部署

  • 可维护性:修改影响范围明确

  • 复用性:公共domain对象跨客户端复用

3. 客户端横向隔离

// 内容模块下的权限差异示例
// 管理端Controller
@PreAuthorize("hasRole('CONTENT_ADMIN')")
@PostMapping("/admin/content")
public AjaxResult createContent(...) {// 需要审核流程
}// 门户端Controller 
@RateLimit(100) // 限流注解
@GetMapping("/portal/content")
public ContentVO getContent(...) {// 缓存优化实现
}

4. 技术纵向分层

# 典型业务模块内部结构
content/
├── admin
│   ├── controller       # API入口
│   ├── service          # 业务逻辑
│   └── mapper           # 数据持久
├── portal
│   ├── controller
│   ├── service
│   └── mapper
└── domain               # 核心领域模型├── entity          # JPA实体├── dto             # 传输对象└── vo              # 视图对象

(二)前后端代码统筹

1.代码仓库管理策略

若是属于少量人开发项目,则推荐单一代码仓库 + 多模块结构的方案进行开发。

my-cms-project/
├── backend/          # Spring Boot后端
│   ├── src/
│   └── pom.xml
├── admin-frontend/   # 管理端Vue3
│   ├── src/
│   └── package.json
└── portal-frontend/  # 门户端Nuxt3├── pages/└── package.json

若是多人开发项目,应该分为3个代码仓库,由不同的技术人员开发提交对应的代码。

2.配置示例(.gitignore):

# 通用忽略
*.log
*.iml
.idea/# 后端忽略
backend/target/# 前端忽略
admin-frontend/node_modules/
admin-frontend/dist/
portal-frontend/node_modules/
portal-frontend/.nuxt/

三、后端实施建议

(一)领域对象

1.领域对象复用

// 公共实体定义
@Entity
@Table(name = "cms_content")
public class Content {@Id@GeneratedValueprivate Long id;// 公共字段private String title;private String content;// 管理端特有字段(审计用)@Column(name = "audit_status")@AdminOnly  // 自定义注解private AuditStatus auditStatus;// 门户端特有字段(展示用)@Column(name = "view_count")@PortalOnlyprivate Integer viewCount;
}

(二)API控制器

1.API路径设计规范

管理端和门户端的api接口需要隔离,用/api/admin和/api/portal区分好,还是用/admin/api和/portal/api区分好?

推荐:/api/admin/api/portal 双前缀模式

管理端: /api/admin/v1/content
门户端: /api/portal/v1/content

优势分析:

  • 路由清晰:/api 明确标识API入口,/admin|portal区分客户端
  • 网关友好:Nginx可统一配置/api路由规则
  • 安全隔离:方便在网关层设置不同安全策略
  • 版本控制:v1支持平滑升级到v2

2.控制器隔离

// 管理端文章控制器
@RestController
@RequestMapping("/api/admin/v1/articles")
public class AdminArticleController {@PreAuthorize("hasRole('ADMIN')")@PostMappingpublic AjaxResult createArticle(@Valid @RequestBody ArticleCreateDTO dto) {// 管理端专用创建逻辑}
}// 门户端文章控制器 
@RestController
@RequestMapping("/api/portal/v1/articles")
public class PortalArticleController {@GetMapping("/{id}")public ArticleVO getArticle(@PathVariable Long id) {// 门户端专用查询逻辑}
}

3.API文档管理

// 使用Swagger分组
@Bean
public Docket adminApi() {return new Docket(DocumentationType.OAS_30).groupName("管理端API").select().apis(RequestHandlerSelectors.basePackage("com.cms.controller.admin"))
}

(三)服务层

1.服务层复用策略

// 通用服务接口
public interface ArticleBaseService {Article getById(Long id);
}// 管理端服务实现  
@Service
public class AdminArticleService implements ArticleBaseService {@Overridepublic Article getById(Long id) {// 管理端专用逻辑(包含审计字段)}public void auditArticle(Long id) {// 管理端特有方法}
}// 门户端服务实现
@Service 
public class PortalArticleService implements ArticleBaseService {@Overridepublic Article getById(Long id) {// 门户端专用逻辑(缓存优化)}
}

2. 服务层差异处理

// 管理端服务实现
@Service
public class AdminContentService {@AdminAuditRequired // 自定义审核注解public void publishContent(Long id) {// 包含审核流程}
}// 门户端服务实现
@Service
public class PortalContentService {@Cacheable("content") // 缓存优化public ContentVO getContent(Long id) {// 访问统计逻辑}
}

(四)安全配置

1.安全配置分离

// 管理端安全配置类
@Configuration
@EnableWebSecurity
@Order(1) // 高优先级
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.antMatcher("/admin/**").authorizeRequests().anyRequest().hasRole("ADMIN").and().formLogin().disable();}
}// 门户端安全配置类  
@Configuration
@Order(2) // 低优先级
public class PortalSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.antMatcher("/portal/**").authorizeRequests().antMatchers(HttpMethod.GET).permitAll().anyRequest().authenticated().and().oauth2ResourceServer().jwt();}
}
# application-admin.yml(管理端配置)
security:oauth2:resource:id: admin-apiuser-info-uri: http://auth-server/oauth2/user# application-portal.yml(门户端配置)  
security:oauth2:resource:id: portal-apiuser-info-uri: http://auth-server/oauth2/openid
# 权限配置示例(admin/portal分离)
security:admin:roles: [CONTENT_ADMIN, COMMENT_ADMIN]access: DENY_AFTER_17:00-08:00 # 管理端时间限制portal:rate-limit: 1000/分钟open-apis: [/api/portal/content/*]

(五)异常处理

1.异常处理方案

@RestControllerAdvice(basePackages = {"com.company.cms.content.admin","com.company.cms.content.portal"})
public class ContentExceptionHandler {@ExceptionHandler(ContentNotFoundException.class)public ResponseEntity<ErrorResult> handleNotFound(ContentNotFoundException ex) {return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResult("CONTENT_NOT_FOUND", ex.getMessage()));}
}

2. 错误码规范示例

模块错误范围示例
内容模块1000-19991001=内容不存在
评论模块2000-29992003=评论包含敏感词
统计模块3000-39993005=数据导出失败

(六)配置管理

1.配置管理策略

多环境配置示例

config/
├── application.yml           # 公共配置
├── application-dev.yml       # 开发环境
├── application-prod.yml      # 生产环境
├── content-admin.yml         # 内容管理端特有配置
└── content-portal.yml        # 内容门户端特有配置
# application.yml(公共配置)
spring:datasource:url: jdbc:mysql://localhost:3306/cmsusername: rootpassword: 123456---
# application-admin.yml(管理端特有配置)
management:endpoints:web:exposure:include: health,info,metricsendpoint:health:show-details: always---
# application-portal.yml(门户端特有配置)  
spring:redis:host: portal-redisport: 6379

动态配置示例

@Configuration
@ConfigurationProperties(prefix = "cms.content")
public class ContentConfig {// 管理端特有配置private AdminConfig admin;// 门户端特有配置private PortalConfig portal;@Datapublic static class AdminConfig {private int auditTimeout = 24; // 审核超时时间(小时)}@Datapublic static class PortalConfig {private int cacheTTL = 3600; // 缓存时间(秒)}
}
3. 数据库隔离策略
-- 管理表(admin_开头)
CREATE TABLE admin_operation_log (id BIGINT PRIMARY KEY,user_id BIGINT NOT NULL,action VARCHAR(50) NOT NULL
);-- 门户表(portal_开头)
CREATE TABLE portal_comment (id BIGINT PRIMARY KEY,article_id BIGINT NOT NULL,content TEXT
);

四、前端技术确认

端类型技术栈适用场景示例代码
管理后台Vue3 + Ruoyi-UI需要快速开发CRUD界面使用若依的src/views/system结构
门户网站Nuxt3 + SSR需要SEO优化和首屏性能pages/article/[id].vue动态路由

(一)前端API调用对比

管理端调用示例(Vue3):

// admin-frontend/src/api/content.js
import request from '@/utils/request'export function getContentList(params) {return request({url: '/api/admin/v1/content',method: 'get',params})
}

门户端调用示例(Nuxt3):

// portal-frontend/composables/useContent.js
export default () => {const getContent = async (id) => {return $fetch(`/api/portal/v1/content/${id}`, {method: 'GET'})}return { getContent }
}

(二)开发环境代理配置

管理端Vite配置(admin-frontend/vite.config.js):

export default defineConfig({server: {proxy: {'/api/admin': {target: 'http://localhost:8080', // Spring Boot地址changeOrigin: true,rewrite: path => path.replace(/^\/api\/admin/, '')}}}
})

门户端Nuxt配置(portal-frontend/nuxt.config.js):

export default defineNuxtConfig({devServer: {proxy: {'/api/portal': 'http://localhost:8080'}}
})

前端环境变量:

# admin-frontend/.env.development
VITE_API_BASE=/api/admin# portal-frontend/.env.production
NUXT_PUBLIC_API_BASE=/api/portal

五、其它

1.Nginx统一配置:

server {listen 80;# 管理前端location /admin {alias /var/www/admin-frontend/dist;try_files $uri $uri/ /admin/index.html;}# 门户前端location / {alias /var/www/portal-frontend/dist;try_files $uri $uri/ /index.html;}# API路由location /api {proxy_pass http://backend-server:8080;proxy_set_header Host $host;# 管理API超时设置location ~ ^/api/admin {proxy_read_timeout 300s;}# 门户API缓存配置location ~ ^/api/portal.*\.(js|css|png)$ {expires 30d;}}
}

2.日常开发流程:

创建功能分支
后端开发
管理前端对接
门户前端对接
本地联调测试
提交到同一分支
创建合并请求
代码评审后合并

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式里的时间魔法:RTC 与 BKP 深度拆解

文章目录 RTC实时时钟与BKPUnix时间戳UTC/GMT时间戳转换时间戳转换BKP简介BKP基本结构1. 电池供电模块&#xff08;VBAT 输入&#xff09;2. 侵入检测模块&#xff08;TAMPER 输入&#xff09;3. 时钟输出模块&#xff08;RTC 输出&#xff09;4. 内部寄存器组 RTC简介RTC时钟源…

STC8H系列 驱动步进电机

STC8H 驱动步进电机 一、引言二、硬件设计三、软件设计Step_Motor2.c文件Step_ Motor2.h文件 一、引言 众所周知STC8H系列有两个PWM&#xff0c;分别为PWMA和PWMB外设模块&#xff0c;我全都用上&#xff0c;岂不是就有两个带动电机的脉冲信号&#xff1f;&#xff01;哈哈哈哈…

Python高阶函数:从入门到精通

目录 Python高阶函数详解&#xff1a;从概念到高级应用引言&#xff1a;函数式编程的魅力一、高阶函数基础概念1.1 什么是高阶函数1.2 Python中的一等函数 二、内置高阶函数详解2.1 map函数&#xff1a;数据转换利器2.2 filter函数&#xff1a;数据筛选专家2.3 reduce函数&…

腾讯开源视频生成工具 HunyuanVideo-Avatar,上传一张图+一段音频,就能让图中的人物、动物甚至虚拟角色“活”过来,开口说话、唱歌、演相声!

腾讯混元团队提出的 HunyuanVideo-Avatar 是一个基于多模态扩散变换器&#xff08;MM-DiT&#xff09;的模型&#xff0c;能够生成动态、情绪可控和多角色对话视频。支持仅 10GB VRAM 的单 GPU运行&#xff0c;支持多种下游任务和应用。例如生成会说话的虚拟形象视频&#xff0…

DeepSeek-R1-0528:开源推理模型的革新与突破

一、 发布日期与背景 2025年5月29日&#xff0c;备受业界关注的DeepSeek推理模型DeepSeek-R1迎来重要更新——DeepSeek-R1-0528模型正式发布。此次更新采取了“静默发布”策略&#xff0c;未提前预告&#xff0c;而是通过官方渠道&#xff08;官网、App、小程序&#xff09;及…

LeetCode 1723: 完成所有工作的最短时间

给你一个整数数组 jobs &#xff0c;其中 jobs[i] 是完成第 i 项工作要花费的时间。 请你将这些工作分配给 k 位工人。所有工作都应该分配给工人&#xff0c;且每项工作只能分配给一位工人。工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作…

JDK8新特性之Steam流

这里写目录标题 一、Stream流概述1.1、传统写法1.2、Stream写法1.3、Stream流操作分类 二、Stream流获取方式2.1、根据Collection获取2.2、通过Stream的of方法 三、Stream常用方法介绍3.1、forEach3.2、count3.3、filter3.4、limit3.5、skip3.6、map3.7、sorted3.8、distinct3.…

split方法

在编程中&#xff0c;split 方法通常用于将字符串按照指定的分隔符拆分成多个部分&#xff0c;并返回一个包含拆分结果的列表&#xff08;或数组&#xff09;。不同编程语言中的 split 方法语法略有不同&#xff0c;但核心功能相似。以下是常见语言中的用法&#xff1a; ​1. P…

深入理解 x86 汇编中的符号扩展指令:从 CBW 到 CDQ 的全解析

引入 在汇编语言的世界里&#xff0c;数据宽度的转换是一项基础却至关重要的操作。尤其是在处理有符号数时&#xff0c;符号扩展&#xff08;Sign Extension&#xff09;作为保持数值符号一致性的核心技术&#xff0c;直接影响着运算结果的正确性。本文将聚焦 x86 架构中最常用…

计算机基础知识(第五篇)

计算机基础知识&#xff08;第五篇&#xff09; 架构演化与维护 软件架构的演化和定义 软件架构的演化和维护就是对架构进行修改和完善的过程&#xff0c;目的就是为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改等&#xff0c;是一个不断迭代的过程&#xff0…

前端开发三剑客:HTML5+CSS3+ES6

在前端开发领域&#xff0c;HTML、CSS和JavaScript构成了构建网页与Web应用的核心基础。随着技术标准的不断演进&#xff0c;HTML5、CSS3以及ES6&#xff08;ECMAScript 2015及后续版本&#xff09;带来了诸多新特性与语法优化&#xff0c;极大地提升了开发效率和用户体验。本文…

c++ 头文件

目录 防止头文件重复包含 头文件的作用 如何让程序的多个 .cpp 文件之间共享全局变量&#xff08;可能是 int、结构体、数组、指针、类对象&#xff09;? 防止头文件重复包含 为什么要防止头问件重复包含&#xff1f; 当然一般也不会把变量定义放到头问件&#xff0c;那为…

深入解析 JavaScript 中 var、let、const 的核心区别与实践应用

一、历史背景与语法基础 JavaScript 作为动态弱类型语言&#xff0c;变量声明机制经历了从 ES5 到 ES6 的重大变革。在 ES5 及更早版本中&#xff0c;var 是唯一的变量声明方式&#xff0c;而 ES6&#xff08;2015 年&#xff09;引入了 let 和 const&#xff0c;旨在解决 var…

【Linux庖丁解牛】—自定义shell的编写!

1. 打印命令行提示符 在我们使用系统提供的shell时&#xff0c;每次都会打印出一行字符串&#xff0c;这其实就是命令行提示符&#xff0c;那我们自定义的shell当然也需要这一行字符串。 这一行字符串包含用户名&#xff0c;主机名&#xff0c;当前工作路径&#xff0c;所以&a…

应用案例 | 设备分布广, 现场维护难? 宏集Cogent DataHub助力分布式锅炉远程运维, 让现场变“透明”

在日本&#xff0c;能源利用与环保问题再次成为社会关注的焦点。越来越多的工业用户开始寻求更高效、可持续的方式来运营设备、管理能源。而作为一家专注于节能与自动化系统集成的企业&#xff0c;日本大阪的TESS工程公司给出了一个值得借鉴的答案。 01 锅炉远程监控难题如何破…

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…

jdk同时安装多个版本并自由切换

一、安装不同版本的JDK 二、配置环境变量&#xff08;多版本JDK&#xff09; 1. 新建版本专用环境变量&#xff08;用于切换&#xff09; 操作位置&#xff1a;系统变量 > 新建 变量名&#xff1a;JAVA_HOME_1.8 变量值&#xff1a;JDK 8安装路径变量名&#xff1a;JAVA1…

java中装饰模式

目录 一 装饰模式案例说明 1.1 说明 1.2 代码 1.2.1 定义数据服务接口 1.2.2 定义基础数据库服务实现 1.2.3 日志装饰器 1.2.4 缓存装饰器 1.2.5 主程序调用 1.3 装饰模式的特点 一 装饰模式案例说明 1.1 说明 本案例是&#xff1a;数据查询增加缓存&#xff0c;使用…

【论文阅读】YOLOv8在单目下视多车目标检测中的应用

Application of YOLOv8 in monocular downward multiple Car Target detection​​​​​ 原文真离谱&#xff0c;文章都不全还发上来 引言 自动驾驶技术是21世纪最重要的技术发展之一&#xff0c;有望彻底改变交通安全和效率。任何自动驾驶系统的核心都依赖于通过精确物体检…

在uni-app中如何从Options API迁移到Composition API?

uni-app 从 Options API 迁移到 Composition API 的详细指南 一、迁移前的准备 升级环境&#xff1a; 确保 HBuilderX 版本 ≥ 3.2.0项目 uni-app 版本 ≥ 3.0.0 了解 Composition API 基础&#xff1a; 响应式系统&#xff1a;ref、reactive生命周期钩子&#xff1a;onMount…