文章目录
基础的CRUD项目
代码获取:
通过网盘分享的文件:electronicLibraryV1.zip https://pan.baidu.com/s/1yn4YhSAp7LThVc-we3EmRw?pwd=6666 提取码: 6666
项目结构
electroniclibraryv1
├─sql SQL脚本及数据库图形化关系图
└──src
└──main
├─java
│ └─com.chyb.electroniclibraryv1 包
│ ├─common 公共模块
│ │ ├─until 存放一些配置类和过滤器等文件
│ │ │ └─config
│ │ └─web 三层架构中公共的类,以及返回的对象
│ │ ├─Domain
│ │ ├─controller
│ │ └─page 封装的分页返回对象
│ └─基础三层架构
└─resources
└──mapper
目标
- 自动配置、多环境切换、Starter 原理。
- 复习springBoot
基础功能
- 增删改查
步骤
- 导入基础依赖
<!--导入mybatisPlus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Knife4j(增强版Swagger)用于配置springDoc的依赖 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
- 配置mysql、mybatisPlus、springDoc
spring:
application:
name: 'electronicLibraryV1'
#建立连接Mysql数据库的四要素
datasource:
#驱动类名称
driver-class-name: com.mysql.cj.jdbc.Driver
#数据库连接的url
# 注意这里3306后面的mysqlMybatisTest是你创建表的所在的库
url: jdbc:mysql://localhost:3306/electronic_library
#账号密码
username: root
password: 123456
server:
port: 8081
# 配置mybatisPlus
mybatis-plus:
configuration:
# 输出sql语句的日志,效果就是在每次进行执行sql语句时会输出在控制板中
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# springdoc-openapi项目配置
springdoc:
swagger-ui:
path: /swagger-ui.html # Swagger UI 的访问路径(默认即为此值)
tags-sorter: alpha # 按字母顺序对 API 的标签(Tags)进行排序
operations-sorter: alpha # 按字母顺序对每个标签下的接口(Operations)进行排序
api-docs:
path: /v3/api-docs # OpenAPI 规范文档(JSON 格式)的访问路径(默认值)
group-configs:
- group: 'default' # 分组名称(默认分组)
paths-to-match: '/**' # 匹配所有接口路径
packages-to-scan: com.chyb.electroniclibraryv1.controller # 扫描指定包下的控制器类
# knife4j的增强配置,不需要增强可以不配
knife4j:
enable: true # 启用 Knife4j 的增强功能(如离线文档下载、接口调试等)
setting:
language: zh_cn # 将 Knife4j 的界面语言设置为简体中文
- 写三层架构的基本业务(CRUD)
- 测试
写项目时遇到的问题
1.mysql数据库的创建
创建数据库主要还是使用AI,自动帮我生成但是要注意许多的细节问题,列如:命名问题、软删除、索引等
2.mybatisPlus与springBoot整合
常见报错:
依赖问题:要注意springBoot版本和mybatisPlus的版本是否匹配
列如springBoot3官方对应的版本为:<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.11</version> </dependency>
3.springDoc的配置及应用(了解)
springDoc可以快速的将我们开发的API接口进行测试,就不需要使用postman进行一个一个的输入网址测试
配置好后直接访问:http://localhost:8081/doc.html (这里的端口写自己配置的端口)
- springDoc的配置:
# springdoc-openapi项目配置
springdoc:
swagger-ui:
path: /swagger-ui.html # Swagger UI 的访问路径(默认即为此值)
tags-sorter: alpha # 按字母顺序对 API 的标签(Tags)进行排序
operations-sorter: alpha # 按字母顺序对每个标签下的接口(Operations)进行排序
api-docs:
path: /v3/api-docs # OpenAPI 规范文档(JSON 格式)的访问路径(默认值)
group-configs:
- group: 'default' # 分组名称(默认分组)
paths-to-match: '/**' # 匹配所有接口路径
packages-to-scan: com.chyb.libraryManage.controllers # 扫描指定包下的控制器类
# knife4j的增强配置,不需要增强可以不配
knife4j:
enable: true # 启用 Knife4j 的增强功能(如离线文档下载、接口调试等)
setting:
language: zh_cn # 将 Knife4j 的界面语言设置为简体中文
- springDoc的规范(controller)
@RestController
@RequestMapping("body")
@Tag(name = "body参数")
public class BodyController {
@Operation(summary = "普通body请求")
@PostMapping("/body")
public ResponseEntity<FileResp> body(@RequestBody FileResp fileResp){
return ResponseEntity.ok(fileResp);
}
@Operation(summary = "普通body请求+Param+Header+Path")
@Parameters({
@Parameter(name = "id",description = "文件id",in = ParameterIn.PATH),
@Parameter(name = "token",description = "请求token",required = true,in = ParameterIn.HEADER),
@Parameter(name = "name",description = "文件名称",required = true,in=ParameterIn.QUERY)
})
@PostMapping("/bodyParamHeaderPath/{id}")
public ResponseEntity<FileResp> bodyParamHeaderPath(@PathVariable("id") String id,@RequestHeader("token") String token, @RequestParam("name")String name,@RequestBody FileResp fileResp){
fileResp.setName(fileResp.getName()+",receiveName:"+name+",token:"+token+",pathID:"+id);
return ResponseEntity.ok(fileResp);
}
}
4.分页查询
方法一(使用mybatis中提供的分页插件):
1、配置Page分页插件
(注意这里的Page插件是mybatisPlus中内置的)public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
分页配置的作用是:
- 1:增加代码的灵活性,可以个性化的配置分页插件
- 2:应对一些难以适配的特殊环境
- 3:利用后期的维护和理解
2、在Service层中使用分页
@Override public List<BookContent> selectPage(BookContent bookContent) { /*创建Page用于在调用pageList时进行传值*/ Page<BookContent> page = new Page<>(); /*开始进行查询*/ Page<BookContent> tempPage = bookContentMapper.pageList(page, bookContent); /*将返回的类型转换为List*/ List<BookContent> records = tempPage.getRecords(); return records; }
3、Mapper中创建pageList方法
Page<BookContent> pageList(Page<BookContent> page,@Param("bookContent") BookContent bookContent);
4、xml中调用属性的值,并做条件判断
<select id="pageList" resultMap="bookContentResult" parameterType="BookContent"> <include refid="bookContentVO"/> <where> <if test="bookContent.bookId != null">and book_id = #{bookContent.bookId}</if> <if test="bookContent.chapterTitle != null and bookContent.chapterTitle != ''">and chapter_title like concat('%',#{bookContent.chapterTitle},'%')</if> <if test="bookContent.chapterContent != null and bookContent.chapterContent != ''">and chapter_content like concat('%',#{bookContent.chapterContent},'%')</if> </where> </select>
注意:此方法在xml中调用bookContent参数时,需要使用@Param("bookContent“)进行标记一下,在xml调用bookContent.~
方法二(直接使用xml进行编写):
1、xml中编写代码
<select id="selectPageTwo" resultMap="bookContentResult" parameterType="BookContent"> <include refid="bookContentVO"/> <where> <if test="bookId != null">and book_id = #{bookId}</if> <if test="chapterTitle != null and chapterTitle != ''">and chapter_title like concat('%',#{chapterTitle},'%') </if> <if test="chapterContent != null and chapterContent != ''">and chapter_content like concat('%',#{chapterContent},'%') </if> </where> limit #{pageNum},#{pageSize} </select>
这里的Service中直接调用此方法即可,在mapper中传参只需要传输一个bookContent参数(因为这个类中有封装page中所需的属性)
注意:当项目多的时候xml中会很繁琐,因为每当想要使用分页的时候都需要手动的去写sql很不便捷
方法三(仿写若依框架中的分页查询)【推荐】
在若依框架中原理也是使用您的PageHelper这个插件,但是它只需要执行BaseController.startPage方法进行分页,在根据业务进行条件判断即可
!!!这里使用的Page和上面MybatisPlus中内置的Page不一样!!!
1、导入PageHelper及所用到的jsqlparser依赖
<!-- pagehelper 分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!--导入pageHelper所用到的依赖--> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.6</version> <!-- 可根据需要选择合适的版本 --> </dependency>
2、创建一个BaseController用于存放每一个controller中共用的方法例如:分页
import com.chyb.electroniclibraryv1.common.web.Domain.BaseDomain; import com.github.pagehelper.PageHelper; public class BaseController { /** * 普通合理化的分页 */ public static void startPage(BaseDomain bd){ /** count:是否进行 count 查询。 reasonable:启用合理化时,如果pageNum < 1会查询第一页,如果pageNum > 总页数会查询最后一页;禁用合理化时,如果pageNum < 1或pageNum > 总页数会返回空数据。 pageSizeZero:pageSize = 0时是否进行查询,如果为true,当pageSize = 0时会查询全部结果,否则返回空数据。 orderBy:排序字段,格式为 “字段名 1 排序方式 1, 字段名 2 排序方式 2”,例如 “id desc, name asc”。 */ PageHelper.startPage(bd.getPageNum(), bd.getPageSize(), false, true, false); } /** * 加入排序进行分页 */ public static void startPageOrderBy(BaseDomain bd){ /** 这里的orderby参数可以使用BaseDomain中的IsAsc、orderByColumn, 但是要注意传值的方式,使得BaseController中的order参数不会显得那么臃肿, 我这里就直接写成字符串了*/ PageHelper.startPage(bd.getPageNum(), bd.getPageSize(), "create_time desc, update_time desc").setReasonable(true); } }
BaseDomain:
@Data @NoArgsConstructor @AllArgsConstructor public class BaseDomain { /*修改为自增*/ @TableId(type = IdType.AUTO) private Long id; /*标记为软删除*/ @TableLogic(value = "0", delval = "1") private Integer isDeleted; /*设置排序*/ @OrderBy(asc = true, sort = 0) private Date createTime; @OrderBy(asc = true, sort = 1) private Date updateTime; /*分页*/ @TableField(exist = false) private Integer pageSize; @TableField(exist = false) private Integer pageNum; @TableField(exist = false) private Boolean isAsc = true; @TableField(exist = false) private String orderByColumn; }
3、在对应的Controller中继承BaseController并调用startPageByOrder方法
public class BookContentController extends BaseController { @Autowired private IBookContentService bookContentService; /*仿写若依框架的分页*/ @PostMapping("/ryPage") @Operation(summary = "仿写若依框架的分页") public TableDataInfo ryPage(@RequestBody BookContent bookContent) { startPageOrderBy(bookContent); return TableDataInfo.getPageInfo(bookContentService.ryPage(bookContent)); } }
后面就和正常的调用查询一样,查完之后返回的值创建一个对象进行接受如TableDataInfo
这里只是简单的去仿写达到了此效果若是想了解一下源码的话可以去 若依官网
若是还是看不太懂的话推荐去看一下这一篇文章:《分析若依的分页实现逻辑》,个人觉得写的挺细节的