码云:
代码地址
创建项目
使用aliyun创建springboot
勾选我们所需开发工具
选择Mybatis plus模板和mysql驱动,如果使用默认创建springboot工程自己在pom.xml中添加即可
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.2version>
dependency>
添加德鲁伊连接池依赖
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.6version>
dependency>
DROP TABLE IF EXISTS `tbl_book`;
CREATE TABLE `tbl_book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 19 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tbl_book
-- ----------------------------
INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Java编程思想(第4版)', 'Java学习经典,殿堂级著作!赢得了全球程序员的广泛赞誉。');
INSERT INTO `tbl_book` VALUES (2, '计算机理论', '计算机组成原理', '资深的计算机体系结构教育家Alan Clements博士编写,涵盖计算机系统的组成和体系结构的基本概念、指令系统以及处理器实现等涉及计算机组成原理课程的内容。');
INSERT INTO `tbl_book` VALUES (3, '程序设计', 'C++ Primer Plus 第6版 中文版', 'C++程序设计经典教程,畅销30年的C++大百科全书全新升级,经典C++入门教程十年新版再现');
INSERT INTO `tbl_book` VALUES (4, '程序设计', 'RocketMQ技术内幕:RocketMQ架构设计与实现原理(第2版)', '畅销书升级,RocketMQ创始人高度评价,深入源码分析技术架构和实现原理,打造高性能、高可用、高吞吐量、低延迟RocketMQ');
INSERT INTO `tbl_book` VALUES (5, '程序设计', ' 深入理解Java虚拟机:JVM高级特性与实践(第3版)', '周志明虚拟机新作,第3版新增内容近50%,5个维度全面剖析JVM,大厂面试知识点全覆盖。与 Java编程思想、Effective Java、Java核心技术 堪称:Java四大名著');
INSERT INTO `tbl_book` VALUES (6, '历史', '见识城邦·人类简史:从动物到上帝(新版)', '以色列新锐历史学家尤瓦尔·赫拉利代表作,第十届文津图书奖获奖作品');
INSERT INTO `tbl_book` VALUES (7, '历史', '中国通史', '吕思勉先生写给普通读者的中国通史入门书,用白话文写成的中国通史,把历史从“帝王的家谱”转变为人类的进化史');
INSERT INTO `tbl_book` VALUES (8, '哲学', '理想国(柏拉图代表作)', '奠定西方哲学史的源流之作。2021新译本,以斯灵斯校勘本为底本,遵照“字对字”的原则,从古希腊原文直译,兼顾准确性和语言通顺性,助你读懂理想国。');
INSERT INTO `tbl_book` VALUES (9, '哲学', '苏格拉底的申辩', '《柏拉图注疏集:苏格拉底的申辩》记述的是公元前399年,一个叫莫勒图斯的年轻人在雅典状告哲学家苏格拉底,说他不信城邦诸神,引进新的精灵之事,败坏青年。 于是,苏格拉底被传讯,在500人组成的陪审团面前作了著名的申辩。');
INSERT INTO `tbl_book` VALUES (10, '文学', '鲁迅全集', '大师全集,完整收录,鲁迅毕生之心血尽归于此。\r\n\r\n 鲁迅是中国20世纪的文学家、思想家、革命家,中国近代文学巨匠。他早年留学于日本,后来弃医从文,他用笔耕不辍的文字为新一代青年们指引方向,在国内外思想文化领域有着极高的声誉。');
INSERT INTO `tbl_book` VALUES (11, '文学', '人间清醒', '茅盾文学奖获得者梁晓声2021全新力作');
INSERT INTO `tbl_book` VALUES (12, '经济', '八次危机:中国的真实经验1949-2009', '著名“三农”专家温铁军,用经济的独特视角,重新审视中国的1949-2009,历史给我了我们怎样的真实经验?');
SET FOREIGN_KEY_CHECKS = 1;
SELECT * FROM tbl_book;
创建实体类Book
@Data注解会帮我们生成geter setter方法和tostring
如果需要空参构造方法和有参构造方法可以使用
@AllArgsConstructor
@NoArgsConstructor(无参)
例如:项目场景:示例:通过蓝牙芯片(HC-05)与手机 APP 通信,每隔 5s 传输一批传感器数据(不是很大)
duid和mybatisplus配置:
数据库连接池信息根据自身填写
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/user_db?serverTimezone=UTC
username: root
password: root
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启MP运行日志信息
创建数据接口BookDao
MybatisPlus提供了快速开发方案 提供了BaseMapper接口指定实体类的泛型
@Mapper
@Component
public interface BookDao extends BaseMapper<Book> {
// @Select("select * from tbl_book where id =#{id}")
// Book getById(Integer id);
}
BaseMapper中已经帮我们定义了很多常用的操作,如果我们有自己需求的操作在接口中自己定义就可以了,只能说一声牛逼
创建分页拦截器
@Configuration
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
如果没有分页拦截器会默认查询所有数据,有了拦截器以后我们可以看到成功查询到前五条数据
测试按条件查询
基于mybatisplus实现CRUD快速开发
MybatisPlus提供有业务层通用接口(ISerivce)与业务层通用实现类(ServiceImpl
创建IBookService接口,如果还有其他业务功能直接添加即可
public interface IBookService extends IService<Book> {
IPage<Book> getPage(int currentPage,int pageSize);
IPage<Book> getPage(int currentPage,int pageSize,Book book);
}
创建实现类
serviceImpl
@Service
public class IBookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
@Autowired
private BookDao bookDao;
@Override
public IPage<Book> getPage(int currentPage, int pageSize) {
Page<Book> page = new Page<>(currentPage, pageSize);
bookDao.selectPage(page,null);
return page;
}
@Override
public IPage<Book> getPage(int currentPage, int pageSize,Book book) {
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
//动态查询
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());
Page<Book> page = new Page<>(currentPage, pageSize);
bookDao.selectPage(page,lqw);
return page;
}
}
提示:这里填写问题的分析:
例如:Handler
发送消息有两种方式,分别是 Handler.obtainMessage()
和 Handler.sendMessage()
,其中 obtainMessage
方式当数据量过大时,由于 MessageQuene
大小也有限,所以当 message
处理不及时时,会造成先传的数据被覆盖,进而导致数据丢失。
提示:这里填写该问题的具体解决方案:
基于Restful进行表现层接口开发
创建BookController
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private IBookService bookService;
@GetMapping
public R getAll(){
return new R(true,bookService.list());
}
@PostMapping
public R save(@RequestBody Book book) throws IOException {
//模拟异常 情况为书名为123的时候
if (book.getName().equals("123"))throw new IOException();
boolean flag = bookService.save(book);
//运用三目运算符,如果运行正常就显示添加成功否则相反
return new R(flag,flag?"添加成功":"添加失败");
}
@PutMapping
public R updatte(@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?"删除成功":"删除失败");
}
@GetMapping("{id}")
public R getById(@PathVariable Integer id){
return new R(true,bookService.getById(id));
}
@GetMapping("{currentPage}/{pageSize}")
public R getPage(@PathVariable int currentPage,@PathVariable int pageSize,Book book){
IPage<Book> page = bookService.getPage(currentPage, pageSize,book);
//解决如果点击删除时候 现在所在页数大于已有页数
if (currentPage>page.getPages()){
page = bookService.getPage((int) page.getPages(), pageSize,book);
}
return new R(true,page);
}
}
使用postman测试表现层接口功能
测试getAll方法
测试getById方法
测试save方法
测试delete方法
表现层数据一致处理(之前存在数据各式各样 数组也有对象加大了前端人员对数据的处理难度)
设计表现层返回结果的模型类,用于后端与前端进行数据格式统一,也称为前后端数据协议
创建模型类R
@Data
public class R {
private Boolean flag;
private Object data;
private String msg;
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;
}
}
前端代码已经放在码云了
实现列表功能
在页面一展现出来的时候就要展出出数据了,在vue里面有一个钩子函数,vue对象初始化完成后自动执行,初始化完成之后自动调用展现数据
getAll() {
// 发送异步请求
axios.get("/books").then(res => {
// console.log(res.data);
this.dataList = res.data.data;
});
},
实现添加功能
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
//每一次打开窗口的时候都会清除数据
this.resetForm();
},
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.dialogFormVisible4Edit = 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(res.data.msg);
} else {
this.$message.error(res.data.msg);
}
}).finally(() => {
this.getAll();
});
}).catch(() => {
//点击取消
this.$message.info("取消操作");
});
},
修改功能
//修改
handleEdit() {
axios.put("/books", this.formData).then(res => {
// 判断当前操作是否成功
if(res.data.flag) {
// 1.关闭弹层
this.dialogFormVisible4Edit = false;
this.$message.success(res.data.msg);
} else {
this.$message.error(res.data.msg);
}
}).finally(() => {
// 2.重新加载数据
this.getAll();
});
},
分页功能
getAll() {
// 组织参数,拼接url请求地址
var paramStr = "?name=" + this.pagination.name
+ "&type=" + this.pagination.type
+ "&description=" + this.pagination.description;
console.log(paramStr);
axios.get("/books/" + this.pagination.currentPage + "/" + this.pagination.pageSize + paramStr).then(res => {
// console.log(res.data);
this.pagination.currentPage = res.data.data.current;
this.pagination.pageSize = res.data.data.size;
this.pagination.total = res.data.data.total;
//data.data.records就是分组完后的数据 是一个集合
this.dataList = res.data.data.records;
});
},
发送异步请求的时候会将我们查询的内容自动封装成javabean对象,我们用book类接收
@Override
public IPage<Book> getPage(int currentPage, int pageSize,Book book) {
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
//动态查询
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());
Page<Book> page = new Page<>(currentPage, pageSize);
bookDao.selectPage(page,lqw);
return page;
}