第三章 系统架构设计:分层架构、微服务选型与技术栈
好,咱们进入第三章。这一章我打算聊聊系统架构设计。说实话,这是整个OA系统的骨架。骨架搭歪了,后面再怎么填肉都别扭。我在好几个项目里都吃过架构选型不当的亏,今天把这些经验摊开来跟你讲讲。
3.1 分层架构:表现层、业务层、数据层
分层架构,说白了就是「各司其职」。你想想看,一个OA系统要处理审批、考勤、会议、文档……如果所有代码都揉在一起,那维护起来简直是噩梦。我习惯把系统切成三层:
- 表现层:负责跟用户打交道。展示页面、接收输入、做简单的校验。
- 业务层:核心逻辑在这里。比如审批流程的流转规则、考勤的计算逻辑。
- 数据层:跟数据库打交道。增删改查,别掺和业务判断。
为什么要这么分?我给你讲个真实案例。之前有个项目,同事把SQL查询直接写在Vue的组件里。嗯,你没听错。后来数据库字段一改,满屏找代码改,差点没把项目搞崩。分层之后,数据层只暴露接口,业务层只管逻辑,表现层只管展示。改一个字段,最多动数据层和业务层,表现层完全不用碰。
核心原则:上层依赖下层,下层不依赖上层。表现层调用业务层,业务层调用数据层。千万别让数据层反过来调用表现层——我见过有人这么干,结果代码像意大利面条一样乱。
3.2 微服务架构选型
说到微服务,很多人一上来就喊「我们要上微服务!」。我劝你冷静。微服务不是银弹,它解决的是「单体应用过于庞大」的问题。OA系统要不要拆?我的建议是:
- 小企业(50人以下):单体应用就够了。别折腾微服务,运维成本你扛不住。
- 中型企业(50-500人):可以拆成几个核心服务。比如用户服务、审批服务、考勤服务。
- 大型企业(500人以上):微服务是必须的。否则一个模块出问题,整个系统都瘫痪。
我个人习惯用Spring Cloud Alibaba这套生态。为什么?因为它在国内落地案例多,坑少。Nacos做注册中心和配置中心,Sentinel做流量控制,Seata处理分布式事务。这些组件我都踩过坑,后面会细说。
避坑指南:我曾经在一个项目里强行把所有功能都拆成微服务,结果服务间调用链长达七八层,出个问题排查半天。后来我学乖了——按业务边界拆,不强求「每个服务都独立数据库」。有些紧密关联的功能,放在同一个服务里反而更高效。
3.3 技术栈选择
技术栈这东西,没有最好,只有最合适。我选技术栈的标准很简单:社区活跃、文档齐全、团队熟悉。下面是我给OA系统推荐的一套组合:
| 层级 | 技术选型 | 理由 |
|---|---|---|
| 后端框架 | Spring Boot 2.7+ | 生态成熟,上手快,适合快速迭代 |
| 前端框架 | Vue.js 3 + Element Plus | 组件丰富,适合后台管理系统 |
| 数据库 | MySQL 8.0 | 稳定可靠,OA系统数据量一般不大 |
| 缓存 | Redis | 处理会话、缓存热点数据 |
| 消息队列 | RabbitMQ | 处理异步通知、日志收集 |
你可能会问:为什么不用MyBatis-Plus?嗯,我其实挺推荐的。它让数据层的开发效率提升不少。但要注意,别滥用它的自动映射——我见过有人一个查询查出几十个字段,结果页面只用了三个。性能就是这么被拖垮的。
前端这块,Vue 3 + Element Plus是绝配。Element Plus的表格、表单、弹窗组件,基本覆盖了OA系统90%的场景。我习惯用Vite做构建工具,比Webpack快太多了,开发体验好一个档次。
注意:技术栈选好了,别频繁升级。我有个朋友,项目做到一半把Spring Boot从2.6升到3.0,结果一堆依赖不兼容,加班两周才搞定。除非有重大安全漏洞,否则保持稳定版本,等迭代间隙再升级。
3.4 代码示例:一个简单的分层实现
光说不练假把式。我给你看一个用户登录的简单实现,感受一下分层是怎么落地的。
数据层(UserMapper.java):
@Mapper
public interface UserMapper {
UserDO findByUsername(@Param("username") String username);
}
业务层(UserService.java):
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public UserVO login(String username, String password) {
UserDO user = userMapper.findByUsername(username);
if (user == null) {
throw new BusinessException("用户不存在");
}
if (!password.equals(user.getPassword())) {
throw new BusinessException("密码错误");
}
// 这里可以加登录日志、更新最后登录时间等
return new UserVO(user.getId(), user.getName(), user.getRole());
}
}
表现层(UserController.java):
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public Result<UserVO> login(@RequestBody LoginDTO dto) {
UserVO user = userService.login(dto.getUsername(), dto.getPassword());
return Result.success(user);
}
}
你看,每一层各管各的事。数据层只查数据库,业务层做逻辑判断,表现层只负责接收请求和返回结果。这样写出来的代码,改起来心里有底。
3.5 总结一下
架构设计这件事,没有标准答案。但有几个原则我建议你记住:
- 分层要清晰:别让表现层直接操作数据库,也别让数据层处理业务逻辑。
- 微服务要克制:不是功能越多越好,拆之前先想想「这个服务独立部署的价值是什么」。
- 技术栈要务实:选团队熟悉的、社区活跃的、文档齐全的。别为了炫技选冷门框架。
嗯,这一章就聊到这儿。下一章我会讲数据库设计,包括表结构怎么规划、索引怎么建、读写分离怎么做。到时候见。