当前位置: 首页 > news >正文

Java 后端分层架构详解

Java 后端分层架构详解

我完全懂你的疑惑!刚接触 Java 后端的人,都会觉得:“不就是写个接口吗?为啥要建这么多文件?”

其实这不是“多此一举”,而是 Java 后端最标准的「分层架构」,每个文件/包都有明确的分工,就像外卖平台的不同岗位,各司其职,代码才不会乱成一团。

我结合你项目里的结构,用通俗比喻+逐文件拆解,给你讲得明明白白!


一、先看整体:你的项目是怎么分工的?

你的接口流程,就像一个「部门列表接口」的完整外卖流程,数据是这样走的:

前端请求 → Controller(接单) → Service(处理业务) → Mapper(取餐) → 数据库

而 POJO 就是传递数据的「餐盒」。


二、逐个拆解:每个文件到底干啥?

  1. controller 包:DeptController(接单员/前台)
  • 图标:蓝色 C,表示是一个类

  • 作用:接口的入口,只和前端打交道,不处理任何业务逻辑

  • 具体干的事:

    1. 接收前端的请求(比如 GET /dept/list)

    2. 调用 Service 层的方法

    3. 把 Service 返回的结果,包装成统一格式返回给前端

  • 举个例子:

@RestController
@RequestMapping(“/dept”)
public class DeptController {
@Autowired
private DeptService deptService;

@GetMapping("/list") public Result list() { // 只负责调用service,不写任何业务逻辑 List<Dept> list = deptService.list(); return Result.success(list); }

}

  • 为什么单独建?

如果把业务逻辑写在 Controller 里,以后接口多了,代码会乱成一锅粥,而且 Controller 只需要负责“接请求、返回结果”,不需要知道“怎么查数据库、怎么处理数据”。


  1. service 包:DeptService + DeptServiceImpl(后厨/业务处理)

这是两个文件,是 Java 里典型的接口+实现类模式,你可以把它们当成“后厨的菜单+厨师”:

① DeptService(绿色 I,接口)

  • 作用:定义「业务规则」,也就是“后厨要做什么菜”

  • 只写方法名,不写具体逻辑,比如:

public interface DeptService {
List list(); // 查询部门列表
void add(Dept dept); // 新增部门
void delete(Integer id); // 删除部门
}

② DeptServiceImpl(蓝色 C,实现类)

  • 作用:真正干活的「厨师」,实现接口里定义的所有方法,写核心业务逻辑

  • 具体干的事:

    1. 处理业务逻辑(比如新增部门时,校验部门名称是否重复;查询列表时过滤禁用状态)

    2. 调用 Mapper 层的方法,获取/修改数据库数据

  • 举个例子:

@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;

@Override public List<Dept> list() { // 业务逻辑:只查询启用的部门 return deptMapper.list().stream() .filter(dept -> dept.getStatus() == 1) .toList(); }

}

  • 为什么要分成两个文件?

这是 Java 的「面向接口编程」,好处是:

  • 以后要修改业务逻辑,只需要改 DeptServiceImpl,不用动 DeptService 和 Controller

  • Spring 框架会自动帮你把实现类注入进去,代码更灵活


  1. mapper 包:DeptMapper(取餐员/数据库操作)
  • 图标:绿色 I,接口

  • 作用:只负责和数据库打交道,写SQL、做增删改查,不处理任何业务逻辑

  • 具体干的事:

    1. 写 SQL 语句(比如 SELECT * FROM dept)

    2. 从数据库查出数据,返回给 Service 层;或者把 Service 传来的数据,写入数据库

  • 举个例子(用MyBatis的话):

@Mapper
public interface DeptMapper {
// 查询所有部门
@Select(“SELECT * FROM dept”)
List list();

// 新增部门 @Insert("INSERT INTO dept(name, status) VALUES(#{name}, #{status})") void add(Dept dept);

}

  • 为什么单独建?

把“数据库操作”和“业务逻辑”彻底分开:

  • 以后换数据库(比如从MySQL换成Oracle),只需要改 Mapper 层的SQL,不用动 Service 和 Controller

  • 找bug的时候,数据不对就看Mapper,逻辑不对就看Service,问题定位超清晰


  1. pojo 包:Dept + Result(餐盒/数据模型)

这两个都是数据模板,用来装数据,在各个层之间传递:

① Dept(蓝色 C,实体类)

  • 作用:对应数据库的 dept 表,是部门数据的模板

  • 里面的字段和数据库表的列一一对应,比如:

public class Dept {
private Integer id; // 部门ID
private String name; // 部门名称
private Integer status; // 状态:1启用 0禁用
private LocalDateTime createTime; // 创建时间
// …getter、setter、构造方法
}

  • 从数据库查出来的数据,会自动封装成 Dept 对象,在 Service、Controller 之间传递。

② Result(蓝色 C,统一返回类)

  • 作用:统一接口返回格式,就是你之前写的 {code, msg, data}

  • 所有接口都返回这个格式,前端不用处理五花八门的返回结果,直接按 code 判断成功/失败:

public class Result {
private Integer code; // 响应码:200成功 500失败
private String msg; // 提示信息
private Object data; // 返回数据
// …success、fail静态方法
}


  1. 启动类 TliasWebManagementA(餐厅大门)
  • 这个是 Spring Boot 项目的入口,不用管太多,只要知道:运行这个类,整个项目就启动了,接口就能被访问了。

三、写一个接口,数据到底怎么走?

用你的「部门列表接口」举个完整流程,你就懂了:

  1. 前端请求 GET /dept/list → 到 DeptController

  2. DeptController 调用 deptService.list() → 把请求交给 Service 层

  3. DeptServiceImpl 处理业务逻辑(比如过滤禁用部门),再调用 deptMapper.list() → 交给 Mapper 层

  4. DeptMapper 执行SQL,从数据库查出部门数据 → 返回给 Service

  5. Service 把处理好的数据返回给 Controller

  6. Controller 把数据包装成 Result 格式,返回给前端


四、为什么一定要这么分?(小白也能懂的好处)

  1. 职责清晰,好维护:每个文件只干一件事,找bug的时候,数据错了看Mapper,逻辑错了看Service,接口报错看Controller,一眼就能定位问题。

  2. 代码可复用:比如 DeptService 里的 list() 方法,可以被多个 Controller 调用,不用写两遍。

  3. 方便修改:以后要改业务逻辑,只改 DeptServiceImpl;要改SQL,只改 DeptMapper,不用动其他层,不会“牵一发而动全身”。

  4. 和前端联调更稳定:统一用 Result 返回,前端不用处理各种奇葩格式,联调效率高。


五、和你之前写的代码对比一下

你之前写的读取 user.txt 的代码,是把“读文件、解析数据、返回结果”全写在 Controller 里,这是没有分层的写法,只能写简单接口,项目大了就会乱。

现在你学的分层写法,是企业级项目的标准规范,学会这个,你写的接口就和大厂的后端代码结构一模一样了!


要不要我帮你写一个「部门列表接口」的完整代码,把每个文件的内容都补全,你直接复制就能跑?

http://www.jsqmd.com/news/697424/

相关文章:

  • 告别手动抠图!3分钟学会用Layerdivider将单图变PSD分层文件
  • E5开发者账号保活避坑指南:除了Renew X,你的Docker日志和邮箱通知设置对了吗?
  • 数字大宅的安保进化论:起底安卓 FBE 与元数据加密的工作细节
  • 华为 FusionCompute Win11 25H2 虚拟机模板制作文档
  • 5步快速上手LaserGRBL:开源激光雕刻控制软件的完整实践指南
  • 用 Roo Code 插件让 Cursor 接入 Claude:零基础配置教程(2026)
  • 从“含茶量”到技术洞察:如何用算法追踪社交网络中的热点话题
  • VESTA绘图进阶:从“能看”到“好看”,手把手教你调出SCI论文级晶体结构图
  • C++ vector底层实现大揭秘
  • 分享一套锋哥原创的SpringBoot4+Vue3实验室预约管理系统
  • FRED应用:目标平面特定照度分布优化
  • PDA5927四象限光电管:从基础测试到光电流线性化应用
  • 告别电源纹波焦虑:手把手教你用村田Simsurfing为LMR14030精准选输出电容
  • Qwen3.6-27B 开源:昇腾适配已到位,AtomGit AI 开放体验
  • 2026年上海大型仿真模型定制与全国工业模型制作深度指南 - 企业名录优选推荐
  • 为什么打工人都爱清远漂流?一趟团建给出了答案 - 佳天下国旅
  • USB隔离
  • 嵌入式Linux实战:手把手教你为i.MX6ULL开发板移植FT5X06触摸驱动(含设备树配置)
  • 别再傻傻分不清OLTP和OLAP了!用TiDB和MySQL实战带你搞懂HTAP架构
  • MATLAB R2022a + YOLOv5s:手把手教你搭建一个带中文界面的目标检测小工具(附完整代码)
  • 高管断裂带FAU和ASW结果+计算代码R语言2010-2022年
  • FPG平台:投教资源如何提升交易员的市场认知
  • 【架构实战】CQRS架构模式实战
  • 2026年贵阳运营岗位开放潮:从死工资到年薪30万+,这个赛道为什么值得All In? - 年度推荐企业名录
  • 如何让Blender成为你的3D打印创意工厂:3MF插件终极指南
  • LabVIEW FPGA SPI通信保姆级教程:从单端口到多路复用的配置避坑指南
  • 场景真实感,才是电商视频真正的转化杠杆
  • 2026年绍兴短视频代运营与AI推广服务深度选型指南:政企视频营销一站式方案 - 年度推荐企业名录
  • 从CT到MRI:不同设备DICOM图像的像素间距差异有多大?一份实测对比报告
  • 思源黑体TTF:高性能字体提示优化与多区域字符集构建实战方案