

简而言之:

具体步骤如下:
1、创建新模块,并勾选web与sql技术集:

2、手动导入所需的额外依赖:
- <dependency>
- <groupId>com.baomidougroupId>
- <artifactId>mybatis-plus-boot-starterartifactId>
- <version>3.5.1version>
- dependency>
-
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druid-spring-boot-starterartifactId>
- <version>1.2.6version>
- dependency>
-
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- dependency>
3、修改配置文件:
- server:
- port: 80
-
- spring:
- datasource:
- druid:
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
- username: root
- password: mypassword
-
- mybatis-plus:
- configuration:
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4、表:

5、构建实体类:
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @TableName("boot_book")
- public class Book extends Model
{ -
- @TableId(type = IdType.AUTO)
- private Integer id;
- private String type;
- private String name;
- private String description;
-
- }
1、构建mapper接口:
- @Mapper
- public interface BookMapper extends BaseMapper
{ - }
2、配置文件中开启日志,并设置为标准输出:
- mybatis-plus:
- configuration:
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3、配置MP分页插件:
由于没有applicationContext.xml,配置方法与传统MP不同
- package com.kvno.config;
-
- import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
- import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- @Configuration
- public class MPConfig {
-
- //分页插件
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor(){
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
- return interceptor;
- }
-
- }
4、编写测试类:
- @SpringBootTest
- public class MapperTestCase {
- @Autowired
- BookMapper bookMapper;
-
- @Test
- public void testGetById() {
- System.out.println(bookMapper.selectById(1));
- }
-
- @Test
- public void testInsert() {
- Book book = new Book();
- book.setName("海绵宝宝");
- book.setType("CH");
- book.setDescription("yellow");
-
- boolean result = book.insert();
- System.out.println(result);
- }
-
- @Test
- public void testUpdate() {
- Book book = new Book();
- book.setId(3);
- book.setName("海绵宝宝");
- book.setType("CH");
- book.setDescription("square");
-
- boolean result = book.updateById();
- System.out.println(result);
- }
-
- @Test
- public void testGetAll() {
- List
books = bookMapper.selectList(null); - for (Book book: books) {
- System.out.println(book);
- }
- }
-
- @Test
- public void testGetPage() {
- IPage
page = new Page<>(1,1); - bookMapper.selectPage(page,null);
- System.out.println(page.getCurrent());
- System.out.println(page.getSize());
- System.out.println(page.getTotal());
- System.out.println(page.getPages());
- System.out.println(page.getRecords());
- }
-
- @Test
- public void testWrapper() {
- QueryWrapper
userQueryWrapper = new QueryWrapper<>(); - userQueryWrapper.eq("type","CH");
- bookMapper.selectList(userQueryWrapper);
- }
- }

1、定义接口并编写实现类:
- public interface BookService {
- Boolean insert(Book book);
- Boolean update(Book book);
- Boolean delete(Integer id);
- Book getById(Integer id);
- List
getAll(); - IPage getPage(Integer currentpage,Integer sizePage);
- }
- @Service
- public class BookServiceImpl implements BookService {
- @Autowired
- private BookMapper bookMapper;
-
- @Override
- public Boolean insert(Book book) {
- return book.insert();
- }
-
- @Override
- public Boolean update(Book book) {
- return book.updateById();
- }
-
- @Override
- public Boolean delete(Integer id) {
- return bookMapper.deleteById(id) > 0;
- }
-
- @Override
- public Book getById(Integer id) {
- return bookMapper.selectById(id);
- }
-
- @Override
- public List
getAll() { - return bookMapper.selectList(null);
- }
-
- @Override
- public IPage getPage(Integer currentpage, Integer sizePage) {
- IPage page = new Page(currentpage,sizePage);
- return bookMapper.selectPage(page,null);
- }
-
- }
2、编写测试类:
- @SpringBootTest
- public class ServiceTestCase {
- @Autowired
- private BookService bookService;
-
- @Test
- void testGetById() {
- System.out.println(bookService.getById(1));
- }
-
- @Test
- public void testInsert() {
- Book book = new Book();
- book.setName("test");
- book.setType("CH");
- book.setDescription("service");
- bookService.insert(book);
- }
-
- @Test
- void testUpdate(){
- Book book = new Book();
- book.setId(4);
- book.setDescription("测试数据service");
- bookService.update(book);
- }
-
- @Test
- void testDelete(){
- bookService.delete(4);
- }
-
- @Test
- void testGetAll(){
- bookService.getAll();
- }
-
- @Test
- public void testGetPage() {
- IPage page = bookService.getPage(2,1);
- System.out.println(page.getCurrent());
- System.out.println(page.getSize());
- System.out.println(page.getTotal());
- System.out.println(page.getPages());
- System.out.println(page.getRecords());
- }
- }
使用MyBatisPlus提供有业务层通用接口(ISerivce
在通用类基础上做功能重载或功能追加;
可以编写额外方法,注意重载时不要覆盖原始操作,避免原始提供的功能丢失。
与MP提供的BaseMapper类似,封装了各种业务层方法。简化了开发过程。
1、接口与实现类:
- public interface IBookService extends IService
{ - boolean saveBook(Book book);
-
- IPage
getPage(int currentPage, int pageSize, Book book); - }
- @Service
- public class QuickBookServiceImp extends ServiceImpl
implements IBookService { - @Autowired
- private BookMapper bookMapper;
-
- @Override
- public boolean saveBook(Book book) {
- return bookMapper.insert(book) > 0;
- }
-
-
- @Override
- public IPage
getPage(int currentPage, int pageSize, Book book) { - LambdaQueryWrapper
wrapper = new LambdaQueryWrapper(); - wrapper.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
- wrapper.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
- wrapper.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
- IPage page = new Page(currentPage,pageSize);
- bookMapper.selectPage(page,wrapper);
-
- return page;
- }
- }
2、测试:
- @SpringBootTest
- public class QuickServiceTestCase {
- @Autowired
- private IBookService bookService;
-
- @Test
- void testGetById() {
- System.out.println(bookService.getById(1));
- }
-
- @Test
- public void testSave() {
- Book book = new Book();
- book.setName("test");
- book.setType("CH");
- book.setDescription("service");
- bookService.save(book);
- }
-
- @Test
- void testUpdate(){
- Book book = new Book();
- book.setId(4);
- book.setDescription("测试数据service");
- bookService.updateById(book);
- }
-
- @Test
- void testDelete(){
- bookService.removeById(4);
- }
-
- @Test
- void testGetAll(){
- bookService.list();
- }
-
- @Test
- public void testGetPage() {
- IPage page = new Page(2,1);
- bookService.page(page);
- System.out.println(page.getCurrent());
- System.out.println(page.getSize());
- System.out.println(page.getTotal());
- System.out.println(page.getPages());
- System.out.println(page.getRecords());
- }
- }

1、编写controller:
注:@RequestBody:接收前端传递给后端的请求体中的数据。
- /*
- 表现层 测试业务层接口
- @RequestBody:接收前端传递给后端的请求体中的数据
- */
-
- //@RestController
- @RequestMapping("/books")
- public class BookControllerTest {
- @Autowired
- private IBookService bookService;
-
- @GetMapping
- public List
getAll() { - return bookService.list();
- }
-
- @PostMapping
- public Boolean save(@RequestBody Book book) { //@RequestBody
- return bookService.save(book);
- }
-
- @PutMapping
- public Boolean update(@RequestBody Book book) {
- return bookService.updateById(book);
- }
-
- @DeleteMapping("/{id}")
- public Boolean delete(@PathVariable(value = "id") Integer id) {
- return bookService.removeById(id);
- }
-
- @GetMapping("/{id}")
- public Book getById(@PathVariable(value = "id") Integer id) {
- return bookService.getById(id);
- }
-
- @GetMapping("/{currentPage}/{pageSize}")
- public IPage
getPage(@PathVariable int currentPage, @PathVariable int pageSize){ - IPage page = new Page(currentPage,pageSize);
- return bookService.page(page);
- }
-
- }
2、测试:


返回数据类型不一致会给前端带来不便:

单纯地封装数据又会造成误解,如数据为null时:

故采用以下格式:

优点:

示例:
1、设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议:
- /*
- 统一表现层响应的数据返回值类型
- */
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class R { //Result
- private Boolean flag;
- private Object data;
-
- public R(Boolean flag) {
- this.flag = flag;
- }
- }
2、编写controller:
- /*
- 统一了返回值类型的正式版表现层
- */
-
- @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) { //@RequestBody:接收前端传递给后端的请求体中的数据
- return new R(bookService.save(book));
- }
-
- @PutMapping
- public R update(@RequestBody Book book) {
- return new R(bookService.updateById(book));
- }
-
- @DeleteMapping("/{id}")
- public R delete(@PathVariable(value = "id") Integer id) {
- return new R(bookService.removeById(id));
- }
-
- @GetMapping("/{id}")
- public R getById(@PathVariable(value = "id") Integer id) {
- return new R(true,bookService.getById(id));
- }
-
- @GetMapping("/{currentPage}/{pageSize}")
- public R getPage(@PathVariable int currentPage, @PathVariable int pageSize){
- return new R(true,bookService.page(new Page(currentPage,pageSize)));
- }
-
- }
3、测试:






1、使用注解@RestControllerAdvice定义SpringMVC异常处理器,异常处理器必须被扫描加载,否则无法生效;对异常消息进行统一处理,出现异常后返回指定类型:
- @RestControllerAdvice
- public class ProjectExceptionAdvice {
-
- //拦截所有的异常信息
- @ExceptionHandler(Exception.class)
- public R doException(Exception ex){
- //记录日志
- //通知运维
- //通知开发
- ex.printStackTrace(); //控制台仍然要显示异常
- return new R(false,"服务器故障,请稍后再试!");
- }
-
- }
2、修改表现层返回结果的模型类,封装出现异常后对应的信息:
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class R { //Result
- private Boolean flag;
- private Object data;
- private String msg;
-
- 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;
- }
- }


- html>
-
- <html>
-
- <head>
-
-
-
- <meta charset="utf-8">
-
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
-
- <title>SpringBoot整合SSM案例title>
-
- <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
-
-
-
- <link rel="stylesheet" href="../plugins/elementui/index.css">
-
- <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
-
- <link rel="stylesheet" href="../css/style.css">
-
- head>
-
- <body class="hold-transition">
-
- <div id="app">
-
- <div class="content-header">
-
- <h1>图书管理h1>
-
- div>
-
- <div class="app-container">
-
- <div class="box">
-
- <div class="filter-container">
- <el-input placeholder="图书类别" v-model="pagination.type" style="width: 200px;" class="filter-item">el-input>
- <el-input placeholder="图书名称" v-model="pagination.name" style="width: 200px;" class="filter-item">el-input>
- <el-input placeholder="图书描述" v-model="pagination.description" style="width: 200px;" class="filter-item">el-input>
- <el-button @click="getAll()" class="dalfBut">查询el-button>
- <el-button type="primary" class="butT" @click="handleCreate()">新建el-button>
- div>
-
- <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>
-
- <el-table-column type="index" align="center" label="序号">el-table-column>
-
- <el-table-column prop="type" label="图书类别" align="center">el-table-column>
-
- <el-table-column prop="name" label="图书名称" align="center">el-table-column>
-
- <el-table-column prop="description" label="描述" align="center">el-table-column>
-
- <el-table-column label="操作" align="center">
-
- <template slot-scope="scope">
-
- <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑el-button>
-
- <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除el-button>
-
- template>
-
- el-table-column>
-
- el-table>
-
-
- <div class="pagination-container">
-
- <el-pagination
- class="pagiantion"
-
- layout="total, prev, pager, next, jumper"
-
- @current-change="handleCurrentChange"
-
- :current-page.sync="pagination.currentPage"
-
- :page-size="pagination.pageSize"
-
- :total="pagination.total">
-
- el-pagination>
-
- div>
-
-
-
- <div class="add-form">
-
- <el-dialog title="新增图书" :visible.sync="dialogFormVisible">
-
- <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px">
-
- <el-row>
-
- <el-col :span="12">
-
- <el-form-item label="图书类别" prop="type">
-
- <el-input v-model="formData.type"/>
-
- el-form-item>
-
- el-col>
-
- <el-col :span="12">
-
- <el-form-item label="图书名称" prop="name">
-
- <el-input v-model="formData.name"/>
-
- el-form-item>
-
- el-col>
-
- el-row>
-
-
- <el-row>
-
- <el-col :span="24">
-
- <el-form-item label="描述">
-
- <el-input v-model="formData.description" type="textarea">el-input>
-
- el-form-item>
-
- el-col>
-
- el-row>
-
- el-form>
-
- <div slot="footer" class="dialog-footer">
-
- <el-button @click="cancel()">取消el-button>
-
- <el-button type="primary" @click="handleAdd()">确定el-button>
-
- div>
-
- el-dialog>
-
- div>
-
-
-
- <div class="add-form">
-
- <el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">
-
- <el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right" label-width="100px">
-
- <el-row>
-
- <el-col :span="12">
-
- <el-form-item label="图书类别" prop="type">
-
- <el-input v-model="formData.type"/>
-
- el-form-item>
-
- el-col>
-
- <el-col :span="12">
-
- <el-form-item label="图书名称" prop="name">
-
- <el-input v-model="formData.name"/>
-
- el-form-item>
-
- el-col>
-
- el-row>
-
- <el-row>
-
- <el-col :span="24">
-
- <el-form-item label="描述">
-
- <el-input v-model="formData.description" type="textarea">el-input>
-
- el-form-item>
-
- el-col>
-
- el-row>
-
- el-form>
-
- <div slot="footer" class="dialog-footer">
-
- <el-button @click="cancel()">取消el-button>
-
- <el-button type="primary" @click="handleEdit()">确定el-button>
-
- div>
-
- el-dialog>
-
- div>
-
- div>
-
- div>
-
- div>
-
- body>
-
-
- <script src="../js/vue.js">script>
-
- <script src="../plugins/elementui/index.js">script>
-
- <script type="text/javascript" src="../js/jquery.min.js">script>
-
- <script src="../js/axios-0.18.0.js">script>
-
- <script>
- var vue = new Vue({
- el: '#app',
- data:{
- dataList: [],//当前页要展示的列表数据
- dialogFormVisible: false,//添加表单是否可见
- dialogFormVisible4Edit:false,//编辑表单是否可见
- formData: {},//表单数据
- rules: {//校验规则
- type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],
- name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]
- },
- pagination: {//分页相关模型数据
- currentPage: 1,//当前页码
- pageSize:10,//每页显示的记录数
- total:0,//总记录数
- //条件查询
- type: "",
- name: "",
- description: ""
- },
- },
-
-
- //钩子函数,VUE对象初始化完成后自动执行,效果为每次打开页面都会执行该操作
- created() {
- this.getAll();
- },
-
- methods: {
- // //列表
- // getAll() {
- // //发送异步请求
- // axios.get("/books").then((res)=>{
- // // console.log(res.data);
- // this.dataList = res.data.data;
- // });
- // },
-
- //分页查询
- getAll() {
- //组织条件查询参数,拼接url请求地址
- param = "?type="+this.pagination.type;
- param +="&name="+this.pagination.name;
- param +="&description="+this.pagination.description;
-
- //发送异步请求
- axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res)=>{
- this.pagination.pageSize = res.data.data.size;
- this.pagination.currentPage = res.data.data.current;
- this.pagination.total = res.data.data.total;
-
- this.dataList = res.data.data.records;
- });
- },
-
- //切换页码
- handleCurrentChange(currentPage) {
- //修改页码值为当前选中的页码值
- this.pagination.currentPage = currentPage;
- //执行查询
- this.getAll();
- },
-
- //弹出添加窗口
- handleCreate() {
- this.dialogFormVisible = true;
- this.resetForm(); //重置表单
- },
-
- //重置表单
- resetForm() {
- this.formData = {};
- },
-
- //添加
- 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();
- });
- },
-
- //取消
- cancel(){
- this.dialogFormVisible = false;
- this.dialogFormVisible4Edit = false;
- this.$message.info("当前操作取消");
- },
-
- // 删除
- handleDelete(row) {
- this.$confirm("此操作永久删除当前信息,是否继续?","提示",{type:"info"}).then(()=>{
- axios.delete("/books/"+row.id).then((res)=>{
- if(res.data.flag){
- this.$message.success("删除成功");
- }else{
- this.$message.error("数据同步失败,自动刷新");
- }
- }).finally(()=>{
- //2.重新加载数据
- this.getAll();
- });
- }).catch(()=>{
- this.$message.info("取消操作");
- });
- },
-
- //弹出编辑窗口
- 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(()=>{
- //2.重新加载数据
- this.getAll();
- });
- },
-
- //修改
- 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();
- });
- },
-
- }
- })
-
- script>
-
- html>
- @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) throws IOException { //@RequestBody:接收前端传递给后端的请求体中的数据
- //测试异常消息一致性处理
- /*if(book.getName().equals("123")) {
- throw new IOException();
- }*/
-
- Boolean flag = bookService.save(book);
- return new R(flag,flag ? "添加成功" : "添加失败");
- }
-
- @PutMapping
- public R update(@RequestBody Book book) {
- return new R(bookService.updateById(book));
- }
-
- @DeleteMapping("/{id}")
- public R delete(@PathVariable(value = "id") Integer id) {
- return new R(bookService.removeById(id));
- }
-
- @GetMapping("/{id}")
- public R getById(@PathVariable(value = "id") Integer id) {
- return new R(true,bookService.getById(id));
- }
-
- @GetMapping("/{currentPage}/{pageSize}")
- public R getPage(@PathVariable int currentPage, @PathVariable int pageSize,Book book){
- IPage
page = bookService.getPage(currentPage, pageSize,book); - //如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
- if( currentPage > page.getPages()){
- page = bookService.getPage((int)page.getPages(), pageSize,book);
- }
- return new R(true, page);
- }
-
- }


