# maple **Repository Path**: yaosongyu/maple ## Basic Information - **Project Name**: maple - **Description**: 自己整理的框架集合,好用的功能整理 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-06-05 - **Last Updated**: 2024-06-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # maple ### 介绍 基于微服务架构的综合技术平台,由网关、授权、消息、系统、基础等服务组成,实现了用户多方式登录,用户权限管理,文件多方式上传,视频切片,消息订阅与发送,文档管理等功能。还整理了日常开发过程中遇到的比较好用的工具、方法、设计思路、实现方式等。也包含的自己平时对算法、设计模式、jdk源码、netty、spring、mybatis的练习demo ### 技术栈 涉及的技术栈有`Spring Cloud Alibaba 2020`、`SpringBoot`、`Mybatis-Plus`、`Spring Security`、`WebSocket`、`EasyExcel`、`Netty`等,使用`MySQL`进行数据存储,使用`Redis`进行缓存和分布式锁,文件存储使用`Minio`、`OSS`,使用`Kafka`消息队列进行削峰填谷 ### 服务结构 ``` maple 系统根目录 ├─ maple-cloud 系统框架根目录 │ ├─ maple-cloud-admin 服务管理模块 │ ├─ maple-cloud-api 服务远程接口模块 │ ├─ maple-cloud-core 服务基础模块 │ ├─ maple-cloud-gateway 服务网关模块 │ └─ maple-cloud-web 服务web模块 ├─ maple-common 框架公共模块 │ └─ yvon-core 框架基础依赖模块 ├─ maple-service 微服务父目录 │ ├─ maple-service-auth 授权服务 │ │ ├─ maple-auth-biz 授权服务业务模块 │ │ ├─ maple-auth-controller 授权服务接口模块 │ │ ├─ maple-auth-entity 授权服务实体模块 │ │ └─ maple-auth-server 授权服务启动模块 │ ├─ maple-service-base 基础服务 │ │ ├─ maple-base-biz 基础服务业务模块 │ │ ├─ maple-base-controller 基础服务接口模块 │ │ ├─ maple-base-entity 基础服务实体模块 │ │ └─ maple-base-server 基础服务启动模块 │ ├─ maple-service-demo demo服务(个人练习) │ │ ├─ maple-demo-algorithm demo服务算法模块 │ │ ├─ maple-demo-design demo服务设计模式模块 │ │ ├─ maple-demo-jdk demo服务jdk模块 │ │ ├─ maple-demo-mybatis demo服务mybatis模块 │ │ ├─ maple-demo-netty demo服务netty模块 │ │ └─ maple-demo-spring demo服务spring模块 │ ├─ maple-service-doc 文档服务 │ │ ├─ maple-doc-biz 文档服务业务模块 │ │ ├─ maple-doc-controller 文档服务接口模块 │ │ ├─ maple-doc-entity 文档服务实体模块 │ │ └─ maple-doc-server 文档服务启动模块 │ ├─ maple-service-msg 消息服务 │ │ ├─ maple-msg-core 消息服务核心模块 │ │ ├─ maple-msg-server 消息服务启动模块 │ │ └─ maple-msg-sub 消息服务订阅模块 │ ├─ maple-service-system 系统服务 │ │ ├─ maple-system-biz 系统服务业务模块 │ │ ├─ maple-system-controller 系统服务接口模块 │ │ ├─ maple-system-entity 系统服务实体模块 │ │ └─ maple-system-server 系统服务启动模块 ├─ yvon-boot-starter-parent stater根目录 │ ├─ yvon-boot-apiversion-starter 接口版本 starter │ ├─ yvon-boot-common-starter 通用 starter │ ├─ yvon-boot-dependencies 依赖管理 │ ├─ yvon-boot-excel-starter excel stater │ ├─ yvon-boot-jwt-starter jwt stater │ ├─ yvon-boot-knife4j-starter 接口文档 stater │ ├─ yvon-boot-log-starter 日志 stater │ ├─ yvon-boot-mail-starter 邮件 stater │ ├─ yvon-boot-mybatis-starter mybatis stater │ ├─ yvon-boot-redis-starter redis stater │ └─ yvon-boot-websocket-starter websocket stater └─ yvon-generator 代码生成器模块 ``` ### 功能介绍 #### 依赖关系 ![](https://kulalasmile.oss-cn-hangzhou.aliyuncs.com/202304041437153.jpg) #### * Service层 1. 基于`Mybatis-Plus`封装出`yvon-boot-myabtis-starter`包,包中对`Mybatis-Plus`中的`IService`和`ServiceImpl`的增删查改功能进行封装,并增加了**分页查询**、**列表查询**、**字段唯一性校验** ```java public interface IBaseService extends IService { /** * 分页查询 * * @param pageQuery 分页参数 * @return ListData * @author : Yvon / 2021-09-03 */ ListData page(PageQuery pageQuery); /** * 列表 * * @param baseQuery 基本查询 * @return List */ List list(BaseQuery baseQuery); /** * 检查是否唯一 *

* 新增时不传id,校验范围:全部内容
* 更新时必传id,校验范围:除当前记录为的其他内容 *

* * @param column 需要检验的数据库字段名 * @param value 需要检验的值 * @param id ID * @param message 提示消息 * @author : Yvon / 2021-09-28 */ void checkUniqueness(String column, Object value, Serializable id, String message); } ``` 2. 再对`IBaseService`和`BaseTreeServiceImpl`进行功能封装,增加了对树形数据结构的处理方法 ```java @Transactional(readOnly = false) public interface IBaseTreeService extends IBaseService { /** * 保存更新节点 * * @param entity 实体 * @return boolean */ boolean saveUpdateNode(T entity); /** * 根据父ID查询子节点的 * * @param parentId 父ID * @return */ List findChildListByParentId(Long parentId); /** * 根据树路径查询所有的子节点信息 * @param parentIds * @return */ List findChildListByParentIds(String parentIds); /** * 查询最大编号 * @param parentId * @return */ Integer findMaxSort(Long parentId); } ``` 3. 对分页查询进行封装,通过自定义注解来实现分页查询中的条件过滤和排序 自定义搜索: ```java @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface MpSearch { /** * 别名 * 对于查询语句中字段所在表的别名 * * @return {@code String } */ String alias() default ""; /** * 字段名 * 对于查询语句中字段名称 * * @return {@code String[] } */ String[] fieldName() default {}; /** * 操作 * 对于查询语句中查询条件 * * @return {@code String } */ Operator operate() default Operator.eq; /** * 值 * 对于查询语句中查询条件的值 * * @return {@code String } */ String[] value() default {}; /** * 自动排序,该属性是实现默认字段排序 * * @return {@link MpOrder.Order} */ MpOrder.Order autoOrder() default MpOrder.Order.none; /** * 忽略 * * @return boolean */ boolean ignore() default false; public static enum Operator { eq, ne, gt, ge, lt, le, betweenStart, betweenEnd, notBetweenStart, notBetweenEnd, like, notLike, orLike, likeLeft, likeRight, in, notIn, isNull, isNotNull; private Operator() { } } } ``` 自定义排序: ```java /** * 排序 * 接收前端排序规则,进行排序 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface MpOrder { /** * 别名 * 对于查询语句中字段所在表的别名 * * @return {@code String } */ String alias() default ""; /** * 字段名 * 对于查询语句中字段名称 * * @return {@code String[] } */ String[] fieldName() default {}; MpOrder.Order order() default MpOrder.Order.none; public enum Order { asc, desc, none; Order() { } } } ``` 在前端需要查询的参数中使用注解进行标注,后端会对注解进行解析,根据注解内容进行SQL语句和参数拼接,最终实现快速分页查询: ```java @EqualsAndHashCode(callSuper = true) @Data @NoArgsConstructor @AllArgsConstructor public class UserQuery extends PageQuery { /** * 部门id-精确匹配 */ @MpSearch(alias = "ud") private Long deptId; /** * 昵称-模糊查询 */ @MpSearch(alias = "u", operate = MpSearch.Operator.like) private String nickname; /** * 用户名-精确匹配 */ @MpSearch(alias = "u") private String username; /** * 电话-精确匹配 */ @MpSearch(alias = "u", operate = MpSearch.Operator.like) private String phone; /** * 状态-精确匹配 */ @MpSearch(alias = "u") private Boolean enabled; /** * 创建时间开始-范围查询 */ @MpSearch(fieldName = "u.create_time", operate = MpSearch.Operator.betweenStart) private String createTimeBegin; /** * 创建时间结束-范围查询 */ @MpSearch(fieldName = "u.create_time", operate = MpSearch.Operator.betweenEnd) private String createTimeEnd; /** * 创建时间-顺序 */ @MpOrder(fieldName = "u.create_time") private MpOrder.Order createTimeOrder; } ``` 4. 由于java中的Long类型为19位,前端js只能接收17位的数字,会造成末尾两位为0,所以自定义了ID生成器,将生成的ID设置为16位 * Controller层 1. `ApiController`定义了响应结果的封装 1. `AbstractController`继承与ApiController,定义了数据类型的转换 2. `BaseCrudController`继承与AbstractController,定义了增删查改接口 根据需求继承对应的Controller即可 * POJO层 1. 入参为后端接受前端提交的参数,命名:VO,继承BaseVO,会对更新时实体类的ID进行必填校验 ```java @Data @ApiModel("主体请求参数") public class BaseVO implements Serializable { /** * id */ @ApiModelProperty(value = "id(新增操作可以不传!)") @NotNull(groups = {UpdateGroup.class}, message = "ID不能为空") private Long id; } ``` 2. 出参为响应给前端的实体类,命名:DTO,继承BaseDTO ```java @ApiModel("基础响应参数") @Data public class BaseDTO implements Serializable { /** * id. */ @ApiModelProperty(value = "id") private Long id; /** * 创建时间. */ @ApiModelProperty(value = "创建时间(yyyy-MM-dd HH:mm:ss)") @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) private LocalDateTime createTime; /** * 最后一次更新时间. */ @ApiModelProperty(value = "最后一次更新时间(yyyy-MM-dd HH:mm:ss)") @JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) private LocalDateTime updateTime; } ``` 3. entity为与数据库交互的实体类,命名无要求,继承BaseEntity ```java @Data @NoArgsConstructor @AllArgsConstructor public class BaseEntity implements Serializable { /** * id. */ @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id; /** * 创建时间. */ @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; /** * 更新时间. */ @TableField(fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; /** * 创建人. */ @TableField(fill = FieldFill.INSERT) private Long createUserId; /** * 更新人. */ @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUserId; } ```