Spring里面的几个层

发布时间:2026/11/4 11:45:49

Spring里面的几个层 数据的全局流动浏览器发请求 │ ▼ ┌─────────────────┐ │ Controller 层 │ ← 接收请求返回响应前台接待 │ 控制层 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Service 层 │ ← 处理业务逻辑业务主管 │ 业务层 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Dao / Mapper 层 │ ← 操作数据库仓库管理员 │ 数据访问层 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 数据库 │ │ MySQL │ └─────────────────┘ 贯穿所有层的 ┌─────────────────┐ │ Entity 实体类 │ ← 数据的载体像快递包裹一样在各层之间传递 │ 实体层 │ └─────────────────┘Entity实体层实体类就是和数据库表一一对应的 Java 对象用来在各层之间传递数据表的内容student 表 ┌────┬────────┬────┬──────────┐ │ id │ name │ age│ email │ ├────┼────────┼────┼──────────┤ │ 1 │ 张三 │ 20 │ zsqq.com│ │ 2 │ 李四 │ 22 │ lsqq.com│ └────┴────────┴────┴──────────┘实体类的内容packagecom.example.entity;publicclassStudent{privateIntegerid;// 对应表里的 id 列privateStringname;// 对应表里的 name 列privateIntegerage;// 对应表里的 age 列privateStringemail;// 对应表里的 email 列// ---- 无参构造必须有很多框架依赖它----publicStudent(){}// ---- 全参构造方便创建对象----publicStudent(Integerid,Stringname,Integerage,Stringemail){this.idid;this.namename;this.ageage;this.emailemail;}// ---- getter 和 setter必须有框架通过它们读写数据----publicIntegergetId(){returnid;}publicvoidsetId(Integerid){this.idid;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicIntegergetAge(){returnage;}publicvoidsetAge(Integerage){this.ageage;}publicStringgetEmail(){returnemail;}publicvoidsetEmail(Stringemail){this.emailemail;}// ---- toString 方便打印调试 ----OverridepublicStringtoString(){returnStudent{idid, namename, ageage, emailemail};}}Dao层Mapper层Dao 层专门负责对数据库做增删改查CRUD它不关心业务规则只关心怎么存取数据只负责增删改查packagecom.example.dao;importcom.example.entity.Student;importorg.apache.ibatis.annotations.*;importjava.util.List;/** * Dao 层使用 MyBatis 框架操作数据库 * * 每个方法对应一个 SQL 操作 * 这里只定义接口SQL 写在注解或 XML 文件里 */Mapper// 告诉 MyBatis这是一个数据库操作接口请帮我生成实现类publicinterfaceStudentDao{// ---- 增往数据库插入一条学生记录 ----Insert(INSERT INTO student(name, age, email) VALUES(#{name}, #{age}, #{email}))intinsert(Studentstudent);// #{name} 的意思是从传入的 Student 对象里取 name 字段的值// ---- 删根据 id 删除一条记录 ----Delete(DELETE FROM student WHERE id #{id})intdeleteById(Integerid);// ---- 改修改学生信息 ----Update(UPDATE student SET name#{name}, age#{age}, email#{email} WHERE id#{id})intupdate(Studentstudent);// ---- 查根据 id 查询一个学生 ----Select(SELECT * FROM student WHERE id #{id})StudentselectById(Integerid);// ---- 查查询所有学生 ----Select(SELECT * FROM student)ListStudentselectAll();// ---- 查根据名字模糊查询 ----Select(SELECT * FROM student WHERE name LIKE CONCAT(%, #{name}, %))ListStudentselectByName(Stringname);}Service层业务逻辑层Service 层负责实现具体的业务规则它是整个系统最核心的一层业务主管。客户说我要办银行卡主管会想先检查身份证、再查征信、再开户……这些流程和规则都在主管脑子里Service 层调用 Dao 层来操作数据库Service 层不处理 HTTP 请求也不直接写 SQL业务规则校验、判断、流程写在 Service 层举例子packagecom.example.service;importcom.example.dao.StudentDao;importcom.example.entity.Student;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.List;Service// 告诉 Spring这是一个 Service 类请放进容器管理publicclassStudentService{Autowired// 让 Spring 自动把 StudentDao 的实例注入进来privateStudentDaostudentDao;/** * 添加学生——这是业务方法里面有业务规则 */publicintaddStudent(Studentstudent){// 业务规则1名字不能为空 if(student.getName()null||student.getName().trim().isEmpty()){thrownewRuntimeException(学生姓名不能为空);}// 业务规则2年龄必须在合理范围 if(student.getAge()1||student.getAge()150){thrownewRuntimeException(年龄必须在 1-150 之间);}// 业务规则3检查是否重名 ListStudentexistingstudentDao.selectByName(student.getName());if(!existing.isEmpty()){thrownewRuntimeException(已经存在同名学生student.getName());}// 所有规则都通过了才去操作数据库returnstudentDao.insert(student);}/** * 删除学生——有业务规则 */publicintdeleteStudent(Integerid){// 业务规则先检查学生是否存在 StudentstudentstudentDao.selectById(id);if(studentnull){thrownewRuntimeException(学生不存在idid);}returnstudentDao.deleteById(id);}/** * 修改学生信息 */publicintupdateStudent(Studentstudent){// 业务规则先检查存在性StudentexistingstudentDao.selectById(student.getId());if(existingnull){thrownewRuntimeException(学生不存在idstudent.getId());}returnstudentDao.update(student);}/** * 查询单个学生 */publicStudentgetStudent(Integerid){returnstudentDao.selectById(id);}/** * 查询所有学生 */publicListStudentgetAllStudents(){returnstudentDao.selectAll();}}Controller层用来接收请求参数调用Service层然后返回结果packagecom.example.controller;importcom.example.entity.Student;importcom.example.service.StudentService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.*;importjava.util.List;importjava.util.HashMap;importjava.util.Map;RestController// 告诉 Spring这是一个控制器返回的数据直接写入 HTTP 响应体RequestMapping(/student)// 所有接口的 URL 都以 /student 开头publicclassStudentController{AutowiredprivateStudentServicestudentService;/** * 添加学生 * 前端发 POST 请求到 /student/add * 请求体里带 JSON 数据 * * 例如POST /student/add * Body: {name:张三, age:20, email:zsqq.com} */PostMapping(/add)publicMapString,ObjectaddStudent(RequestBodyStudentstudent){// RequestBody 把前端发来的 JSON 自动转成 Student 对象MapString,ObjectresultnewHashMap();try{introwsstudentService.addStudent(student);result.put(code,200);result.put(msg,添加成功);result.put(data,rows);}catch(Exceptione){result.put(code,500);result.put(msg,e.getMessage());// 把 Service 层抛出的错误信息返回}returnresult;}/** * 删除学生 * DELETE /student/delete/1 */DeleteMapping(/delete/{id})publicMapString,ObjectdeleteStudent(PathVariableIntegerid){// PathVariable 从 URL 路径中取 id 的值MapString,ObjectresultnewHashMap();try{studentService.deleteStudent(id);result.put(code,200);result.put(msg,删除成功);}catch(Exceptione){result.put(code,500);result.put(msg,e.getMessage());}returnresult;}/** * 查询单个学生 * GET /student/1 */GetMapping(/{id})publicMapString,ObjectgetStudent(PathVariableIntegerid){MapString,ObjectresultnewHashMap();StudentstudentstudentService.getStudent(id);if(student!null){result.put(code,200);result.put(msg,查询成功);result.put(data,student);}else{result.put(code,404);result.put(msg,学生不存在);}returnresult;}/** * 查询所有学生 * GET /student/list */GetMapping(/list)publicMapString,ObjectgetAllStudents(){MapString,ObjectresultnewHashMap();ListStudentliststudentService.getAllStudents();result.put(code,200);result.put(msg,查询成功);result.put(data,list);returnresult;}}
延伸阅读

更多相关文章

2026/11/4 11:40:47

如何搞定课程设计?别人走过的捷径,你也可以走

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 11:40:47

【WebSocket】Spring WebSocket 应用出现“Connection closed before receiving a handshake response”错误,可能原因有哪些?

WebSocket 握手失败深度排查:IoT 设备指令下发系统的连接诊断体系 用户问题原文:Spring WebSocket 应用出现“Connection closed before receiving a handshake response”错误,可能原因有哪些? 在构建 IoT 设备指令下发系统时,我们曾因无法准确诊断握手失败原因导致设备大…

2026/11/4 12:46:09

操作系统底层原理:从硬件中断到进程调度的完整链路解析

1. 操作系统运行链路全景解析作为一名在系统底层开发摸爬滚打多年的工程师,我见过太多人把操作系统当作"黑匣子"来学习。今天我们就用最接地气的方式,拆解从鼠标点击到程序运行的完整链路,让你真正理解操作系统如何协调软硬件资源。…

2026/11/4 12:46:09

Nginx核心初始化机制:ngx_init_cycle深度解析

1. Nginx核心初始化机制解析:ngx_init_cycle深度剖析在Nginx的高性能架构中,ngx_init_cycle函数扮演着系统初始化和配置重载的核心角色。这个超过800行的复杂函数,是Nginx实现零停机重载配置、高效资源管理的技术基石。作为Nginx的核心开发者…

2026/11/4 12:46:09

SymbolTypeViewer 1.0.0.6内核符号结构配置与排错

简介:Symbol Type Viewer 1.0.0.6 是一款面向 Windows 驱动开发、逆向工程与内核安全学习者的符号与结构分析辅助工具,重点解决 PDB 符号文件获取繁琐、内核类型层级难以直观查看,以及结构体内存布局不易核对等问题。压缩包共 8 个文件&#…

2026/11/4 12:46:09

量子计算测试技术解析与工程实践

1. 量子觉醒事件的技术解析 2087年11月23日,百度昆仑量子实验室的"九章七号"系统在常规运算中输出的那段代码,本质上是一个基于量子退相干时间的条件权益声明。让我们拆解这个看似简单的if-else语句背后蕴含的革命性技术细节: if…

2026/11/4 12:46:09

数字化转型中的技术协同与合规架构实践

1. 项目背景与核心价值HappyPlanet这个项目名称本身就传递着积极信号——它试图通过技术手段打造一个更美好的数字生态。在当前数字化转型浪潮下,这类平台型解决方案正在重新定义人机交互的边界。我观察到,真正具有生命力的数字平台往往具备三个特征&…

2026/11/4 12:41:08

大数据产品技术架构与行业应用解析

1. 大数据领域数据产品的发展现状剖析 1.1 行业应用全景扫描 在金融行业,数据产品已经深度嵌入核心业务流程。以某股份制商业银行的智能风控系统为例,其通过整合内部交易数据、外部征信数据和社交行为数据,将传统风控模型的审批时效从3天缩短…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 0:03:20

AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年…

2026/11/4 0:03:20

从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你…

2026/11/4 0:03:20

32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑