目录
1.案例不同模块的开发以所用技术汇总
=================================================
2.模块创建
3.实体类开发
3.1 创建数据库
3.2 创建对应的实体类 LomBok
4.数据层开发
4.1相关配置 配置MP与druid
4.2 创建数据层接口
——————Ctrl+F12 查看当前类的方法——————————
4.3效果测试
4.3.1 查询
4.3.2 添加
4.3.3 修改
4.3.4 删除及查询所有数据
4.3.5 分页
4.3.6 条件查询
4.4 MP运行日志 开启后可以看到具体的内容
5. 业务层开发
5.1 基础CUDA
5.2 快速开发,基于MyBatisPlus
6.表现层标准开发
7.前后端协议联调
7.1 前端发送异步请求,调用后端接口
7.2列表功能
8.
实体类开发————使用Lombok快速制作实体类
Dao开发————整合MybatisPius,制作数据层测试类
Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
Controller开发————基于Restful开发,使用PostMan测试接口功能
Controller开发————前后端开发协议制作
页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
列表,新增,修改,删除,分页,查询
项目异常处理
按条件查询————页面功能调整,Controller修正功能,Service修正功能
创建时,勾选web 与SQL连接, 随后手动添加MyBatis_puls与Druid,详见
SptingBoot项目创建与手动添加其他坐标https://blog.csdn.net/qq_45851715/article/details/125300671
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.1
com.example
demo_ssm
0.0.1-SNAPSHOT
demo_ssm
demo_ssm
1.8
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
runtime
com.baomidou
mybatis-plus-boot-starter
3.4.3
com.alibaba
druid-spring-boot-starter
1.2.6
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
这里为了测试是方便,将端口设为了80
server:
port: 80
Alt+7,查看方法
LomBok,一个Java类库,提供了一-组注解,简化P0J0实体类开发
a>导入坐标
org.projectlombok
lombok
b>在book。java 实体类中添加相应的方法
package com.example.demo_ssm.domain;
//采用lombok的形式快速开发
import lombok.*;
//@Getter 通过注解产生相应的get方法
//@Setter 通过注解产生相应的set方法
@Data //通过注解产生相应的 get/set/equals/hashCode/toString 方法 ??????无构造方法
//@AllArgsConstructor 全参构造方法
//@NoArgsConstructor 无参构造方法
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
server:
port: 80
#2.设置数据源参数
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/boot?serverTimezone=UTC
username: root
password: root
# 设置MP相关配置
## ??MP????
#mybatis-plus:
# global-config:
# db-config:
# table-prefix: tbl_
继承自BaseMapper
package com.example.demo_ssm.Dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo_ssm.domain.Book;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookDao extends BaseMapper {
}
@Test
//查询单个
void selectById() {
System.out.println(bookDao.selectById(1));
}
//结果 Book(id=1, type=玄幻, name=斗罗大陆, description=唐三)
直接使用会使报id错误,需要添加
mybatis-plus:
global-config:
db-config:
# table-prefix: tbl_
id-type: auto
@Test
//添加
void insert() {
Book book=new Book();
book.setType("AB");
book.setName("CD");
book.setDescription("EF");
System.out.println(bookDao.insert(book));
}
@Test
//修改,根据ID修改
void updateById() {
Book book = new Book();
book.setId(16);
book.setType("ABababab");
book.setName("CDcdcdcd");
book.setDescription("EFefefef");
System.out.println(bookDao.updateById(book));
}
@Test
void dome() {
//删除
bookDao.deleteById(16);
//查询全部数据
//条件构造器为空,这里为null意味没有条件,全部查询出来
bookDao.selectList(null);
}
为了实现分页,首先需要去配置拦截器
package com.example.demo_ssm.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 mybatisPlusInterceptor=new MybatisPlusInterceptor();
//addInnerInterceptor添加内部拦截器,
// PaginationInnerInterceptor 专门做分页的拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
@Test
void selectPage() {
IPage iPage=new Page(1,3);
bookDao.selectPage(iPage,null);
System.out.println("+++++++++++++++++++++");
System.out.println(iPage.getCurrent());//当前页条数
System.out.println(iPage.getSize());//每页的数据条数
System.out.println(iPage.getTotal());//总数据条数
System.out.println(iPage.getPages());//页数条数
System.out.println(iPage.getRecords());//所展示页的详细数据
System.out.println("++++++++++++++++++++");
}
从中可以看到count以及limit等这些用于分组的select语句
(注)如果不这样操作,即使使用了selectPage方法,也没有效果,
现将MPConfig注释掉
测试结果如下
一次直接查出了16条信息,写的分页,却没有效果
1.0
@Test
void tiaojianchaxun(){
//bug type属性值手打,万一写错了完犊子
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.like("type","玄幻");
bookDao.selectList(queryWrapper);
}
2.0
@Test
void tiaojianchaxun1(){
//采用 lambdaQueryWrapper 避免错误
String Type="玄幻";
LambdaQueryWrapper lambdaQueryWrapper=new LambdaQueryWrapper();
lambdaQueryWrapper.like(Type!=null,Book::getType,Type);
bookDao.selectList(lambdaQueryWrapper);
}
添加Mybatis-plus配置
mybatis-plus:
global-config:
db-config:
# table-prefix: tbl_
id-type: auto
configuration:
# StdOutImpl 标准输出 打印到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5.1.1 编写Service层接口,定义方法
package com.example.demo_ssm.service;
import com.example.demo_ssm.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 getAll();
}
5.1.2 定义BookService的实现类
package com.example.demo_ssm.service.impl;
import com.example.demo_ssm.Dao.BookDao;
import com.example.demo_ssm.domain.Book;
import com.example.demo_ssm.service.BookService;
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;
}
@Override
public Book getById(Integer id) {
return bookDao.selectById(id);
}
@Override
public List getAll() {
return bookDao.selectList(null);
}
}
5.1.3 编写测试类
package com.example.demo_ssm.service;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class BookServiceTestCase {
@Autowired
private BookService bookService;
@Test
void test(){
System.out.println(bookService.getById(3));
}
}
5.1.4 测试结果
Service接口名称定义成业务名称,并与Dao接口名称进行区分
制作测试类测试Service功能是否有效
接口的编写
package com.example.demo_ssm.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo_ssm.domain.Book;
public interface IBookService extends IService {
//定义自己的方法
//判断有没有和MP的方法重名,添加 @Override 注解,如果报错,是不重名
boolean savebook(Book book);
}
实现类的编写】
package com.example.demo_ssm.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo_ssm.Dao.BookDao;
import com.example.demo_ssm.domain.Book;
import com.example.demo_ssm.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl1 extends ServiceImpl implements IBookService {
//定义自己的方法
@Autowired
private BookDao bookDao;
@Override
public boolean savebook(Book book) {
return bookDao.insert(book)>0;
}
}
测试
package com.example.demo_ssm.service;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class BookServiceTestCase {
@Autowired
private IBookService bookService;
@Test
void test(){
System.out.println(bookService.getById(10));
}
}
测试结果
使用MyBatisPlus提供有业务层通用接口(ISerivce
在通用类基础上做功能重载或功能追加
注意重载时不要覆盖原始操作,避免原始提供的功能丢失
基于Restful进行表现层接口开发
使用Postman测试表现层接口功能
package com.example.demo_ssm.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.demo_ssm.domain.Book;
import com.example.demo_ssm.service.IBookService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService iBookService;
@GetMapping
public List getAll(){
return iBookService.list();
}
@PostMapping
public Boolean save(Book book){
return iBookService.save(book);
}
@PostMapping
public Boolean update(Book book){
return null;
}
@DeleteMapping("{id}")
public Boolean delete(@PathVariable Integer id){
return iBookService.removeById(id);
}
@GetMapping("{id}")
public Book getById(@PathVariable Integer id){
return iBookService.getById(id);
}
@GetMapping("{currentPage}/{pageSize}")
public IPage getPage(@PathVariable int currentPage,@PathVariable int pageSize) {
return iBookService.getPage(currentPage,pageSize);
}
}
设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议
package com.example.demo_ssm.controller.utils;
import lombok.Data;
@Data
public class R {
private Boolean flag;
private Object date;
public R() {}
public R(Boolean flag){
this.flag=flag;
}
public R(Boolean flag,Object date){
this.flag=flag;
this.date=date;
}
}
package com.example.demo_ssm.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.demo_ssm.controller.utils.R;
import com.example.demo_ssm.domain.Book;
import com.example.demo_ssm.service.IBookService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService iBookService;
@GetMapping
public R getAll(){
// return iBookService.list();
return new R(true,iBookService.list());
}
@PostMapping
public R save(Book book){
return new R(iBookService.save(book));
}
@PostMapping
public Boolean update(Book book){
return null;
}
@DeleteMapping("{id}")
public R delete(@PathVariable Integer id){
// return iBookService.removeById(id);
return new R(iBookService.removeById(id));
}
@GetMapping("{id}")
public R getById(@PathVariable Integer id){
// return iBookService.getById(id);
return new R(true,iBookService.getById(id));
}
@GetMapping("{currentPage}/{pageSize}")
public IPage getPage(@PathVariable int currentPage,@PathVariable int pageSize) {
return iBookService.getPage(currentPage,pageSize);
}
}
设计统--的返回值结果类型便于前端开发读取数据
返回值结果类型可以根据需求自行设定,没有固定格式
返回值结果模型类用于后端与前端进行数据格式统- -,也称为前后端数据协议
前后端分离结构设计中页面归属前端服务器
单体工程中页面放置在resources目录下的static目录中(建议执行clean)
需要放置文件如下
资源链接地址https://download.csdn.net/download/qq_45851715/85950895
单体项目中页面放置在resources/static目录下
created钩子函数用于初始化页面时发起调用
页面使用axios发送异步请求获取数据后确认前后端是否联通
将查询数据返回到页面,利用前端数据双向绑定进行数据展示
//弹出添加窗口
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.$message.info("当前操作取消");
},
// 删除
handleDelete(row) {
// console.log(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.dialogFormVisibleEdit = 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.dialogFormVisibleEdit = false;
this.$message.success("修改成功");
}else{
this.$message.error("修改失败");
}
}).finally(()=>{
//2.重新加载数据
this.getAll();
});
},
}
})
//取消
cancel(){
this.dialogFormVisible = false;
this.dialogFormVisibleEdit = false;
this.$message.info("当前操作取消");
},
请求方式使用PUT调用后台对应操作
修改操作结束后动态刷新页面加载数据(同新增)
根据操作结果不同,显示对应的提示信息( 同新增)
package com.example.demo_ssm.controller.utils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//SpringMVC的异常处理器
//@ControllerAdvice
@RestControllerAdvice
//比@ControllerAdvice 多了一个@ResponseBody注解
public class ProjectExceptionAdive {
//拦截所有的异常信息
@ExceptionHandler
public R doException(Exception ex) {
//记录日志
//通知运维
//通知开发
ex.printStackTrace();
return new R("服务器故障,请稍后再试");
}
}
使用注解@RestControllerAdvice定义SpringMVC异常处理器用来处理异常的
异常处理器必须被扫描加载,否则无法生效
表现层返回结果的模型类中添加消息属性用来传递消息到页面