案例实现方案分析
实体类开发————使用Lombok快速制作实体类
Dao开发————整合MyBatisPlus,制作数据层测试类
Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
Controller开发————基于Restful开发,使用PostMan测试接口功能
Controller开发————前后端开发协议制作
页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
列表、新增、修改、删除、分页、查询
项目异常处理
按条件查询————页面功能调整、Controller修正功能、Service修正功能
1.模块创建
-
勾选SpringMVC与MySQL坐标
-
修改配置文件为yml格式
-
设置端口为80方便访问
2.实体类开发
Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency
lombok版本由SpringBoot提供,无需指定版本
常用注解:@Data
@Data public class Book { private Integer id; private String type; private String name; private String description; }
为当前实体类在编译期设置对应的get/set方法,toString方法,hashCode方法,equals方法等
3.数据层面开发
使用技术:MyBatis-plus+Druid
1.导入相对应的MyBatisPlus与Druid对应的starter
<!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> </dependency> <!--druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.16</version> </dependency>
2.配置数据源与MyBatisPlus对应的基础配置(id生成策略使用数据库自增策略)
#配置端口号 server: port: 80 #配置数据源druid spring: datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: 123456 #mp的配置 mybatis-plus: global-config: db-config: table-prefix: tbl_ #数据库id的自增策略 id-type: auto #配置日志 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
继承BaseMapper并指定泛型
@Mapper public interface BookDao extends BaseMapper<Book> { }
制作测试
@SpringBootTest public class BookTest { @Autowired private BookDao bookDao; @Test public void testById(){ Book byId = bookDao.selectById(2); System.out.println(byId); } @Test public void testSave(){ Book book=new Book(); book.setName("明朝那些事"); book.setType("有关历史"); book.setDescription("nib"); bookDao.insert(book); } @Test public void testDelete(){ bookDao.deleteById(15); } @Test public void testUpdata(){ Book book=new Book(); book.setId(16); book.setName("明朝那些事"); book.setType("有关历史"); book.setDescription("nibglss"); bookDao.updateById(book); } @Test public void testGetAll(){ System.out.println( bookDao.selectList(null)); } @Test public void testGetPage(){ //需要拦截器追加sql分页的sql语句 /* * 参数1:当前是第几页 * 参数2:每页显示的数据条数 * */ IPage page=new Page(2,5); bookDao.selectPage(page,null); System.out.println(page.getCurrent()); System.out.println(page.getPages()); System.out.println(page.getSize()); System.out.println(page.getRecords()); System.out.println(page.getTotal()); } //按条件查询 @Test public void testGetByCondition1(){ QueryWrapper<Book> queryWrapper=new QueryWrapper<Book>(); queryWrapper.like("name","spring");//select*from tbl_book where name like%spring% System.out.println( bookDao.selectList(queryWrapper)); } //使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象,所有查询操作封装成方法调用,支持动态拼写查询条件 @Test public void testGetByCondition2(){ String name="Spring"; LambdaQueryWrapper<Book> queryWrapper=new LambdaQueryWrapper<Book>(); //select*from tbl_book where name like%spring% queryWrapper.like(name!=null,Book::getName,name);//select*from tbl_book where name like%spring% System.out.println( bookDao.selectList(queryWrapper)); } }
分页操作是在MyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现
@Configuration//用于指定该类是spring配置类,创建容器时会从该类加载注解 public class MPConfig { @Bean//标注该方法的返回值会存储到Spring容器中 public MybatisPlusInterceptor mybatisPlusInterceptor(){ //拦截器的外壳 MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor(); // 用什么拦截器,加载什么拦截器 mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mybatisPlusInterceptor; } }
4.业务开发层
定义接口
public interface BookService { boolean save(Book book); boolean delete(Integer id); boolean update(Book book); Book getById(Integer id); List<Book> getAll(); IPage<Book> getByPage(int currentPage,int pageSize); }
实现层定义
@Service public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; public Boolean save(Book book) { return bookDao.insert(book) > 0; } public Boolean delete(Integer id) { return bookDao.deleteById(id) > 0; } public Boolean update(Book book) { return bookDao.updateById(book) > 0; } }
测试类定义
@SpringBootTest public class BookServiceTest { @Autowired private BookService bookService; @Test void testGetById(){ bookService.getById(9); } @Test void testGetAll(){ bookService.getAll(); } @Test void testGetByPage(){ bookService.getByPage(1,5); } }
5.业务层—快速开发
使用MyBatisPlus提供有业务层通用接口(ISerivce<T>)与业务层通用实现(ServiceImpl<M,T>)在通用类基础上做功能重载或功能追加 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
@Service public class IBookServiceImpl extends ServiceImpl<BookDao,Book> implements IBookService { }
测试
@SpringBootTest public class BookServiceTest2 { @Autowired private IBookServiceImpl bookService; @Test public void getById(){ System.out.println( bookService.getById(1)); } @Test public void selectAll(){ System.out.println(bookService.list()); } @Test public void delete(){ bookService.removeById(16); } @Test public void testSave(){ Book book=new Book(); book.setName("大名王朝"); book.setType("有关历史"); book.setDescription("nib"); bookService.save(book); } @Test public void testUpdata(){ Book book=new Book(); book.setId(14); book.setName("明朝那些事"); book.setType("有关历史"); book.setDescription("nibglss"); bookService.updateById(book); } @Test public void testGetByPage(){ IPage<Book> page = new Page<Book>(1,5); IPage<Book> byPage = bookService.page(page); List<Book> records = byPage.getRecords(); System.out.println(records); } }
总结:
-
使用通用接口(ISerivce<T>)快速开发Service
-
使用通用实现类(ServiceImpl<M,T>)快速开发ServiceImpl
-
可以在通用接口基础上做功能重载或功能追加
-
注意重载时不要覆盖原始操作,避免原始提供的功能丢失
6.表现层开发
基于Restful进行表现层接口开发
使用Postman测试表现层接口功能
1.功能测试
2.表现层接口开发
总结
\1. 基于Restful制作表现层接口
新增:POST
删除:DELETE
修改:PUT
查询:GET
\2. 接收参数
实体数据:@RequestBody
路径变量:@PathVariable
3.表现层消息的统一处理
问题:无法判断时因为id不存在返回的null,还是因为抛出异常返回null
设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称前后端数据协议
package com.lin.controller.utils; //前后端联调 public class Result { private boolean flag; private Object data; public Result() { } public Result(boolean flag) { this.flag=flag; } public Result(boolean flag, Object data) { this.flag = flag; this.data = data; } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } @Override public String toString() { return "Result{" + "flag=" + flag + ", data=" + data + '}'; } }
表现层接口统一返回类型结果
@RestController @RequestMapping("/books") public class BookController2 { @Autowired private IBookService bookService; //查询所有 @GetMapping public Result getAll(){ Result result=new Result(true,bookService.list()); return result; } //添加 @PostMapping //@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的); public Result save(@RequestBody Book book){ return new Result(bookService.save(book)); } //更新 @PutMapping public Result update(@RequestBody Book book){ return new Result(bookService.updateById(book)); } //删除 //通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器(controller)处理方法的形参中:URL 中的 {xxx} 占位符可以通过 @DeleteMapping("{id}") public Result delete(@PathVariable Integer id){ return new Result(bookService.removeById(id)); } //通过id查询 @GetMapping("{id}") public Result getById(@PathVariable Integer id){ return new Result(true,bookService.getById(id)); } //分页查询 @GetMapping("{current}/{pageSize}") public Result getByPage(@PathVariable int current,@PathVariable int pageSize){ return new Result(true,bookService.page(current,pageSize)); } }
总结:
1.设计统一的返回值结果便于前端开发读取数据
2.返回值类型可以根据自己的需求设定,没有固定的格式
3.返回值结果模型类用于后端与前端进行数据格式的统一,前后端数据协议