基础CRUD后端项目(使用MybatisPlus、springBoot3)


基础的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

基础功能

  • 增删改查

步骤

  1. 导入基础依赖
<!--导入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>
  1. 配置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 的界面语言设置为简体中文
  1. 写三层架构的基本业务(CRUD)
  2. 测试

写项目时遇到的问题

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

这里只是简单的去仿写达到了此效果若是想了解一下源码的话可以去 若依官网

若是还是看不太懂的话推荐去看一下这一篇文章:《分析若依的分页实现逻辑》,个人觉得写的挺细节的

### 代码生成器的系统架构设计 在基于 MyBatis Plus、Spring Boot、MySQL、MinIO 及微服务架构的 Web 端代码生成器中,系统采用前后端分离与模块化设计。前端基于 Vue3 构建可视化界面,用户通过拖拽组件配置页面结构和业务逻辑[^1];后端则利用 Spring Boot 提供 RESTful API 支持,并结合 MyBatis Plus 实现数据库操作的自动封装与优化[^2]。整个系统被拆分为多个微服务模块,例如用户管理、权限控制、文件上传(MinIO)等,每个模块独立部署并通过网关统一对外提供服务。 ### 数据模型定义与 ORM 映射机制 数据模型是代码生成器的核心输入之一。用户通过平台的数据建模工具定义实体类及其字段类型、关联关系等信息,系统将这些元数据转换为数据库表结构及对应的 Java 实体类[^3]。MyBatis Plus 在此过程中负责处理实体类与数据库之间的映射关系,并自动生成 CRUD 操作接口及动态 SQL 文件。例如,一个名为 `User` 的实体类会对应生成如下代码: ```java // 自动生成的 User 实体类 @Data @TableName("user") public class User { @TableId(type = IdType.AUTO) private Long id; private String name; private String email; } ``` ```java // 自动创建的 Mapper 接口 public interface UserMapper extends BaseMapper<User> { } ``` 上述代码由平台解析数据模型并调用模板引擎生成,确保数据库结构与 Java 类型的一致性[^4]。 ### 代码生成引擎的工作原理 代码生成引擎基于模板驱动的方式实现,其核心流程包括:读取用户配置的元数据、解析模板规则、执行代码渲染。平台内置多种代码模板,涵盖 Controller、Service、Mapper、Vue 组件等多个层级[^5]。以 Vue 前端为例,用户在设计器中选择“用户管理”模块并设置字段后,系统会根据预设的 Vue3 模板生成如下组件: ```vue <template> <div class="user-form"> <el-form :model="formData" label-width="120px"> <el-form-item label="姓名"> <el-input v-model="formData.name" /> </el-form-item> <el-form-item label="邮箱"> <el-input v-model="formData.email" /> </el-form-item> <el-button @click="submit">提交</el-button> </el-form> </div> </template> <script setup> import { ref } from &#39;vue&#39;; import axios from &#39;axios&#39;; const formData = ref({ name: &#39;&#39;, email: &#39;&#39; }); const submit = async () => { const response = await axios.post(&#39;/api/user&#39;, formData.value); console.log(&#39;提交结果:&#39;, response.data); }; </script> ``` 该组件由平台根据用户配置的字段信息自动拼接而成,支持响应式编程和 Composition API 特性[^6]。 ### 微服务架构下的代码集成策略 在微服务架构中,代码生成器需支持模块化输出和跨服务集成。每个生成的服务模块应具备独立运行能力,并通过服务注册中心(如 Nacos、Eureka)进行发现与通信。例如,用户管理模块生成的 Spring Boot 工程包含以下结构: - `UserController.java`:REST 控制器,接收 HTTP 请求并调用业务层 - `UserService.java`:业务逻辑接口及实现类 - `UserMapper.java`:MyBatis Plus 映射接口 - `application.yml`:配置文件,指定数据库连接、服务注册地址等 微服务之间通过 Feign 或 RestTemplate 进行远程调用,例如文件上传服务可由 MinIO 驱动,其接口定义如下: ```java // MinIO 文件上传接口 @RestController @RequestMapping("/file") public class FileUploadController { @PostMapping("/upload") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) { // 调用 MinIO SDK 上传文件 String url = minioService.upload(file); return ResponseEntity.ok(url); } } ``` 该接口由代码生成器依据平台提供的模板自动创建,确保各模块间职责清晰且易于维护[^7]。 ### Vue3 前端与后端服务的集成方案 Vue3 前端通过 Axios 或 Fetch API 与后端微服务进行交互。平台在生成前端代码时,会自动注入 API 地址配置,并使用环境变量区分不同部署阶段(开发、测试、生产)。例如,在 `.env` 文件中定义: ``` VUE_APP_API_URL=http://localhost:8080/api ``` 前端组件通过 `process.env.VUE_APP_API_URL` 获取服务地址,并在请求时动态拼接路径[^8]。此外,平台还支持 Token 认证机制,前端在每次请求时携带 JWT 令牌,由网关统一验证权限[^9]。 ### 代码生成器的扩展性与二次开发能力 为满足复杂业务需求,代码生成器需具备良好的扩展性。平台允许开发者在生成的代码基础上进行二次开发,包括但不限于自定义校验规则、添加拦截器、修改数据库事务行为等。例如,可以在 `UserController` 中添加日志记录功能: ```java @PostMapping public ResponseEntity<?> createUser(@RequestBody User user) { logger.info("收到创建用户请求: {}", user.getName()); userService.save(user); return ResponseEntity.status(HttpStatus.CREATED).build(); } ``` 此外,平台提供插件机制,支持第三方开发者贡献新的代码模板或 UI 组件,从而增强系统的灵活性和适应性[^10]。 ### 总结与展望 基于 MyBatis Plus + Spring Boot + MySQL + MinIO + 微服务架构的 Web 端代码生成器实现了从数据建模到代码输出的全流程自动化,显著提升了开发效率并降低了编码错误率。Vue3 前端的响应式特性和模块化结构进一步增强了用户体验和系统可维护性。未来,随着 AI 技术的发展,代码生成器有望引入智能推荐、自然语言理解等能力,使低代码开发更趋近于零代码目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值