SSMP开发
本篇笔记基于黑马程序员的SpringBoot教学视频,具体视频链接:黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战
创建项目
SpringMVC+SpringBoot+Mybatis-plus
勾选web、sql即可,其余手动装配
Mybatis-plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
Druid
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
lombok
<!-- 还需要安装lombok插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
创建实体Dao类和domain类
使用lombok技术快速封装Getter和Setter方法
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
基础CRUD
使用Mybatis-plus让Dao类继承BaseMapper进行快速开发
@Mapper
@Repository
public interface BookDao extends BaseMapper<Book> {}
在测试类中测试是否生效
@SpringBootTest
public class BookDaoTestCase {
@Autowired
private BookDao bookDao;
@Test
void getBookById() {
System.out.println(bookDao.selectById(1));
}
@Test
void save() {
Book book = new Book();
book.setName("test123");
book.setType("test123");
book.setDescription("test123");
bookDao.insert(book);
}
@Test
void update() {
Book book = new Book();
book.setId(13);
book.setName("测试测试");
book.setType("测试测试");
book.setDescription("测试测试");
bookDao.updateById(book);
}
@Test
void delete() {
bookDao.deleteById(13);
}
@Test
void getAll() {
System.out.println(bookDao.selectList(null));
}
}
Mybatis-plus配置
mybatis-plus:
global-config:
db-config:
# 表头名称
table-prefix: tbl_
# id设置自增需要进行该设置
id-type: auto
configuration:
# 日志打印方式配置
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
分页查询
通过Mybatis-plus内置的方法selectPage(Page, queryWrapper);进行设置分页数据请求
设置分页数据请求的时候需要进行配置类设置拦截器。
前端更方便的做法是先获取全部数据,再在element-ui等组件中设置current(第几页)、size(每页有几个数据)即可。
@Test
void getByPage() {
IPage page = new Page(1, 5);
bookDao.selectPage(page, null);
}
通过配置类设置拦截器
Mybatis-plus的配置类
通过该配置类设置拦截器能够完成分页操作
//有这个注解存在能被扫描到
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor MybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
Page可调用的方法
在前面创建了Page实例之后,我们可以调用实例的方法进行操作
page.getCurrent():获取现在第几页
page.getSize():获取每页几个数据
page.getPages():获取总页数
page.getTotal():获取数据总数
page.getRecords():获取全部数据
条件查询
使用QueryWrapper/LambdaQueryWrapper进行条件查询
//使用QueryWrapper进行条件查询,需要使用字符串,容易出错,不推荐,对应SQL语句:Preparing: SELECT id,type,name,description FROM tbl_book WHERE (name LIKE %Spring%)
@Test
void getByDetail() {
QueryWrapper<Book> qw = new QueryWrapper<>();
qw.like("name", "Spring");
bookDao.selectList(qw);
}
//使用LambdaQueryWrapper进行条件查询,可以通过调用来减少出错,推荐,对应SQL语句同上
@Test
void getByDetail2() {
String name = "Spring";
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Book::getName, name);
bookDao.selectList(lqw);
}
//当数据为null的时候的查询不会进行条件查询,而是返回所有的数据,对应SQL语句:SELECT id,type,name,description FROM tbl_book
@Test
void getByDetail3() {
String name = null;
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(name != null, Book::getName, lqw);
bookDao.selectList(lqw);
}
业务层
这个是SpringMVC比较慢的方式,Mybatis-plus提供了更快的方式给我们进行开发。
定义业务层接口BookService
public interface BookService {
boolean save(Book book);
boolean update(Book book);
boolean delete(Integer id);
Book getById(Integer id);
List<Book> getAll();
IPage getByPage(Integer current, Integer size);
}
定义业务层实现类BookServiceImpl,实现业务层接口
// 必须要这个@Service注解
@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;
}
@Override
public Book getById(Integer id) {
return bookDao.selectById(id);
}
@Override
public List<Book> getAll() {
return bookDao.selectList(null);
}
@Override
public IPage getByPage(Integer current, Integer size) {
IPage page = new Page(current, size);
return bookDao.selectPage(page, null);
}
}
测试类测试是否可行
@SpringBootTest
public class BookDaoTestCase {
@Autowired
private BookService bookService;
@Test
void getBookById() {
System.out.println(bookService.getById(1));
}
@Test
void save() {
Book book = new Book();
book.setName("test123");
book.setType("test123");
book.setDescription("test123");
bookService.save(book);
}
@Test
void update() {
Book book = new Book();
book.setId(16);
book.setName("测试测试");
book.setType("测试测试");
book.setDescription("测试测试");
bookService.update(book);
}
@Test
void delete() {
bookService.delete(15);
}
@Test
void getAll() {
System.out.println(bookService.getAll());
}
@Test
void getPage(){
System.out.println(bookService.getByPage(2, 5));
}
}
快速开发业务层
使用Mybatis-plus提供的方式可以实现快速开发业务层
业务层接口继承IService<Book>
业务可以自己进行扩展,但是尽量不要重写原来的方法
public interface IBookService extends IService<Book> {
// 可以自己进行扩展,但是尽量不要重写原来的方法
Book getBookByBookId(Integer id);
}
业务层实现类实现IBookService接口,并继承ServiceImpl<BookDao, Book>
之前在接口定义的方法要自己重写
@Service
public class BookServiceImplement extends ServiceImpl<BookDao, Book> implements IBookService {
@Autowired
private BookDao bookDao;
public Book getBookByBookId(Integer id) {
return bookDao.selectById(id);
}
}
测试类测试是否可行
@SpringBootTest
public class BookServiceTestCase_MP {
@Autowired
private IBookService iBookService;
@Test
void getBookById() {
System.out.println(iBookService.getById(1));
}
@Test
void save() {
Book book = new Book();
book.setName("test123");
book.setType("test123");
book.setDescription("test123");
iBookService.save(book);
}
@Test
void update() {
Book book = new Book();
book.setId(16);
book.setName("测试测试123");
book.setType("测试测试123");
book.setDescription("测试测试123");
iBookService.updateById(book);
}
@Test
void delete() {
iBookService.removeById(17);
}
@Test
void getAll() {
System.out.println(iBookService.list());
}
@Test
void getPage(){
IPage page = new Page<Book>(3, 5);
System.out.println(iBookService.page(page));
}
@Test
void getBookByBookId(){
iBookService.getBookByBookId(2);
}
}
控制层开发
教程中叫表现层,个人习惯不同我管他叫控制层Controller
写控制层代码和写测试类代码差不多,只是需要运用RESTful语法并Postman进行接口测试。
Controller类
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService iBookService;
@GetMapping("/{id}")
public Result getBookById(@PathVariable Integer id) {
return new Result(true, iBookService.getById(id));
}
@GetMapping
public Result getAll(){
return new Result(true, iBookService.list());
}
@PostMapping
public Result save(@RequestBody Book book){
return new Result(iBookService.save(book));
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id){
return new Result(iBookService.removeById(id));
}
@PutMapping
public Result update(@RequestBody Book book){
return new Result(iBookService.updateById(book));
}
@GetMapping("/{current}/{size}")
public Result getByPage(@PathVariable Integer current, @PathVariable Integer size){
return new Result(true, iBookService.getByPage(current, size));
}
}
运行SpringBoot启动类
使用Postman进行测试
数据一致性
前端在获取数据的时候需要获取一定格式的数据,这个时候可以使用工具类Result
// 不能漏这个注解
@Data
public class Result {
private Object data;
private boolean flag;
public Result(boolean flag) {
this.flag = flag;
}
public Result(boolean flag, Object data) {
this.data = data;
this.flag = flag;
}
}
返回的代码分为两部分,数据及状态码如图:
实际开发中并不会使用boolean类型作为状态码,而是类似于404、502等作为状态码。
前后端接口调用(前后端分离模式)
前端结构
https://gitee.com/Lindaxia1026/SSMP_vue.git
后端结构
https://gitee.com/Lindaxia1026/SSMP_SpringBoot.git
前后端分离跨域问题
什么是跨域?
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
该项目后端服务器是:http://localhost(浏览器默认端口号,即http://localhost:80)
前端服务器是:http://localhost:8080
两者的端口号不同所以造成了跨域
解决前后端分离跨域问题
方式一:
在每个controller类中加入@CrossOrigin注解(亲测有效)
// 用于前后端分离项目解决跨域问题
@CrossOrigin
public class BookController {}
方式二:
在 Controller的基类中加上 @CrossOrigin 注解然后其他 Controller 类就有了这个 @Controller