javaweb-day10案例
前言:在 Spring Boot 项目中,controller、mapper、pojo 和 service 四个模块之间存在清晰的职责划分和调用关系。以下是它们之间的 分层架构图 和 相互调用关系说明:
+------------------+
| controller | ← 接收 HTTP 请求并返回响应
+--------+---------+|↓
+------------------+ +------------------+
| service | → | serviceImpl | ← 调用业务逻辑(接口/实现)
+------------------+ +------------------+|↓
+------------------+
| mapper | ← 数据库操作接口(MyBatis Mapper)
+------------------+|↓
+------------------+
| pojo | ← 数据模型(实体类)
+------------------+
典型调用流程示例(以部门管理为例):
- 客户端发送请求到 /dept/list;
- DeptController 接收到请求,调用 DeptService 的 list() 方法;
- DeptServiceImpl 执行业务逻辑,调用 DeptMapper 的 selectAll() 方法;
- DeptMapper 查询数据库,返回 List<Dept>;
- DeptServiceImpl 处理后返回给 DeptController;
- DeptController 将结果封装为 Result,返回 JSON 响应给客户端。
一、准备工作
- 准备数据库表(dept、emp)
- 创建springboot工程,引入必要依赖(web、mybatis、mysql驱动、lombok,mybatis可能需要根据给出区间版本选择对应的版本,要不然在引入Mapper依赖时会出错)
- 配置文件application.properties中引入mybatis的配置信息,准备对应的实体类
- 准备对应的Mapper、Service(接口、实现类)、Controller基础结构
最后的结构:
开发规范——Restful(前端请求后端,后端响应给前端的过程)
REpresentational State Transfer,表述状态转换,是一种软件架构风格
统一响应结果——Result类
package org.example.tilasweb.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private Integer code;//响应码,1 代表成功; 0 代表失败private String msg; //响应信息 描述字符串private Object data; //返回的数据//增删改 成功响应public static Result success(){return new Result(1,"success",null);}//查询 成功响应public static Result success(Object data){return new Result(1,"success",data);}//失败响应public static Result error(String msg){return new Result(0,msg,null);}
}
二、部门管理(删除、新增、修改)
大概思路:
DeptController:接受请求参数;调用service进行操作;响应
DeptService:(补充基础属性);调用mapper接口执行
DeptMapper:写SQL语句
以新增部门为例:
注解@RequestBody的作用:
1. 接收 JSON 格式的请求体
@RequestBody 的作用是将 HTTP 请求体中的 JSON 或 XML 数据自动反序列化为 Java 对象(这里是 Dept 类型)。
当前端通过 POST 请求发送 JSON 数据时(如 {"name": "HR部门"}),Spring 会自动将其转换为 Dept 对象。
2. 与 HTTP 方法匹配
此方法映射的是 @PostMapping,通常用于新增资源,数据一般放在请求体中。
如果不加 @RequestBody,Spring 默认会尝试从请求参数(query parameters 或 form data)中绑定属性,这不符合 RESTful 风格和实际传输方式。
//DeptController
@PostMappingpublic Result add(@RequestBody Dept dept){log.info("添加部门:{}",dept);deptService.add(dept);return Result.success();}
//DeptService.java
void add(Dept dept);
注解@Autowired的作用
1. 自动注入 Bean
DeptMapper 是一个接口,并没有手动 new 实例。
Spring 容器会在启动时扫描带有 @Mapper 注解的类(由 MyBatis-Spring 集成管理),并自动生成实现类。
2. 无需手动 new 或查找对象
如果不用 @Autowired,你需要通过 ApplicationContext.getBean(...) 手动获取 Bean,代码繁琐且耦合度高。使用 @Autowired 后,Spring 自动完成对象创建和依赖管理。
@Autowiredprivate DeptMapper deptMapper;@Overridepublic void add(Dept dept){dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.adddept(dept);}
//DeptMapper.java
@Insert("insert into dept (name, create_time, update_time) value (#{name},#{createTime},#{updateTime})")void adddept(Dept dept);
三、员工管理
1. 员工查询(分页查询)
首先,明确前端传递给后端的数据:当前页码:page 每页展示记录数:pageSize
后端给前端返回的数据:数据列表:List 总记录数:total (分别用两条SQL语句查询)
查看接口文档,明确请求路径、请求方式、响应数据类型
用一个类来表示返回数据的格式 PageBean
/*
* f分页查询结果
* */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {private Integer page;//当前页码private List rows;//每页数据
}
controller层:前端传来两个数据,设置默认值(@RequestParam),调用service层,要返回的是
PageBean类的
@RestController
public class EmpController {@Autowiredprivate EmpServiceImpl empService;@GetMapping("/emps")public Result list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize){return Result.success(empService.list(page,pageSize));}}
service层,对传入进来的数据加工处理,传给mapper层
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;@Overridepublic PageBean list(Integer page, Integer pageSize) {Integer count = empMapper.count();Integer start = (page - 1) * pageSize;List<Emp> list = empMapper.list(start,pageSize);PageBean pageBean = new PageBean(count,list);return pageBean;}
}
mapper层:执行SQL语句(两句:总数+当前请求页面的数据)
@Mapper
public interface EmpMapper {@Select("select count(*) from emp")public Integer count();@Select("select * from emp limit #{start},#{pageSize}")public List<Emp> list(Integer start, Integer pageSize);
}
2.PageHelper插件(简化分页查询)
步骤:
- 引入依赖
<!--PageHelper分页插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version></dependency>
- 修改mapper,只需要一句SQL
@Select("select * from emp")public List<Emp> list();
- 修改service 会自动计算起始数
@Overridepublic PageBean list(Integer page, Integer pageSize) {//1.参数设置PageHelper.startPage(page,pageSize);//2.执行查询List<Emp> emplist = empMapper.list();Page<Emp> p = (Page<Emp>) emplist;//3.封装数据PageBean pageBean = new PageBean(p.getTotal(),p.getResult());return pageBean;}
3. 条件分页查询
需求:根据姓名、性别、入职时间来查询
方法:动态SQL查询——XML映射文件 + 分页查询(PageHelper)
在上面分页查询的基础上修改代码
- controller层,添加请求参数
@GetMapping("/emps")public Result list(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize,String name, Short gender,@DateTimeFormat(pattern = "yyyy-MM-dd")LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd")LocalDate end) {PageBean pageBean = empService.list(page,pageSize,name,gender,begin,end);return Result.success(pageBean);}
- service层,修改接口和实现类
@Overridepublic PageBean list(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {//1.参数设置PageHelper.startPage(page,pageSize);//2.执行查询List<Emp> emplist = empMapper.list(name,gender,begin,end);Page<Emp> p = (Page<Emp>) emplist;//3.封装数据PageBean pageBean = new PageBean(p.getTotal(),p.getResult());return pageBean;}
- mapper层,建立XML文件实现动态SQL查询
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.tilasweb.mapper.EmpMapper"><select id="list" resultType="org.example.tilasweb.pojo.Emp">select * from emp<where><if test="name != null and name != ''">name like concat('%',#{name},'%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time desc</select>
</mapper>