news 2026/7/22 14:48:42

后端代码springboot项目,相关层的基础介绍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
后端代码springboot项目,相关层的基础介绍

最标准的SpringBoot三层架构(Controller-Service-DAO)和两个关键的辅助层的全盘梳理


一、整体分层图景(先看全貌)

text

┌─────────────────────────────────────────────────────┐ │ 前端 / 第三方调用 │ └──────────────────────┬──────────────────────────────┘ │ JSON/HTTP ▼ ┌─────────────────────────────────────────────────────┐ │ 【Controller 层】 aka Web层 / 接口层 │ │ 职责:接收请求、参数校验、返回响应 │ │ 注解:@RestController, @RequestMapping │ └──────────────────────┬──────────────────────────────┘ │ 调用 ▼ ┌─────────────────────────────────────────────────────┐ │ 【Service 层】 aka 业务层 │ │ 职责:核心业务逻辑、事务管理、缓存处理 │ │ 注解:@Service, @Transactional │ └──────────────────────┬──────────────────────────────┘ │ 调用 ▼ ┌─────────────────────────────────────────────────────┐ │ 【DAO/Mapper 层】 aka 数据访问层 │ │ 职责:与数据库交互,执行SQL │ │ 注解:@Mapper / @Repository │ └──────────────────────┬──────────────────────────────┘ │ ▼ [数据库]

但实际项目中,远不止这三层,下面我给你展开真正的“企业级分层”。


二、五层详解(由外到内)

1. Controller 层(接口层 / Web层)

定位:项目的“大门”,是所有外部请求的统一入口

该做的事

  • 接收HTTP请求,解析请求参数(@RequestParam@PathVariable@RequestBody)。

  • 最基本的参数校验(非空、格式),但不做业务逻辑校验。

  • 调用Service层处理业务。

  • 把Service返回的结果封装成统一响应格式(如Result<T>)返回给前端。

不该做的事

  • ❌ 写任何业务逻辑(比如计算价格、判断状态机)。

  • ❌ 直接操作数据库(不能出现xxxMapper的注入)。

  • ❌ 处理异常时把堆栈信息直接抛给前端(要全局捕获并转换)。

代码范例

java

@RestController @RequestMapping("/api/user") @Slf4j public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Result<String> login(@Valid @RequestBody LoginRequest request) { // 只做调用和封装,不做业务判断 String token = userService.login(request.getUsername(), request.getPassword()); return Result.success(token); } }

2. Service 层(业务层)——最核心

定位:整个项目的大脑,所有业务规则都在这里落地。

该做的事

  • 实现具体的业务逻辑(比如下单时先查库存、再扣库存、再生成订单)。

  • 管理事务@Transactional),保证数据一致性。

  • 处理缓存@Cacheable)、异步任务@Async)。

  • 调用多个DAO层完成复杂的数据聚合。

  • 抛出业务异常(BizException),由全局异常处理器统一处理。

不该做的事

  • ❌ 处理HTTP相关的东西(HttpServletRequestHttpServletResponse)。

  • ❌ 直接返回JSON给前端(那是Controller的事)。

  • ❌ 在Service里写SQL或操作数据库底层细节。

设计规范接口 + 实现类是标准写法(虽然Spring可以直接用实现类,但接口利于解耦和单元测试)。

java

// 接口 public interface UserService { String login(String username, String password); } // 实现类 @Service @Slf4j public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @Transactional(rollbackFor = Exception.class) public String login(String username, String password) { // 1. 查询用户 User user = userMapper.selectByUsername(username); // 2. 业务校验(密码比对) if (user == null || !password.equals(user.getPassword())) { throw new BizException("用户名或密码错误"); } // 3. 生成Token(业务逻辑) return JwtUtil.generateToken(user.getId()); } }

3. DAO/Mapper 层(数据访问层)

定位:数据库的“翻译官”,把Java对象和数据库表进行映射。

该做的事

  • 定义SQL语句(或通过MyBatis-Plus的BaseMapper自动生成)。

  • 执行CRUD操作,返回PO(持久化对象,即数据库表对应的实体类)。

  • 仅做数据访问,不包含任何业务判断。

不该做的事

  • ❌ 写业务逻辑(比如if判断状态然后改SQL,这是Service的活)。

  • ❌ 处理异常后返回特殊值(比如返回null,让Service去处理)。

代码范例(MyBatis-Plus风格)

java

@Mapper // MyBatis的注解,交给Spring管理 public interface UserMapper extends BaseMapper<User> { // 复杂查询自己写XML或注解SQL @Select("SELECT * FROM user WHERE username = #{username}") User selectByUsername(String username); }

4. DTO / VO 层(数据传输层)——容易被忽略但极其重要

定位:专门用来“传递数据”的对象,绝不与数据库表结构强绑定

为什么要单独拎出来?

  • PO(实体类):和数据库表一一对应,字段完全一致。但你不能直接把它暴露给前端,因为:

    • 用户密码、敏感字段不能返回。

    • 前端可能只需要5个字段,但你查了全表50个字段,浪费性能。

    • 接口升级时,改数据库表结构会影响所有调用方。

正确做法

  • Request(请求DTO):前端传参用的对象,比如LoginRequest

  • Response(响应VO):返回给前端的对象,比如UserVO,只包含前端需要的字段。

java

// 请求对象 @Data public class LoginRequest { @NotBlank(message = "用户名不能为空") private String username; @NotBlank(message = "密码不能为空") private String password; } // 响应对象(不返回密码) @Data public class UserVO { private Long id; private String username; private String phone; }

5. 异常处理层(全局统一处理)——项目稳定的压舱石

定位:不是传统意义上的业务层,但每个成熟项目都必须有

作用:用@ControllerAdvice统一捕获所有异常,把技术异常(如空指针)转换成前端能看懂的业务错误码。

java

@RestControllerAdvice @Slf4j public class GlobalExceptionHandler { // 处理自定义业务异常 @ExceptionHandler(BizException.class) public Result<String> handleBizException(BizException e) { log.warn("业务异常:{}", e.getMessage()); return Result.error(e.getCode(), e.getMessage()); } // 处理参数校验异常 @ExceptionHandler(MethodArgumentNotValidException.class) public Result<String> handleValidException(MethodArgumentNotValidException e) { String msg = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return Result.error(400, msg); } }

三、数据流转全链路(串起来理解)

我给你模拟一个用户登录的完整数据流转,你就全明白了:

  1. 前端发来JSON:{"username":"张三","password":"123"}

  2. Controller层接收 → 用LoginRequest接参,@Valid自动校验非空。

  3. Controller层调用userService.login(),把usernamepassword传过去。

  4. Service层

    • 调用userMapper.selectByUsername()查询数据库。

    • 拿到User对象(包含加密密码)。

    • 进行密码比对,失败则抛出BizException

    • 成功则生成JWT Token。

  5. Service层把Token返回给Controller。

  6. Controller层把Token封装成Result.success(token),转成JSON返回前端。

  7. 如果中间任何环节出错:全局异常处理器拦截,返回Result.error()


四、“各层注入关系禁忌表”(面试高频坑)

可以注入谁绝对不能注入谁
ControllerService❌ Mapper / DAO(绝对不能越界)
ServiceMapper / DAO,其他Service,RedisTemplate❌ Controller(循环依赖)
Mapper/DAO无(只做数据访问)❌ Service(绝对不能反向依赖)

核心原则上层依赖下层,下层绝不依赖上层。数据只能从Controller → Service → Mapper 单向流动。


五、再加一个“隐藏层”:Config / 配置层

业务代码之外,还有一些技术支撑的配置类,比如:

  • RedisConfig:配置Redis序列化方式。

  • WebMvcConfig:配置跨域、拦截器。

  • MybatisPlusConfig:配置分页插件。

这些不属于业务分层,但它们是项目启动的“基础设施”。


用一句话总结这五层的关系:

Controller接客(收请求),Service算账(写逻辑),Mapper跑腿(查数据库),DTO搬货(传数据),ExceptionHandler擦屁股(统一处理异常)。


如果你现在正在搭建自己的项目,我建议你按照这个结构创建一个干净的包目录

text

com.example.project ├── controller ├── service │ ├── impl ├── mapper ├── entity (PO,数据库实体) ├── dto (请求/响应对象) │ ├── request │ └── response ├── config (配置类) ├── handler (全局异常处理) └── utils (工具类)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 14:48:28

Unity协程实战:7大高频场景与性能优化指南

1. 项目概述&#xff1a;为什么Unity协程是游戏逻辑的“瑞士军刀”&#xff1f; 在Unity开发里&#xff0c;协程&#xff08;Coroutine&#xff09;绝对是一个高频词&#xff0c;但也是一个容易被新手误解和滥用的概念。很多人觉得它神秘&#xff0c;不就是个能分帧执行的函数吗…

作者头像 李华
网站建设 2026/7/22 14:48:12

Cortex-M4中断唤醒与Thumb-2指令集实战解析

1. 项目概述与核心价值在嵌入式开发的日常里&#xff0c;中断和指令集是绕不开的两个硬核话题。前者决定了你的系统如何“眼观六路&#xff0c;耳听八方”&#xff0c;后者则是你与处理器沟通的“语言”。今天&#xff0c;我想结合自己这些年调试Cortex-M4内核的经验&#xff0…

作者头像 李华
网站建设 2026/7/22 14:44:05

TI KeyStone I多核DSP硬件设计:复位、配置与接口设计实战指南

1. 项目概述与核心价值在基于德州仪器&#xff08;TI&#xff09;KeyStone I多核DSP架构的硬件设计项目中&#xff0c;最让工程师头疼的往往不是那些复杂的算法实现&#xff0c;而是系统能否“活”起来——也就是从上电到稳定运行的“第一步”。我见过不少项目&#xff0c;原理…

作者头像 李华
网站建设 2026/7/22 14:44:00

AM18xx Bootloader CRC-32算法与ROM函数实战解析

1. 项目概述与核心价值如果你正在使用德州仪器&#xff08;TI&#xff09;的AM18xx系列ARM处理器进行嵌入式开发&#xff0c;那么系统启动&#xff08;Boot&#xff09;环节的稳定性和可靠性&#xff0c;绝对是你项目成功的第一道关卡。我经历过不止一次因为启动镜像在NAND Fla…

作者头像 李华
网站建设 2026/7/22 14:43:47

慢性前列腺炎治疗误区与科学抗炎方案

1. 慢性前列腺炎的认知误区与治疗现状 作为一名从业15年的泌尿外科医生&#xff0c;我接诊过上千例慢性前列腺炎患者。这个看似普通的疾病&#xff0c;却让无数男性陷入"治疗-复发-再治疗"的恶性循环。最让我痛心的是&#xff0c;90%的患者都存在一个致命误区——把慢…

作者头像 李华
网站建设 2026/7/22 14:43:38

福建零一智联:以五星服务赋能企业数字化转型

福建零一智联&#xff1a;以五星服务赋能企业数字化转型 在“数字中国”建设浪潮中&#xff0c;福州正全力推进数字化转型工作。作为用友YonSuite钻石解决方案伙伴&#xff0c;福建零一智联数字科技有限公司扎根福州&#xff0c;以扎实的技术实力与卓越的服务品质&#xff0c;成…

作者头像 李华