案例来源
黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)_哔哩哔哩_bilibili
基础篇整合案例
代码
jiong952/springBootStudy: 黑马2021教程代码 自用 (github.com)
整体框架
- 实体类开发————使用Lombok快速制作实体类
- Dao开发————整合MyBatisPlus,制作数据层测试类
- Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
- Controller开发————基于Restful开发,使用PostMan测试接口功能
- Controller开发————前后端开发协议制作
- 页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
- 列表、新增、修改、删除、分页、查询
- 项目异常处理
- 按条件查询————页面功能调整、Controller修正功能、Service修正功能
项目搭建
选择web、mysql再添加MP、Druid、lombok坐标
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
实体类
使用lombok
需要什么构造器自己创建
Dao层
接口
直接使用MP提供的BaseMapper
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
测试
养成习惯 写完做测试 保证方法都正确
package com.zjh.springboot009_ssmp;
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.zjh.springboot009_ssmp.dao.BookDao;
import com.zjh.springboot009_ssmp.pojo.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;
/**
* @author 张俊鸿
* @description:
* @since 2022-07-17 1:20
*/
@SpringBootTest
public class BookDaoTestCase {
@Autowired
private BookDao bookDao;
@Test
public void testById(){
System.out.println(bookDao.selectById(1));
}
@Test
public void getAll(){
bookDao.selectList(null);
}
@Test
public void getSave(){
Book book = new Book();
book.setName("书");
book.setDescription("这是书");
book.setType("书书");
bookDao.insert(book);
}
@Test
//分页
public void getByPage(){
IPage page = new Page(1,5);
bookDao.selectPage(page,null);
System.out.println(page.getPages());
System.out.println(page.getCurrent());
System.out.println(page.getRecords());
System.out.println(page.getSize());
System.out.println(page.getTotal());
}
@Test
//按条件查询 QueryWrapper
public void getByCondition(){
QueryWrapper<Book> qw = new QueryWrapper<>();
qw.like("name","C");
bookDao.selectList(qw);
}
@Test
//按条件查询 QueryWrapper
public void getByCondition2(){
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Book::getName,"C");
bookDao.selectList(lqw);
}
@Test
//按条件查询 QueryWrapper
public void getByCondition3(){
//业务中经常要判空操作
String name = "3";
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Strings.isNotEmpty(name),Book::getName,name);
bookDao.selectList(lqw);
}
}
Service层
接口 继承IService<>
基于MyBatisPlus进行增量开发 MP提供了一系列方法,如果不合适就自己再写 最好不要覆盖(检测覆盖使用搜索或者加一个@Override注解判断)
public interface BookService extends IService<Book> {
IPage<Book> getByPage(Integer currentPage, Integer pageSize);
IPage<Book> getByPage(Integer currentPage, Integer pageSize,Book book);
}
接口实现类 继承ServiceImpl
记得加@Service注入进容器
@Service
public class BookSeviceImpl extends ServiceImpl<BookDao, Book> implements BookService {
@Autowired
private BookDao bookDao;
@Override
public IPage<Book> getByPage(Integer currentPage, Integer pageSize) {
IPage page = new Page(currentPage,pageSize);
bookDao.selectPage(page,null);
return page;
}
@Override
public IPage<Book> getByPage(Integer currentPage, Integer pageSize, Book book) {
IPage page = new Page(currentPage,pageSize);
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
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());
bookDao.selectPage(page,lqw);
return page;
}
}
测试
package com.zjh.springboot009_ssmp;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjh.springboot009_ssmp.pojo.Book;
import com.zjh.springboot009_ssmp.service.BookService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author 张俊鸿
* @description:
* @since 2022-07-17 15:31
*/
@SpringBootTest
public class BookServiceTestCase {
@Autowired
private BookService bookService;
@Test
public void testById(){
System.out.println(bookService.getById(1));
}
@Test
public void getAll(){
bookService.list(null);
}
@Test
public void getSave(){
Book book = new Book();
book.setName("书");
book.setDescription("这是书");
book.setType("书书");
bookService.save(book);
}
@Test
//分页
public void getByPage(){
IPage page = new Page(1,5);
bookService.page(page,null);
System.out.println(page.getPages());
System.out.println(page.getCurrent());
System.out.println(page.getRecords());
System.out.println(page.getSize());
System.out.println(page.getTotal());
}
}
Controller层
- Rest风格
- 统一数据返回格式(前后端协议联调)
- 异常处理
- 将前端的消息统一由后端给出
封装返回值
自定义属性 需要什么增加什么
使用lombok
使用msg统一返回前端显示的交互信息
@Data
public 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(String msg) {
this.flag = false;
this.msg = msg;
}
public R(Boolean flag, String msg) {
this.flag = flag;
this.msg = msg;
}
}
Rest开发
@RestController
@RequestMapping(“/books”)
- 增post
- 删delete
- 改put
- 查get
- 路径参数@GetMapping(“{id}”) (@PathVariable Integer id)
- 统一结果处理
boolean flag = bookService.save(book);
return new R(flag,flag? "添加成功" : "添加失败");
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
/**查询单个**/
@GetMapping("{id}")
public R getById(@PathVariable Integer id){
if(bookService.getById(id) == null){
return new R(false,null);
}
return new R(true,bookService.getById(id));
}
/**查询全部**/
@GetMapping()
public R getAll(){
if(bookService.list() == null){
return new R(false,null);
}
return new R(true,bookService.list());
}
/**分页查询**/
@GetMapping("{currentPage}/{pageSize}")
public R getByPage(@PathVariable Integer currentPage, @PathVariable Integer pageSize, Book book){
IPage<Book> page = bookService.getByPage(currentPage, pageSize,book);
if(page == null){
return new R(false,null);
}
if(currentPage > page.getPages()){
page = bookService.getByPage((int) page.getPages(), pageSize,book);
}
return new R(true,page);
}
/**插入数据**/
@PostMapping
public R save(@RequestBody Book book) throws Exception {
// if(book.getName().equals("123")) throw new Exception(); //测试异常
boolean flag = bookService.save(book);
return new R(flag,flag? "添加成功" : "添加失败");
}
/**修改数据**/
@PutMapping
public R update(@RequestBody Book book){
boolean flag = bookService.updateById(book);
return new R(flag,flag? "更新成功" : "更新失败");
}
/**删除数据**/
@DeleteMapping("{id}")
public R delete(@PathVariable Integer id){
boolean flag = bookService.removeById(id);
return new R(flag,flag? "删除成功" : "删除失败");
}
}
异常处理
拦截器
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public R doException(Exception ex){
//记录日志
//通知运维
ex.printStackTrace();
return new R("服务器故障!!");
}
}
前端开发
前端页面存放与resources的static目录下
使用vue+elementUi
axios
axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+params).then((res)=>{
this.pagination.total = res.data.data.total;
this.pagination.currentPage = res.data.data.current;
this.pagination.pageSize = res.data.data.size;
this.dataList = res.data.data.records;
})