SSMP:基于SpringBoot,把spring、spring mvc、MyBatis plus 整合在一起
本案例不区分前端服务器后端服务器,整合在一起
本案例使用的如下技术如果不清楚请点下面的链接:
目录
1 pom文件添加MyBatis plus、druid、lombok的依赖
开始
一 数据层
1.1 搭建项目,完成CRUD
创建新模块--spring initializr--勾选SQL里的 mysql driver,web里的spring web
步骤
1 pom文件添加MyBatis plus、druid、lombok的依赖
2 配置文件
3 实体类
4 dao
5 测试类
代码
1 pom文件添加MyBatis plus、druid、lombok的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2 配置文件
yaml
server:
port: 80
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: 123456
#主键不用MyBatis plus的雪花算法,用数据库的主键自增
mybatis-plus:
global-config:
db-config:
id-type: auto
3 实体类
package com.qing.domain;
import lombok.*;
@Data
public class Book {
private Integer id;
private String name;
private String type;
private String description;
}
4 dao
package com.qing.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qing.domain.Book;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Repository
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
5 测试类
package com.qing.dao;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class DaoTest {
@Autowired
BookDao bookDao;
//通过id查询
@Test
public void testGetById() {
System.out.println(bookDao.selectById(1));
}
//查询所有
@Test
public void testGetAll() {
List<Book> books = bookDao.selectList(null);
for (Book book : books) {
System.out.println(book);
}
}
//条件查询 写法1
@Test
public void testSelectBy() {
QueryWrapper<Book> wrapper = new QueryWrapper<>();
//查询type为教科书的所有书
wrapper.like("type", "教科书");
bookDao.selectList(wrapper);
}
//条件查询 写法2(推荐)
@Test
public void testSelectBy2() {
LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
String bookType = "教科书";
//查询type为教科书的所有书
//这样就不会写错列名了
//if(bookType!=null) wrapper.like(Book::getType,bookType);
// wrapper.like(bookType!=null,Book::getType,bookType);
wrapper.like(Strings.isNotEmpty(bookType), Book::getType, bookType);
bookDao.selectList(wrapper);
}
//新增
@Test
public void testSave() {
Book book = new Book();
book.setName("小飞象");
book.setDescription("小飞象的一生");
book.setType("童话");
System.out.println(bookDao.insert(book));
testGetAll();
}
//删除
@Test
public void testDelete() {
System.out.println(bookDao.deleteById(4));
testGetAll();
}
//修改
@Test
public void testUpdate() {
Book book = new Book();
book.setId(1);
book.setName("大学计算机基础");
book.setDescription("计算机的原理");
book.setType("教科书");
System.out.println(bookDao.updateById(book));
testGetAll();
}
//分页
@Test
public void testPage() {
//new Page():参数1为第几页,参数2为一页有几条
IPage page = new Page(2, 3);
bookDao.selectPage(page, null);
System.out.println("当前是第" + page.getCurrent() + "页");
System.out.println("每页" + page.getSize() + "条");
System.out.println("总共" + page.getTotal() + "条数据");
System.out.println("总共" + page.getPages() + "页");
//返回当前page的列表信息
List<Book> books = page.getRecords();
for (Book book : books) {
System.out.println(book);
}
}
}
1.2 开启MyBatis plus的日志
yaml
#主键不用MyBatis plus的雪花算法,用数据库的主键自增
mybatis-plus:
global-config:
db-config:
id-type: auto
#开启MyBatis plus的日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
1.3 分页
1 写拦截器配置类
添加MyBatis plus提供的拦截器
package com.qing.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;
//MyBatis plus分页拦截器的配置
//指定该类为配置类
@Configuration
public class MpConfig {
//注入当前方法的 返回值 ,存入spring 的IOC 容器中
@Bean
public MybatisPlusInterceptor lanjie(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
2 测试类
测试类
//分页
@Test
public void testPage() {
//new Page():参数1为第几页,参数2为一页有几条
IPage page = new Page(2,3);
bookDao.selectPage(page, null);
System.out.println("当前是第"+page.getCurrent()+"页");
System.out.println("每页"+page.getSize()+"条");
System.out.println("总共"+page.getTotal()+"条数据");
System.out.println("总共"+page.getPages()+"页");
//返回当前page的列表信息
List<Book> books = page.getRecords();
for (Book book:books) {
System.out.println(book);
}
}
结果
1.4 条件查询
//条件查询 写法1
@Test
public void testSelectBy() {
QueryWrapper<Book> wrapper = new QueryWrapper<>();
//查询type为教科书的所有书
wrapper.like("type","教科书");
bookDao.selectList(wrapper);
}
//条件查询 写法2(推荐)
@Test
public void testSelectBy2() {
LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
String bookType = "教科书";
//查询type为教科书的所有书
//这样就不会写错列名了
//if(bookType!=null) wrapper.like(Book::getType,bookType);
// wrapper.like(bookType!=null,Book::getType,bookType);
wrapper.like(Strings.isNotEmpty(bookType),Book::getType,bookType);
bookDao.selectList(wrapper);
}
二 业务层
方法1 基础CRUD
service
package com.qing.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qing.domain.Book;
import java.util.List;
public interface BookService {
Boolean save(Book book);
Boolean update(Book book);
Boolean delete(Integer id);
Book getById(Integer id);
List<Book> getAll();
List<Book> getByName(String name);
IPage<Book> getPage(int currentPage,int pageSize);
}
impl
package com.qing.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.BookService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
//增
@Override
public Boolean save(Book book) {
return bookDao.insert(book) > 0;
}
//改
@Override
public Boolean update(Book book) {
return bookDao.updateById(book)>0;
}
//删
@Override
public Boolean delete(Integer id) {
return bookDao.deleteById(id)>0;
}
//查1
@Override
public Book getById(Integer id) {
return bookDao.selectById(id);
}
//条件查询--通过书名查询
@Override
public List<Book> getByName(String name) {
LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
wrapper.like(Strings.isNotEmpty(name),Book::getName,name);
return bookDao.selectList(wrapper);
}
//查所有
@Override
public List<Book> getAll() {
return bookDao.selectList(null);
}
//分页
@Override
public IPage<Book> getPage(int currentPage, int pageSize) {
return bookDao.selectPage(new Page(currentPage,pageSize),null);
}
}
测试类
package com.qing.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import com.qing.service.impl.BookServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class BookServiceTest {
@Autowired
BookServiceImpl bookServiceImpl;
//查1
@Test
public void testGetById(){
System.out.println(bookServiceImpl.getById(5));
}
//查询所有
@Test
public void testGetAll() {
List<Book> books = bookServiceImpl.getAll();
for (Book book : books) {
System.out.println(book);
}
}
//条件查询 -- 通过书名查询
@Test
public void testSelectByName() {
bookServiceImpl.getByName("jav");
}
//新增
@Test
public void testSave() {
Book book = new Book();
book.setName("怎样写故事");
book.setDescription("学写生动的故事");
book.setType("工具书");
System.out.println(bookServiceImpl.save(book));
testGetAll();
}
//删除
@Test
public void testDelete() {
System.out.println(bookServiceImpl.delete(3));
testGetAll();
}
//修改
@Test
public void testUpdate() {
Book book = new Book();
book.setId(1);
book.setName("英语1");
book.setDescription("好好学英语");
book.setType("教科书");
System.out.println(bookServiceImpl.update(book));
testGetAll();
}
//分页
@Test
public void testPage() {
IPage<Book> page = bookServiceImpl.getPage(2,4);
//返回当前page的列表信息
System.out.println("当前是第"+page.getCurrent()+"页");
System.out.println("每页"+page.getSize()+"条");
System.out.println("总共"+page.getTotal()+"条数据");
System.out.println("总共"+page.getPages()+"页");
List<Book> books = page.getRecords();
for (Book book:books) {
System.out.println(book);
}
}
}
部分测试结果
*方法2 基于MyBatis plus的快速开发
步骤
1 service 继承IService<bean类>
2 Serviceimpl 继承ServiceImpl<Dao, bean类> 实现 service
备注:如果有MyBatis plus 没提供的方法,自己手动在service 和 impl添加就好了(添加的方法注意不要和已有的重名)
service
package com.qing.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qing.domain.Book;
public interface IBookService extends IService<Book> {
}
impl
package com.qing.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.IBookService;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
}
测试类
package com.qing.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.domain.Book;
import com.qing.service.impl.BookServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class BookServiceTest {
@Autowired
BookServiceImpl bookServiceImpl;
//查1
@Test
public void testGetById() {
System.out.println(bookServiceImpl.getById(8));
}
//查询所有
@Test
public void testGetAll() {
List<Book> books = bookServiceImpl.list();
for (Book book : books) {
System.out.println(book);
}
}
//条件查询
@Test
public void testSelectByName() {
String bookName="怎样";
LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
wrapper.like(Strings.isNotEmpty(bookName),Book::getName,bookName);
List<Book> books = bookServiceImpl.list(wrapper);
for (Book book:books) {
System.out.println(book);
}
}
//新增
@Test
public void testSave() {
Book book = new Book();
book.setName("怎样找对象");
book.setDescription("泡妹子方法大全");
book.setType("工具书");
System.out.println(bookServiceImpl.save(book));
testGetAll();
}
//删除
@Test
public void testDelete() {
System.out.println(bookServiceImpl.removeById(1));
testGetAll();
}
//修改
@Test
public void testUpdate() {
Book book = new Book();
book.setId(6);
book.setName("英语1");
book.setDescription("好好学英语");
book.setType("教科书");
System.out.println(bookServiceImpl.updateById(book));
testGetAll();
}
//分页
@Test
public void testPage() {
IPage<Book> page = new Page<Book>(2, 3);
bookServiceImpl.page(page);
//返回当前page的列表信息
System.out.println("当前是第" + page.getCurrent() + "页");
System.out.println("每页" + page.getSize() + "条");
System.out.println("总共" + page.getTotal() + "条数据");
System.out.println("总共" + page.getPages() + "页");
List<Book> books = page.getRecords();
for (Book book : books) {
System.out.println(book);
}
}
}
部分测试结果
三 表现层
基于restful进行表现层接口开发,使用postman测试表现层功能
业务层重新写了分页的方法 → 便于controller 使用
package com.qing.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qing.dao.BookDao;
import com.qing.domain.Book;
import com.qing.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
@Autowired
BookDao bookDao;
@Override
public IPage<Book> getPage(int currentPage, int pageSize) {
IPage<Book> page = new Page(currentPage, pageSize);
bookDao.selectPage(page,null);
return page;
}
}
3.1 正常封装数据格式一致
1 表现层消息一致处理
工具类,用于统一返回的数据格式
package com.qing.utils;
import lombok.Data;
//用于统一数据格式
@Data
public class R {
private Boolean flag;
private Object data;
public R() {
}
public R(Boolean flag) {
this.flag = flag;
}
public R(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
}
2 controller
package com.qing.controller;
import com.qing.domain.Book;
import com.qing.service.IBookService;
import com.qing.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService bookService;
//查1
@GetMapping("{id}")
public R getById(@PathVariable Integer id) {
return new R(true,bookService.getById(id));
}
//查询所有
@GetMapping
public R getAll() {
return new R(true,bookService.list());
}
//增 @RequestBody用于获取请求体数据
@PostMapping
public R save(@RequestBody Book book) {
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 Integer id) {
return new R(bookService.removeById(id));
}
//分页
@GetMapping("{currentPage}/{pageSize}")
public R getPage(@PathVariable int currentPage, @PathVariable int pageSize) {
return new R(true,bookService.getPage(currentPage, pageSize));
}
}
部分测试
添加
查询所有
分页
修改
*3.2 出现异常改进
1 出现异常
controller
postman测试:出现异常后,返回的数据格式又不统一了,不是flag和data了
2 解决异常
异常处理工具类
package com.qing.utils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//作为spring mvc的异常处理器
//@ControllerAdvice 和 @RestControllerAdvice两个注解都行
@RestControllerAdvice
public class ProjectExceptionAdvice {
//用这个方法 拦截所有的异常信息
@ExceptionHandler(Exception.class)
public R doException(Exception exception){
//记录日志
//通知运维
//通知开发
//在命令行打印异常信息在程序中出错的位置及原因
exception.printStackTrace();
return new R(false,"服务器故障,请稍后再试!");
}
}
表现层消息一致处理工具类
package com.qing.utils;
import lombok.Data;
//用于统一数据格式
@Data
public class R {
private Boolean flag;
private Object data;
private String message;
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 message) {
this.flag = flag;
this.message = message;
}
}
测试