1. JavaWeb三层架构概述在JavaWeb开发中三层架构是最基础也是最经典的设计模式之一。我第一次接触这个架构是在2013年开发一个电商后台系统时当时项目代码混乱不堪各种业务逻辑和数据库操作混杂在JSP页面中维护起来简直是一场噩梦。后来引入了三层架构整个项目的可维护性立刻提升了几个档次。三层架构的核心思想是关注点分离(Separation of Concerns)将应用程序划分为表现层、业务逻辑层和数据访问层。这种分层方式不仅适用于JavaWeb也是现代软件开发的基础范式。根据我的经验一个中等规模的JavaWeb项目采用三层架构后代码复用率可以提高40%以上新功能开发效率提升30%左右。2. 三层架构详解2.1 表现层(Controller)表现层是系统与用户交互的入口在JavaWeb中通常由Servlet或Spring MVC的Controller承担这一角色。我见过很多新手容易犯的错误是在Controller中写业务逻辑这完全违背了分层原则。一个规范的Controller应该只做三件事接收并校验请求参数调用Service层处理业务返回响应结果以用户登录为例正确的Controller写法应该是Controller RequestMapping(/user) public class UserController { Autowired private UserService userService; PostMapping(/login) public ResponseEntityResult login(Valid RequestBody LoginDTO dto) { String token userService.login(dto); return ResponseEntity.ok(Result.success(token)); } }提示Controller方法应该保持简洁单个方法代码行数最好控制在15行以内。如果发现Controller方法过于复杂说明可能有业务逻辑泄露到了表现层。2.2 业务逻辑层(Service)Service层是整个系统的核心承载着主要的业务逻辑。根据我的项目经验Service层的设计有以下几个要点接口与实现分离先定义接口再写实现类方便后续扩展和Mock测试事务控制使用Transactional注解管理事务边界异常处理定义业务异常体系不要直接抛出SQLException等底层异常典型的Service接口定义public interface UserService { /** * 用户登录 * param dto 登录参数 * return token * throws BusinessException 业务异常 */ String login(LoginDTO dto) throws BusinessException; // 其他业务方法... }Service实现类示例Service public class UserServiceImpl implements UserService { Autowired private UserDao userDao; Autowired private TokenService tokenService; Override Transactional(rollbackFor Exception.class) public String login(LoginDTO dto) throws BusinessException { User user userDao.findByUsername(dto.getUsername()); if(user null || !user.getPassword().equals(encrypt(dto.getPassword()))){ throw new BusinessException(用户名或密码错误); } return tokenService.generateToken(user); } // 其他方法实现... }2.3 数据访问层(Dao)Dao层负责与数据库交互在MyBatis体系中通常由Mapper接口和XML文件组成。根据我的经验Dao层设计要注意以下几点方法命名规范遵循findByXxx、save、update、delete等约定参数校验在Dao层做基础的非空校验SQL优化复杂查询要关注性能必要时添加索引MyBatis Mapper接口示例Mapper public interface UserDao { User findByUsername(Param(username) String username); int save(Param(user) User user); int updatePassword(Param(id) Long id, Param(newPassword) String newPassword); }对应的XML映射文件mapper namespacecom.example.dao.UserDao select idfindByUsername resultTypeUser SELECT * FROM user WHERE username #{username} LIMIT 1 /select insert idsave useGeneratedKeystrue keyPropertyid INSERT INTO user(username, password) VALUES(#{user.username}, #{user.password}) /insert /mapper3. 层间交互与依赖关系三层架构中各层的依赖关系应该是单向的Controller → Service → Dao。在实际项目中我经常看到以下两种反模式循环依赖Service调用Dao的同时Dao又调用了Service跨层调用Controller直接调用Dao绕过Service层这两种情况都会破坏架构的分层原则。正确的依赖关系应该像这样HTTP请求 → Controller → Service → Dao → DB ↑ ↑ 返回结果 返回业务数据为了保持这种清晰的依赖关系我推荐以下实践使用Spring的依赖注入管理Bean各层包结构按功能划分如com.example.controller、com.example.service等禁止在Dao中注入Service也不要在Controller中注入Dao4. 三层架构的演进与变体随着业务复杂度增加基础的三层架构可能会演进为更复杂的结构。以下是几种常见的变体4.1 领域驱动设计(DDD)在复杂业务系统中传统的三层架构可能不够用。DDD引入了以下概念领域层(Domain)包含实体、值对象、领域服务等应用层(Application)协调领域对象完成用例基础设施层(Infrastructure)提供技术实现4.2 六边形架构也称为端口适配器模式核心思想是将业务逻辑放在中心外部通过适配器与业务交互。这种架构特别适合需要支持多种接入方式的系统。4.3 整洁架构由Robert C. Martin提出强调框架无关性可测试性UI和数据库等细节位于外层业务规则位于内层5. 实战经验与常见问题5.1 事务管理最佳实践在Service层管理事务是最佳实践常见问题包括事务传播行为设置不当默认的REQUIRED在大多数情况下够用但嵌套事务需要特别注意异常捕获吞没事务捕获了Exception但没有重新抛出导致事务不回滚大事务问题一个事务中包含太多操作导致锁持有时间过长解决方案示例Service public class OrderServiceImpl implements OrderService { Transactional(propagation Propagation.REQUIRED, isolation Isolation.READ_COMMITTED, rollbackFor Exception.class) public void createOrder(OrderDTO dto) { // 订单创建逻辑 } }5.2 性能优化技巧Dao层优化使用MyBatis的二级缓存批量操作代替循环单条操作合理使用懒加载Service层优化异步处理非核心流程缓存热点数据避免在循环中调用DaoController层优化使用ResponseBody代替转发合理设计API粒度启用Gzip压缩5.3 单元测试策略三层架构天然适合单元测试Controller测试使用MockMvc模拟HTTP请求Service测试Mock依赖的Dao专注业务逻辑Dao测试使用内存数据库如H2测试示例SpringBootTest AutoConfigureMockMvc class UserControllerTest { Autowired private MockMvc mockMvc; MockBean private UserService userService; Test void loginSuccess() throws Exception { when(userService.login(any())).thenReturn(mock-token); mockMvc.perform(post(/user/login) .contentType(MediaType.APPLICATION_JSON) .content({\username\:\test\,\password\:\123456\})) .andExpect(status().isOk()) .andExpect(jsonPath($.data).value(mock-token)); } }6. 从三层架构到微服务随着业务规模扩大单体应用的三层架构可能演变为微服务架构。这种演进需要注意服务拆分原则按业务能力拆分单一职责原则先粗后细逐步演进层的变化Controller层变为API网关Service层拆分为独立服务Dao层变为服务内部实现细节新引入的组件服务注册与发现配置中心分布式事务在实际项目中我建议不要一开始就采用微服务架构。只有当单体应用的三层架构确实无法满足需求时才考虑向微服务演进。根据我的经验日活用户低于50万的系统精心设计的三层架构单体应用完全能够胜任。
阅读完成 · 觉得有帮助?