制作分析
效果演示
流程解析
1. 案例实现方案分析实体类开发————使用Lombok快速制作实体类Dao开发————整合MyBatisPlus,制作数据层测试类Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类Controller开发————基于Restful开发,使用PostMan测试接口功能Controller开发————前后端开发协议制作页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理列表、新增、修改、删除、分页、查询项目异常处理按条件查询————页面功能调整、Controller修正功能、Service修正功能2. SSMP案例制作流程解析先开发基础CRUD功能,做一层测一层调通页面,确认异步提交成功后,制作所有功能添加分页功能与查询功能
模块创建
- SpringBoot Initializr创建模块
- 勾选web、mysql dirver,手动添加mybatis-plus和druid的依赖坐标(需要添加version,因为SpringBoot官方没有收录他们的version坐标)
实体类开发
- 使用Lombok进行实体类的快速开发,Lombok提供了一组注解来简化POJO实体类的开发
在pom.xml文件中添加对应的依赖坐标,version坐标由SpringBoot提供
<!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
常用注解@Data,该注解可以为当前实体类在编译期设置对应的get/set方法,toString方法,hashCode方法,equals方法等。
- 注意:@Data不会给当前实体类添加constructor方法,需要自己添加@NoArgsConstructor或者@AllArgsConstructor到实体类上方。
@Data@NoArgsConstructor@AllArgsConstructorpublic class Book {private Integer id;private String type;private String name;private String description;}
数据层标准开发(基础CRUD)
- 导入MyBatis-plus和Druid对应的starter依赖坐标
```xml
com.baomidou mybatis-plus-boot-starter 3.4.3
- 配置Druid数据源和MyBatis-Plus对应的基础配置(表单中id的自增策略使用数据库自增而不是MyBatis-Plus的雪花算法的自增策略)```yaml# 设置Druid相关配置spring:datasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTCusername: rootpassword: 865330# 设置MyBatisPlus相关配置mybatis-plus:global-config:db-config:table-prefix: tbl_# 使用数据库的id自增而不是MP自带的雪花算法自增id-type: auto# 开启MP日志模式configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
Dao类(Mapper类)继承MP中提供的BaseMapper接口并指定泛型
@Mapperpublic interface BookDao extends BaseMapper<Book> {}
制作测试类
@SpringBootTestpublic class BookDaoTestCase {@Autowiredprivate BookDao bookDao;@Testvoid testGetById(){Book book = bookDao.selectById(1);// 开启MP日志之后,就不用打印出来看了,直接看日志System.out.println(book);}@Testvoid testSave(){Book book = new Book();book.setType("测试数据123");book.setName("测试数据123");book.setDescription("测试数据123");bookDao.insert(book);}@Testvoid testUpdate(){Book book = new Book();book.setId(14);book.setType("测试数据abc");book.setName("测试数据123");book.setDescription("测试数据123");bookDao.updateById(book);}@Testvoid testDelete(){bookDao.deleteById(15);}@Testvoid testGetAll(){// 开启MP日志之后,就不用打印出来看了,直接看日志bookDao.selectList(null);}@Testvoid testGetPage(){// 得到第1页的5条数据IPage page = new Page(2,5);bookDao.selectPage(page, null);System.out.println(page.getPages());System.out.println(page.getTotal());System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getRecords());}@Testvoid testGetBy(){QueryWrapper<Book> qw = new QueryWrapper<>();// select * from tbl_book where name like %Spring%qw.like("name","Spring");bookDao.selectList(qw);}@Testvoid testGetBy2(){String name = "Spring";LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();// select * from tbl_book where name like %Spring%lqw.like(name!=null, Book::getName, "Spring");bookDao.selectList(lqw);}}
开启MP运行日志
# 设置MyBatisPlus相关配置mybatis-plus:global-config:db-config:table-prefix: tbl_# 使用数据库的id自增而不是MP自带的雪花算法自增id-type: auto# 开启MP日志模式configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
分页
分页需要设定分页对象IPage
@Testvoid testGetPage(){// 得到第1页的5条数据IPage page = new Page(1,5);bookDao.selectPage(page, null);System.out.println(page.getPages());System.out.println(page.getTotal());System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getRecords());}
bookDao.selectPage(page, null)返回的是IPage对象,该对象中封装了分页操作中的所有数据:
- 数据
- 当前页码值
- 每页数据总量
- 最大页码值
- 数据总量
分页操作是在MyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句(在这里,分页操作,也就是给SQL语句尾部动态添加LIMIT关键词),因此需要增强对应的功能,使用MyBatisPlus拦截器实现
@Configurationpublic class MPConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){// 1.定义拦截器MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 2.添加具体的拦截器interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}}
测试
@Testvoid testGetPage() {IPage page = new Page(1, 5);bookDao.selectPage(page, null);System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getPages());System.out.println(page.getTotal());System.out.println(page.getRecords());}
数据层标准开发(条件查询)
- 使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象,所有查询操作封装成方法调用
```java
@Test
void testGetBy() {
QueryWrapper
queryWrapper = new QueryWrapper<>(); queryWrapper.like(“name”, “Spring”); bookDao.selectList(queryWrapper); }
@Test
void testGetBy2() {
LambdaQueryWrapper
- 条件查询支持动态拼接查询条件```java@Testvoid testGetBy2() {String name = "1";LambdaQueryWrapper<Book> lambdaQueryWrapper = new LambdaQueryWrapper<>();//if (name != null) lambdaQueryWrapper.like(Book::getName,name);lambdaQueryWrapper.like(Strings.isNotEmpty(name), Book::getName, name);bookDao.selectList(lambdaQueryWrapper);}
小结:
- 使用QueryWrapper对象封装查询条件
- 推荐使用LambdaQueryWrapper对象
- 所有查询操作封装成方法调用
- 查询条件支持动态条件拼装
业务层标准开发(CRUD)
业务层(service)接口定义与数据层(Dao)接口定义有较大区别,注意区分不要混用
- example
selectByUserNameAndPassword(String username,String password); //数据层接口login(String username,String password); //Service层接口
- example
定义接口 ```java public interface BookService {
Boolean save(Book book);
Boolean update(Book book);
Boolean delete(Integer id);
Book getById(Integer id);
List
getAll(); IPage
getPage(int currentPage,int pageSize); }
- 接口实现类```java// 定义成业务层的bean@Servicepublic class BookServiceImpl2 implements BookService {@Autowiredprivate BookDao bookDao;@Overridepublic Boolean save(Book book) {// bookDao.insert(book)返回的是操作的行数,如果行数大于0说明操作成功return bookDao.insert(book) > 0;}@Overridepublic Boolean update(Book book) {return bookDao.updateById(book) > 0;}@Overridepublic Boolean delete(Integer id) {return bookDao.deleteById(id) > 0;}@Overridepublic Book getById(Integer id) {return bookDao.selectById(id);}@Overridepublic List<Book> getAll() {return bookDao.selectList(null);}@Overridepublic IPage<Book> getPage(int current, int pageSize) {IPage page = new Page(current, pageSize);bookDao.selectPage(page, null);// selectPage()之后page对象会被修改,最后还是返回page对象return page;}}
测试类
@SpringBootTestpublic class BookServiceTestCase {@Autowiredprivate BookService bookService;@Testvoid testGetById(){System.out.println(bookService.getById(4));}@Testvoid testSave(){Book book = new Book();book.setType("测试数据123");book.setName("测试数据123");book.setDescription("测试数据123");bookService.save(book);}@Testvoid testUpdate(){Book book = new Book();book.setId(14);book.setType("测试数据abc");book.setName("测试数据123");book.setDescription("测试数据123");bookService.update(book);}@Testvoid testDelete(){System.out.println("delete true or false: "+bookService.delete(15));;}@Testvoid testGetAll(){System.out.println("====testGetAll starts=====");System.out.println(bookService.getAll());;System.out.println("====testGetAll ends=====");}@Testvoid testGetPage(){// 得到第2页的5条数据IPage<Book> page = bookService.getPage(2, 5);System.out.println(page.getPages());System.out.println(page.getTotal());System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getRecords());}}
小结:
- Service接口名称定义成业务名称,并与Dao接口名称进行区分
- 制作测试类测试Service功能是否有效
业务层快速开发(基于MyBatisPlus构建)
- 快速开发方案
- 使用MyBatisPlus提供有业务层通用接口(ISerivce)与业务层通用实现(ServiceImpl
) - 在通用类基础上做功能重载或功能追加
- 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
- 使用MyBatisPlus提供有业务层通用接口(ISerivce)与业务层通用实现(ServiceImpl
定义接口,继承IService
public interface IBookService extends IService<Book> {}
追加接口功能 ```java public interface IBookService extends IService
{ // 追加的操作与原始操作通过名称区分,功能类似 Boolean delete(Integer id);
Boolean insert(Book book);
Boolean modify(Book book);
Book get(Integer id); }
- 实现类```java@Servicepublic class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {}
实现类追加功能 ```java @Service public class BookServiceImpl extends ServiceImpl
implements IBookService { @Autowired private BookDao bookDao;
public Boolean insert(Book book) {
return bookDao.insert(book) > 0;
}
public Boolean modify(Book book) {
return bookDao.updateById(book) > 0;
}
public Boolean delete(Integer id) {
return bookDao.deleteById(id) > 0;
}
public Book get(Integer id) {
return bookDao.selectById(id);
} }
- 测试类```java@SpringBootTestpublic class IBookServiceTestCase {@Autowiredprivate IBookService bookService;@Testvoid testGetById(){System.out.println(bookService.getById(4));}@Testvoid testSave(){Book book = new Book();book.setType("测试数据123");book.setName("测试数据123");book.setDescription("测试数据123");bookService.save(book);}@Testvoid testUpdate(){Book book = new Book();book.setId(14);book.setType("测试数据abc");book.setName("测试数据123");book.setDescription("测试数据123");bookService.updateById(book);}@Testvoid testDelete(){System.out.println("delete true or false: "+bookService.removeById(15));;}@Testvoid testGetAll(){System.out.println("====testGetAll starts=====");System.out.println(bookService.list());;System.out.println("====testGetAll ends=====");}@Testvoid testGetPage(){// 得到第2页的5条数据IPage<Book> page = new Page<>(2, 5);bookService.page(page);System.out.println(page.getPages());System.out.println(page.getTotal());System.out.println(page.getCurrent());System.out.println(page.getSize());System.out.println(page.getRecords());}}
小结:
- 使用通用接口(ISerivce)快速开发Service
- 使用通用实现类(ServiceImpl
)快速开发ServiceImpl - 可以在通用接口基础上做功能重载或功能追加
- 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
表现层标准开发
- 基于RESTFul风格进行表现层开发
- 使用Postman测试表现层接口功能
表现类 ```java @RestController @RequestMapping(“/books”) public class BookController {
@Autowired private IBookService bookService;
@GetMapping public List
getAll() { return bookService.list();
}
@PostMapping public Boolean save(@RequestBody Book book) {
return bookService.save(book);
}
@PutMapping public Boolean update(@RequestBody Book book) {
return bookService.modify(book);
}
@DeleteMapping(“{id}”) public Boolean delete(@PathVariable Integer id) {
return bookService.delete(id);
}
@GetMapping(“{id}”) public Book getById(@PathVariable Integer id) {
return bookService.getById(id);
}
@GetMapping(“{currentPage}/{pageSize}”) public IPage
getPage(@PathVariable Integer currentPage, @PathVariable int pageSize) { return bookService.getPage(currentPage, pageSize);
}
}
- 添加分页的业务层方法```javaIPage<Book> getPage(int currentPage,int pageSize);
@Overridepublic IPage<Book> getPage(int currentPage, int pageSize) {IPage page = new Page(currentPage, pageSize);bookDao.selectPage(page, null);return page;}
小结:
- 基于Restful制作表现层接口
新增:POST
删除:DELETE
修改:PUT
查询:GET - 接收参数
实体数据:@RequestBody
路径变量:@PathVariable
表现层数据一致性处理(R对象)
- 增加response的状态属性(flag)

- 当数据为 null 可能出现的问题
- 查询id不存在的数据,返回 null
- 查询过程中抛出异常,catch 中返回 null
设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议
@Datapublic class R {private Boolean flag;private Object data;public R() {}/*** 不返回数据的构造方法** @param flag*/public R(Boolean flag) {this.flag = flag;}/*** 返回数据的构造方法** @param flag* @param data*/public R(Boolean flag, Object data) {this.flag = flag;this.data = data;}}
表现层接口统一返回值类型结果 ```java @RestController @RequestMapping(“/books”) public class BookController {
@Autowired private IBookService bookService;
@GetMapping public R getAll() {
return new R(true, bookService.list());
}
@PostMapping public R save(@RequestBody Book book) {
return new R(bookService.save(book));
}
@PutMapping public R update(@RequestBody Book book) {
return new R(bookService.modify(book));
}
@DeleteMapping(“{id}”) public R delete(@PathVariable Integer id) {
return new R(bookService.delete(id));
}
@GetMapping(“{id}”) public R getById(@PathVariable Integer id) {
return new R(true, bookService.getById(id));
}
@GetMapping(“{currentPage}/{pageSize}”) public R getPage(@PathVariable Integer currentPage, @PathVariable int pageSize) {
return new R(true, bookService.getPage(currentPage, pageSize));
}
}
小结:1. 设计统一的返回值结果类型便于前端开发读取数据1. 返回值结果类型可以根据需求自行设定,没有固定格式1. 返回值结果模型类用于后端与前端进行数据格式统一,也称为前<br />后端数据协议<a name="QbHq2"></a># 前后端调用(axios发送异步请求)- 前后端分离结构设计中页面归属前端服务器- 单体工程中页面放置在resources目录下的static目录中(建议执行clean)- 前端发送异步请求,调用后端接口```javascript//钩子函数,VUE对象初始化完成后自动执行created() {//调用查询全部数据的操作this.getAll();}
//列表getAll() {//发送异步请求axios.get("/books").then((res)=>{console.log(res.data);})}
小结:
- 单体项目中页面放置在resources/static目录下
- created钩子函数用于初始化页面时发起调用
- 页面使用axios发送异步请求获取数据后确认前后端是否联通
列表功能
- 列表页
小结://列表getAll() {//发送异步请求axios.get("/books").then((res) => {//console.log(res.data);this.dataList = res.data.data;})}
- 将查询数据返回到页面,利用前端v-bind数据双向绑定进行数据展示
添加功能
弹出添加窗口
// 弹出添加窗口handleCreate() {this.dialogFormVisible = true;}
清除数据
//重置表单resetForm() {this.formData = {};}
在弹出添加窗口时 清除数据
//弹出添加窗口handleCreate() {this.dialogFormVisible = true;this.resetForm();}
发送请求
//添加handleAdd() {axios.post("/books", this.formData).then((res) => {//判断当前操作是否成功if (res.data.flag) {//1.关闭弹层this.dialogFormVisible = false;this.$message.success("添加成功");} else {this.$message.error("添加失败");}}).finally(() => {//2.重新加载数据this.getAll();})}
取消添加
//取消cancel() {//1.关闭弹层this.dialogFormVisible = false;//2.提示用户this.$message.info("当前操作取消");}
小结:
- 请求方式使用POST调用后台对应操作
- 添加操作结束后动态刷新页面加载数据
- 根据操作结果不同,显示对应的提示信息
- 弹出添加Div时清除表单数据
删除功能
删除
// 删除handleDelete(row) {axios.delete("/books/" + row.id).then((res) => {if (res.data.flag) {this.$message.success("删除成功");} else {this.$message.error("删除失败");}}).finally(() => {this.getAll();});}
加入确认删除对话框 ```javascript // 删除 handleDelete(row) { //1. 弹出提示框 this.$confirm(“些操作永久删除当前信息,是否继续?”, “提示”, {type: “info”}).then(() => {
//2. 做删除业务axios.delete("/books/" + row.id).then((res) => {//判断当前操作是否成功if (res.data.flag) {this.$message.success("删除成功");} else {this.$message.error("删除失败");}}).finally(() => {//2.重新加载数据this.getAll();})
}).catch(() => {
//3. 取消删除this.$message.info("取消操作");
});
}
小结:1. 请求方式使用Delete调用后台对应操作1. 删除操作需要传递当前行数据对应的id值到后台1. 删除操作结束后动态刷新页面加载数据1. 根据操作结果不同,显示对应的提示信息1. 删除操作前弹出提示框避免误操作<a name="qlPID"></a># 修改功能(加载数据)- 弹出修改窗口```javascript//弹出编辑窗口handleUpdate(row) {axios.get("/books/" + row.id).then((res) => {if (res.data.flag && res.data.data != null) {// 展示弹层,加载数据this.dialogFormVisible4Edit = true;this.formData = res.data.data;} else {this.$message.error("数据同步失败,自动刷新");}}).finally(() => {//重新加载数据this.getAll();});}
- 删除消息维护
```javascript
// 删除
handleDelete(row) {
//1. 弹出提示框
this.$confirm(“些操作永久删除当前信息,是否继续?”, “提示”, {type: “info”}).then(() => {
}).catch(() => {//2. 做删除业务axios.delete("/books/" + row.id).then((res) => {//判断当前操作是否成功if (res.data.flag) {this.$message.success("删除成功");} else {this.$message.error("数据同步失败,自动刷新");}}).finally(() => {//2.重新加载数据this.getAll();});
});//3. 取消删除this.$message.info("取消操作");
}
<a name="ECGec"></a># 修改功能- 修改```javascript//修改handleEdit() {axios.put("/books", this.formData).then((res) => {//判断当前操作是否成功if (res.data.flag) {//1.关闭弹层this.dialogFormVisible4Edit = false;this.$message.success("修改成功");} else {this.$message.error("修改失败");}}).finally(() => {//2.重新加载数据this.getAll();});}
- 取消添加和修改
小结://取消cancel() {//1.关闭弹层this.dialogFormVisible = false;this.dialogFormVisible4Edit = false;//2.提示用户this.$message.info("当前操作取消");}
- 请求方式使用PUT调用后台对应操作
- 修改操作结束后动态刷新页面加载数据(同新增)
- 根据操作结果不同,显示对应的提示信息(同新增)
异常消息处理
- 业务操作成功或失败返回数据格式 ```json { “flag”: true, “data”: null }
{ “flag”: false, “data”: null }
- 后台代码BUG导致数据格式不统一性```json{"timestamp": "2021-11-07T12:44:29.343+00:00","status": 500,"error": "Internal Server Error","path": "/books"}
对异常进行统一处理,出现异常后,返回指定信息
@RestControllerAdvicepublic class ProjectExceptionAdvice {//拦截所有的异常信息@ExceptionHandler(Exception.class)public R doException(Exception ex) {// 记录日志// 发送消息给运维// 发送邮件给开发人员 ,ex 对象发送给开发人员ex.printStackTrace();return new R(false, null, "系统错误,请稍后再试!");}}
修改表现层返回结果的模型类,封装出现异常后对应的信息
flag:false
Data: null
消息(msg): 要显示信息@Datapublic class R {private Boolean flag;private Object data;private String msg;public R() {}public R(Boolean flag) {this.flag = flag;}public R(Boolean flag, Object data) {this.flag = flag;this.data = data;}public R(Boolean flag, String msg) {this.flag = flag;this.msg = msg;}public R(String msg) {this.flag = false;this.msg = msg;}}
页面消息处理,没有传递消息加载默认消息,传递消息后加载指定消息
//添加handleAdd() {axios.post("/books", this.formData).then((res) => {//判断当前操作是否成功if (res.data.flag) {//1.关闭弹层this.dialogFormVisible = false;this.$message.success("添加成功");} else {this.$message.error(res.data.msg);}}).finally(() => {//2.重新加载数据this.getAll();})}
在表现层Controller中进行消息统一处理
@PostMappingpublic R save(@RequestBody Book book) throws IOException {//if (book.getName().equals("123")) throw new IOException();boolean flag = bookService.save(book);return new R(flag, flag ? "添加成功^_^" : "添加失败-_-!");}
页面消息处理
//添加handleAdd() {axios.post("/books", this.formData).then((res) => {//判断当前操作是否成功if (res.data.flag) {//1.关闭弹层this.dialogFormVisible = false;this.$message.success(res.data.msg);} else {this.$message.error(res.data.msg);}}).finally(() => {//2.重新加载数据this.getAll();})}
小结:
- 使用注解@RestControllerAdvice定义SpringMVC异常处理器用来处理异常的
- 异常处理器必须被扫描加载,否则无法生效
- 表现层返回结果的模型类中添加消息属性用来传递消息到页面
分页
页面使用 el 分页组件添加分页功能 ```html
- 定义分页组件需要使用的数据并将数据绑定到分页组件```vuedata: {pagination: { // 分页相关模型数据currentPage: 1, // 当前页码pageSize: 10, // 每页显示的记录数total: 0, // 总记录数}}
替换查询全部功能为分页功能
getAll() {axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize).then((res) => {});}
分页查询
使用路径参数传递分页数据或封装对象传递数据@GetMapping("{currentPage}/{pageSize}")public R getPage(@PathVariable Integer currentPage, @PathVariable int pageSize) {return new R(true, bookService.getPage(currentPage, pageSize));}
加载分页数据
//分页查询getAll() {//发送异步请求axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize).then((res) => {//console.log(res.data);this.pagination.currentPage = res.data.data.current;this.pagination.pageSize = res.data.data.size;this.pagination.total = res.data.data.total;this.dataList = res.data.data.records;})}
分页页码值切换
//切换页码handleCurrentChange(currentPage) {//修改页码值为当前选中的页码值this.pagination.currentPage = currentPage;//执行查询this.getAll();}
小结:
- 使用el分页组件
- 定义分页组件绑定的数据模型
- 异步调用获取分页数据
- 分页数据页面回显
分页功能维护(删除BUG)
- 对查询结果进行校验,如果当前页码值大于最大页码值,使用最大页码值作为当前页码值重新查询
小结:@GetMapping("{currentPage}/{pageSize}")public R getPage(@PathVariable Integer currentPage, @PathVariable int pageSize) {IPage<Book> page = bookService.getPage(currentPage, pageSize);// 如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值if (currentPage > page.getPages()) {page = bookService.getPage((int) page.getPages(), pageSize);}return new R(true, page);}
- 基于业务需求维护删除功能
条件查询
查询条件数据封装
单独封装
与分页操作混合封装pagination: {//分页相关模型数据currentPage: 1,//当前页码pageSize: 10,//每页显示的记录数total: 0,//总记录数type: "",name: "",description: ""}
使用v-model实现页面数据模型绑定
<div class="filter-container"><el-input placeholder="图书类别" v-model="pagination.type" class="filter-item" /><el-input placeholder="图书名称" v-model="pagination.name" class="filter-item" /><el-input placeholder="图书描述" v-model="pagination.description" class="filter-item" /><el-button @click="getAll()" class="dalfBut">查询</el-button><el-button type="primary" class="butT" @click="handleCreate()">新建</el-button></div>
组织数据成为get请求发送的数据
//分页查询getAll() {console.log(this.pagination.type);// /books/1/10?type=???&name=???&decription=?? ;//1. 获取查询条件 , 拼接查询条件param = "?name=" + this.pagination.name;param += "&type=" + this.pagination.type;param += "&description=" + this.pagination.description;//console.log("-----------------" + param);//发送异步请求axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize + param).then((res) => {//console.log(res.data);this.pagination.currentPage = res.data.data.current;this.pagination.pageSize = res.data.data.size;this.pagination.total = res.data.data.total;this.dataList = res.data.data.records;})}
条件参数组织可以通过条件判定书写的更简洁
Controller接收参数
@GetMapping("/{current}/{pageSize}")// 传递的参数名为name,type,description,参数名与实体类Book中的属性名一直,SpringMVC自动为实体类注入属性public R getPage(@PathVariable int current, @PathVariable int pageSize, Book book){IPage<Book> page = bookService.getPage(current, pageSize, book);// 如果当前页码值大于总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值if (current > page.getPages()){page = bookService.getPage((int) page.getPages(), pageSize, book);}return new R(true, page);}
业务层接口功能开发
/*** 分页的条件查询** @param currentPage* @param pageSize* @param book* @return*/IPage<Book> getPage(Integer currentPage, int pageSize, Book book);
业务层接口实现类功能开发
@Overridepublic IPage<Book> getPage(int current, int pageSize, Book book) {LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();// like的参数:第一个是条件,第二个是对应的属性,第三个是对应的值lqw.like(Strings.isNotEmpty(book.getType()), Book::getType, book.getType());lqw.like(Strings.isNotEmpty(book.getName()), Book::getName, book.getName());lqw.like(Strings.isNotEmpty(book.getDescription()), Book::getDescription, book.getDescription());IPage page = new Page(current, pageSize);bookDao.selectPage(page, lqw);// selectPage()之后page对象会被修改,最后还是返回page对象return page;}
Controller调用业务层分页条件查询接口
@GetMapping("/{current}/{pageSize}")// 传递的参数名为name,type,description,参数名与实体类Book中的属性名一直,SpringMVC自动为实体类注入属性public R getPage(@PathVariable int current, @PathVariable int pageSize, Book book){IPage<Book> page = bookService.getPage(current, pageSize, book);// 如果当前页码值大于总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值if (current > page.getPages()){page = bookService.getPage((int) page.getPages(), pageSize, book);}return new R(true, page);}
页面回显数据
//分页查询getAll() {console.log(this.pagination.type);// /books/1/10?type=???&name=???&decription=?? ;//1. 获取查询条件 , 拼接查询条件param = "?name=" + this.pagination.name;param += "&type=" + this.pagination.type;param += "&description=" + this.pagination.description;//console.log("-----------------" + param);//发送异步请求axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize + param).then((res) => {//console.log(res.data);this.pagination.currentPage = res.data.data.current;this.pagination.pageSize = res.data.data.size;this.pagination.total = res.data.data.total;this.dataList = res.data.data.records;})}
小结:
- 定义查询条件数据模型(当前封装到分页数据模型中)
- 异步调用分页功能并通过请求参数传递数据到后台
流程总结
- pom.xml
- 配置起步依赖
- application.yml
- 设置数据源、端口、框架技术相关配置等
- dao
- 继承BaseMapper、设置@Mapper
- dao测试类
- service
- 调用数据层接口或MyBatis-Plus提供的接口快速开发
- service测试类
- controller
- 基于Restful开发,使用Postman测试跑通功能
- 页面
- 放置在resources目录下的static目录中
