`api`、`common`、`service`、`web` 分层架构设计

分层架构设计apicommonserviceweb 是现代 Java 项目(尤其是基于 Spring Boot)中最常见的模块划分。

1、整体架构图(典型 Maven 多模块项目)

复制代码
project-root
├── common          ← 公共模块
├── service         ← 业务逻辑模块
├── api             ← 对外 API 模块
└── web             ← Web 接口层(或 UI 层)

这是一种 "分层 + 模块化" 的设计,常见于微服务或大型单体应用。

2、各模块职责

2.1. common 模块(公共模块)

  • 存放跨模块共享的代码,避免重复,被其他所有模块依赖。

  • 包含内容:

    • 工具类:DateUtils, StringUtils, JsonUtils
    • 公共异常:BusinessException, GlobalException
    • 统一返回格式:ResponseResult<T>ErrorCode
    • 常量类:Constants, StatusEnum
    • 基础配置:BaseConfig, RedisTemplate 配置
    • 分页封装:PageResult<T>

示例:

arduino 复制代码
// 统一响应格式
public class ResponseResult<T> {
    private int code;
    private String message;
    private T data;
    // getter/setter
}

2.2 service 模块(业务逻辑层)

  • 实现核心业务逻辑 ,依赖:common + mapper(或 repository)。

  • 包含内容:

    • Service 接口和实现类:UserService, OrderService
    • 业务逻辑:事务控制、流程编排、规则判断
    • 调用 common 模块的工具和异常
    • 调用 dao / mapper(数据访问层,有时独立为 repository 模块)

示例:

typescript 复制代码
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User findById(Long id) {
        return userMapper.selectById(id);
    }

    @Transactional
    public void transferMoney(Long from, Long to, BigDecimal amount) {
        
    }
}

2.3. api 模块(接口定义层)

  • 对外暴露的服务接口 (通常是接口类,不含实现),用于模块间解耦RPC 调用 ,依赖:common,被 web 和其他服务模块依赖。
  • 包含内容:
    • 接口定义:UserServiceApi, OrderServiceApi
    • DTO(数据传输对象):UserDTO, OrderDTO
    • RPC 调用参数和返回值

示例:

java 复制代码
// 定义一个远程可调用的接口
public interface UserServiceApi {
    ResponseResult<UserDTO> getUserById(Long id);
    ResponseResult<List<UserDTO>> listUsers(PageQuery query);
}

使用场景:

  • 微服务之间通过 Dubbo、gRPC 调用
  • web 模块依赖 api,面向接口编程
  • 前后端分离时,api 模块也可生成 OpenAPI 文档

2.4. web 模块(Web 接口层)

  • 处理 HTTP 请求 ,接收参数、调用 serviceapi,返回 JSON,依赖:api + common, 对外暴露 HTTP 接口。
  • 包含内容:
    • Controller:UserController, OrderController
    • 接收 @RequestParam, @RequestBody
    • 参数校验(@Valid
    • 调用 serviceapi 客户端
    • 返回 ResponseResult<T>

示例:

less 复制代码
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserService userService; // 或 UserServiceApi

    @GetMapping("/{id}")
    public ResponseResult<UserDTO> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseResult.success(UserConverter.toDTO(user));
    }
}

3、依赖原则

markdown 复制代码
web → api → common
     ↘
service → common
  • web 依赖 apicommon
  • service 依赖 common
  • api 依赖 common
  • common 不依赖任何模块(否则会循环依赖!)

原则

依赖只能向"上"或"同级",不能"向下"
common 是最底层,web 是最上层。

4、父pom文件(Maven 多模块)

xml 复制代码
<!-- 父 pom.xml -->
<modules>
    <module>common</module>
    <module>service</module>
    <module>api</module>
    <module>web</module>
</modules>

每个模块都是一个独立的 Maven 项目:

  • common/pom.xml
  • service/pom.xml
  • api/pom.xml
  • web/pom.xml

5、设计优势

优势 说明
解耦清晰 各层职责分明,便于维护
复用性强 common 被所有模块共享
便于测试 可独立测试 service 逻辑
支持微服务 api 模块可用于服务间调用
团队协作 不同团队负责不同模块

6、常见错误

错误 正确做法
common 依赖 service common 不能依赖任何业务模块
web 直接访问 mapper ❌ 应通过 serviceapi
service 返回 ResponseResult service 只返回业务对象,web 层封装响应
api 包含实现类 api 只定义接口,不写实现

7、变体设计(根据项目规模调整)

项目规模 推荐结构
小型项目 单模块:controllerservicecommon 在同一个项目
中型项目 四模块:commonserviceapiweb
大型微服务 每个服务独立部署,api 模块单独发布为 SDK

总结

模块 职责 依赖谁 被谁依赖
common 工具、异常、常量 所有模块
service 业务逻辑 common web、其他服务
api 接口定义(RPC/远程调用) common web、其他服务
web HTTP 接口(Controller) api + common 客户端(前端、App)
相关推荐
Code_Artist3 小时前
说说恶龙禁区Unsafe——绕过静态类型安全检查&直接操作内存的外挂
java·后端·操作系统
二闹3 小时前
别再用错了!深入扒一扒Python里列表和元组那点事
后端·python
编程乐趣3 小时前
基于.Net开发的数据库导入导出的开源项目
后端
赵星星5203 小时前
别再搞混了!深入浅出理解Java线程中start()和run()的本质区别
java·后端
Ray663 小时前
FST
后端
白露与泡影3 小时前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端·sql
花花无缺4 小时前
接口(interface)中的常量和 类(class)中的常量的区别
java·后端
舒一笑4 小时前
利用Mybatis自定义排序规则实现复杂排序
后端·排序算法·mybatis
毕设源码-郭学长4 小时前
【开题答辩全过程】以 基于vue+springboot的校园疫情管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端