目录
=================================================
——————Ctrl+F12 查看当前类的方法——————————
1.案例不同模块的开发以所用技术汇总
实体类开发————使用Lombok快速制作实体类
Dao开发————整合MybatisPius,制作数据层测试类
Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
Controller开发————基于Restful开发,使用PostMan测试接口功能
Controller开发————前后端开发协议制作
页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
列表,新增,修改,删除,分页,查询
项目异常处理
按条件查询————页面功能调整,Controller修正功能,Service修正功能
=================================================
2.模块创建
创建时,勾选web 与SQL连接, 随后手动添加MyBatis_puls与Druid,详见
SptingBoot项目创建与手动添加其他坐标https://blog.csdn.net/qq_45851715/article/details/125300671
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo_ssm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo_ssm</name>
<description>demo_ssm</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<!-- mybatis-plus 坐标-->
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--德鲁伊连接池-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这里为了测试是方便,将端口设为了80
server:
port: 80
3.实体类开发
3.1 创建数据库
3.2 创建对应的实体类 LomBok
Alt+7,查看方法
LomBok,一个Java类库,提供了一-组注解,简化P0J0实体类开发
a>导入坐标
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
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;
}
4.数据层开发
4.1相关配置 配置MP与druid
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_
4.2 创建数据层接口
——————Ctrl+F12 查看当前类的方法——————————
继承自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<Book> {
}
4.3效果测试
4.3.1 查询
@Test
//查询单个
void selectById() {
System.out.println(bookDao.selectById(1));
}
//结果 Book(id=1, type=玄幻, name=斗罗大陆, description=唐三)
4.3.2 添加
直接使用会使报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));
}
4.3.3 修改
@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));
}
4.3.4 删除及查询所有数据
@Test
void dome() {
//删除
bookDao.deleteById(16);
//查询全部数据
//条件构造器为空,这里为null意味没有条件,全部查询出来
bookDao.selectList(null);
}
4.3.5 分页
为了实现分页,首先需要去配置拦截器
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条信息,写的分页,却没有效果
4.3.6 条件查询
1.0
@Test
void tiaojianchaxun(){
//bug type属性值手打,万一写错了完犊子
QueryWrapper<Book> queryWrapper=new QueryWrapper();
queryWrapper.like("type","玄幻");
bookDao.selectList(queryWrapper);
}
2.0
@Test
void tiaojianchaxun1(){
//采用 lambdaQueryWrapper 避免错误
String Type="玄幻";
LambdaQueryWrapper<Book> lambdaQueryWrapper=new LambdaQueryWrapper();
lambdaQueryWrapper.like(Type!=null,Book::getType,Type);
bookDao.selectList(lambdaQueryWrapper);
}
4.4 MP运行日志 开启后可以看到具体的内容
添加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. 业务层开发
5.1 基础CUDA
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<Book> 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<Book> 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功能是否有效
5.2 快速开发,基于MyBatisPlus
接口的编写
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<Book> {
//定义自己的方法
//判断有没有和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<BookDao, Book> 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<T>) 与业务层通用实现类(ServiceImpl<M,T>)
在通用类基础上做功能重载或功能追加
注意重载时不要覆盖原始操作,避免原始提供的功能丢失
6.表现层标准开发
基于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<Book> 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<Book> 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<Book> getPage(@PathVariable int currentPage,@PathVariable int pageSize) {
return iBookService.getPage(currentPage,pageSize);
}
}
设计统--的返回值结果类型便于前端开发读取数据
返回值结果类型可以根据需求自行设定,没有固定格式
返回值结果模型类用于后端与前端进行数据格式统- -,也称为前后端数据协议
7.前后端协议联调
前后端分离结构设计中页面归属前端服务器
单体工程中页面放置在resources目录下的static目录中(建议执行clean)
需要放置文件如下
资源链接地址https://download.csdn.net/download/qq_45851715/85950895
7.1 前端发送异步请求,调用后端接口
单体项目中页面放置在resources/static目录下
created钩子函数用于初始化页面时发起调用
页面使用axios发送异步请求获取数据后确认前后端是否联通
7.2列表功能
将查询数据返回到页面,利用前端数据双向绑定进行数据展示
7.3 添加功能
//弹出添加窗口
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("当前操作取消");
},
7.4 删除
// 删除
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("取消操作");
});
},
7.5弹出编辑窗口
//弹出编辑窗口
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();
});
},
7.6 修改
//修改
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调用后台对应操作
修改操作结束后动态刷新页面加载数据(同新增)
根据操作结果不同,显示对应的提示信息( 同新增)
7.7 异常处理
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异常处理器用来处理异常的
异常处理器必须被扫描加载,否则无法生效
表现层返回结果的模型类中添加消息属性用来传递消息到页面
7.8 分页
7.9 条件查询