From 6adac3aeb159d10dbdd6b3798a8874a9c209ffde Mon Sep 17 00:00:00 2001 From: ailanyin Date: Wed, 26 Apr 2023 19:48:44 +0800 Subject: [PATCH] first commit --- .gitignore | 47 +++ pom.xml | 178 +++++++++ qiaoba-apis/pom.xml | 37 ++ qiaoba-apis/qiaoba-api-job/pom.xml | 15 + .../qiaoba-api-job/src/main/java/.gitkeep | 1 + .../src/main/resources/.gitkeep | 1 + .../qiaoba-api-job/src/test/java/.gitkeep | 1 + qiaoba-apis/qiaoba-api-system/pom.xml | 15 + .../qiaoba/api/system/entity/SysTenant.java | 45 +++ .../system/entity/SysTenantDatasource.java | 44 +++ .../com/qiaoba/api/system/entity/SysUser.java | 65 ++++ .../api/system/entity/param/SysUserParam.java | 24 ++ .../system/service/SysTenantApiService.java | 29 ++ .../api/system/service/SysUserApiService.java | 29 ++ .../src/main/resources/.gitkeep | 1 + .../qiaoba-api-system/src/test/java/.gitkeep | 1 + qiaoba-application/pom.xml | 31 ++ .../qiaoba/application/QiaoBaApplication.java | 26 ++ .../application/config/GlobalCorsConfig.java | 37 ++ .../src/main/resources/application-dev.yml | 11 + .../src/main/resources/application.yml | 40 ++ qiaoba-application/src/test/java/.gitkeep | 1 + qiaoba-commons/pom.xml | 23 ++ qiaoba-commons/qiaoba-common-base/pom.xml | 15 + .../common/base/constants/BaseConstant.java | 21 ++ .../qiaoba/common/base/entity/BaseEntity.java | 53 +++ .../qiaoba/common/base/enums/BaseEnum.java | 31 ++ .../base/exceptions/ServiceException.java | 47 +++ .../src/main/resources/.gitkeep | 1 + .../qiaoba-common-datasource/pom.xml | 36 ++ .../config/DynamicDataSourceConfig.java | 83 ++++ .../config/DynamicDataSourceContext.java | 62 +++ .../database/entity/DynamicDataSource.java | 46 +++ .../factories/DynamicDataSourceFactory.java | 33 ++ .../database/filters/HandleTenantFilter.java | 36 ++ .../database/mapper/BaseMapperPlus.java | 306 +++++++++++++++ .../main/resources/META-INF/spring.factories | 5 + qiaoba-commons/qiaoba-common-doc/pom.xml | 24 ++ .../qiaoba-common-doc/src/main/java/.gitkeep | 1 + .../src/main/resources/.gitkeep | 1 + qiaoba-commons/qiaoba-common-redis/pom.xml | 26 ++ .../common/redis/config/RedisConfig.java | 71 ++++ .../common/redis/constants/CacheConstant.java | 51 +++ .../common/redis/service/RedisService.java | 357 ++++++++++++++++++ .../redis/service/impl/RedisServiceImpl.java | 224 +++++++++++ .../main/resources/META-INF/spring.factories | 5 + qiaoba-commons/qiaoba-common-web/pom.xml | 24 ++ .../qiaoba/common/web/utils/BeanCopyUtil.java | 227 +++++++++++ .../src/main/resources/.gitkeep | 1 + qiaoba-modules/pom.xml | 20 + qiaoba-modules/qiaoba-module-job/pom.xml | 15 + .../qiaoba-module-job/src/main/java/.gitkeep | 1 + .../src/main/resources/.gitkeep | 1 + .../qiaoba-module-job/src/test/java/.gitkeep | 1 + qiaoba-modules/qiaoba-module-system/pom.xml | 20 + .../system/controller/SysUserController.java | 49 +++ .../module/system/mapper/SysTenantMapper.java | 14 + .../module/system/mapper/SysUserMapper.java | 14 + .../system/service/SysTenantService.java | 13 + .../module/system/service/SysUserService.java | 25 ++ .../service/impl/SysTenantServiceImpl.java | 32 ++ .../service/impl/SysUserServiceImpl.java | 47 +++ 62 files changed, 2741 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 qiaoba-apis/pom.xml create mode 100644 qiaoba-apis/qiaoba-api-job/pom.xml create mode 100644 qiaoba-apis/qiaoba-api-job/src/main/java/.gitkeep create mode 100644 qiaoba-apis/qiaoba-api-job/src/main/resources/.gitkeep create mode 100644 qiaoba-apis/qiaoba-api-job/src/test/java/.gitkeep create mode 100644 qiaoba-apis/qiaoba-api-system/pom.xml create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenant.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenantDatasource.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysUser.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/param/SysUserParam.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysTenantApiService.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserApiService.java create mode 100644 qiaoba-apis/qiaoba-api-system/src/main/resources/.gitkeep create mode 100644 qiaoba-apis/qiaoba-api-system/src/test/java/.gitkeep create mode 100644 qiaoba-application/pom.xml create mode 100644 qiaoba-application/src/main/java/com/qiaoba/application/QiaoBaApplication.java create mode 100644 qiaoba-application/src/main/java/com/qiaoba/application/config/GlobalCorsConfig.java create mode 100644 qiaoba-application/src/main/resources/application-dev.yml create mode 100644 qiaoba-application/src/main/resources/application.yml create mode 100644 qiaoba-application/src/test/java/.gitkeep create mode 100644 qiaoba-commons/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-base/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/entity/BaseEntity.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/enums/BaseEnum.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/exceptions/ServiceException.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/resources/.gitkeep create mode 100644 qiaoba-commons/qiaoba-common-datasource/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/entity/DynamicDataSource.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/factories/DynamicDataSourceFactory.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/filters/HandleTenantFilter.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/mapper/BaseMapperPlus.java create mode 100644 qiaoba-commons/qiaoba-common-datasource/src/main/resources/META-INF/spring.factories create mode 100644 qiaoba-commons/qiaoba-common-doc/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-doc/src/main/java/.gitkeep create mode 100644 qiaoba-commons/qiaoba-common-doc/src/main/resources/.gitkeep create mode 100644 qiaoba-commons/qiaoba-common-redis/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/config/RedisConfig.java create mode 100644 qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/constants/CacheConstant.java create mode 100644 qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java create mode 100644 qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java create mode 100644 qiaoba-commons/qiaoba-common-redis/src/main/resources/META-INF/spring.factories create mode 100644 qiaoba-commons/qiaoba-common-web/pom.xml create mode 100644 qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/BeanCopyUtil.java create mode 100644 qiaoba-commons/qiaoba-common-web/src/main/resources/.gitkeep create mode 100644 qiaoba-modules/pom.xml create mode 100644 qiaoba-modules/qiaoba-module-job/pom.xml create mode 100644 qiaoba-modules/qiaoba-module-job/src/main/java/.gitkeep create mode 100644 qiaoba-modules/qiaoba-module-job/src/main/resources/.gitkeep create mode 100644 qiaoba-modules/qiaoba-module-job/src/test/java/.gitkeep create mode 100644 qiaoba-modules/qiaoba-module-system/pom.xml create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysUserController.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysTenantMapper.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysUserMapper.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysTenantService.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysUserService.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysTenantServiceImpl.java create mode 100644 qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserServiceImpl.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c0da3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +###################################################################### +# Build Tools + +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +target/ +!.mvn/wrapper/maven-wrapper.jar + +###################################################################### +# IDE + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### JRebel ### +rebel.xml + +### NetBeans ### +nbproject/private/ +build/* +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +###################################################################### +# Others +*.log +*.xml.versionsBackup +*.swp + +!*/build/*.java +!*/build/*.html +!*/build/*.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..497c0bf --- /dev/null +++ b/pom.xml @@ -0,0 +1,178 @@ + + + 4.0.0 + + com.qiaoba + qiaoba-boot + pom + 1.0 + + qiaoba-modules + qiaoba-apis + qiaoba-commons + qiaoba-application + + + + org.springframework.boot + spring-boot-starter-parent + 2.7.11 + + + + + + + UTF-8 + + UTF-8 + + 8 + + true + + 1.0 + + 1.2.17 + + 5.8.18 + + 8.0.33 + + 3.5.3.1 + + 4.0.0 + + 1.6.14 + + 3.0.2 + + + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + com.github.xiaoymin + knife4j-openapi3-spring-boot-starter + ${knife4j.version} + + + + org.springdoc + springdoc-openapi-ui + ${springdoc.version} + + + + mysql + mysql-connector-java + ${mysql-connector.version} + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatisplus-spring-boot.version} + + + + jakarta.validation + jakarta.validation-api + ${jakarta.version} + + + + + com.qiaoba + qiaoba-common-base + ${qiaoba.version} + + + com.qiaoba + qiaoba-common-datasource + ${qiaoba.version} + + + com.qiaoba + qiaoba-common-web + ${qiaoba.version} + + + com.qiaoba + qiaoba-api-system + ${qiaoba.version} + + + com.qiaoba + qiaoba-module-system + ${qiaoba.version} + + + com.qiaoba + qiaoba-common-doc + ${qiaoba.version} + + + + + + + + + org.projectlombok + lombok + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + + public + 阿里云 + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + + + + public + 阿里云 + http://maven.aliyun.com/nexus/content/groups/public/ + + true + + + false + + + + + \ No newline at end of file diff --git a/qiaoba-apis/pom.xml b/qiaoba-apis/pom.xml new file mode 100644 index 0000000..dfff4a8 --- /dev/null +++ b/qiaoba-apis/pom.xml @@ -0,0 +1,37 @@ + + + + qiaoba-boot + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-apis + pom + + qiaoba-api-system + qiaoba-api-job + + + + + com.qiaoba + qiaoba-common-base + + + com.qiaoba + qiaoba-common-datasource + + + com.qiaoba + qiaoba-common-doc + + + jakarta.validation + jakarta.validation-api + + + \ No newline at end of file diff --git a/qiaoba-apis/qiaoba-api-job/pom.xml b/qiaoba-apis/qiaoba-api-job/pom.xml new file mode 100644 index 0000000..7df87c5 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-job/pom.xml @@ -0,0 +1,15 @@ + + + + qiaoba-apis + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-api-job + + + \ No newline at end of file diff --git a/qiaoba-apis/qiaoba-api-job/src/main/java/.gitkeep b/qiaoba-apis/qiaoba-api-job/src/main/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-job/src/main/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-apis/qiaoba-api-job/src/main/resources/.gitkeep b/qiaoba-apis/qiaoba-api-job/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-job/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-apis/qiaoba-api-job/src/test/java/.gitkeep b/qiaoba-apis/qiaoba-api-job/src/test/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-job/src/test/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-apis/qiaoba-api-system/pom.xml b/qiaoba-apis/qiaoba-api-system/pom.xml new file mode 100644 index 0000000..869c790 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/pom.xml @@ -0,0 +1,15 @@ + + + + qiaoba-apis + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-api-system + + + \ No newline at end of file diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenant.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenant.java new file mode 100644 index 0000000..0b3b982 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenant.java @@ -0,0 +1,45 @@ +package com.qiaoba.api.system.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.qiaoba.common.base.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * 租户表 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 22:02:43 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_tenant") +public class SysTenant extends BaseEntity { + + private static final long serialVersionUID = 1L; + + private Long id; + + private String code; + + private String name; + + private String domainName; + + private Date expiryDate; + + private String contact; + + private String province; + + private String city; + + private String district; + + private String address; + + private String status; +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenantDatasource.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenantDatasource.java new file mode 100644 index 0000000..2aaae5b --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysTenantDatasource.java @@ -0,0 +1,44 @@ +package com.qiaoba.api.system.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 租户数据库表 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 22:07:57 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_tenant_datasource") +public class SysTenantDatasource { + + @NotBlank(message = "【租户码】不能为空") + private String tenantCode; + + @NotBlank(message = "【数据库类型】不能为空") + private String datasourceType; + + @NotBlank(message = "【数据库URL】不能为空") + private String datasourceUrl; + + @NotBlank(message = "【数据库IP】不能为空") + private String datasourceIp; + + @NotBlank(message = "【数据库端口】不能为空") + private String datasourcePort; + + @NotBlank(message = "【数据库用户名】不能为空") + private String datasourceUsername; + + @NotBlank(message = "【数据库密码】不能为空") + private String datasourcePassword; + + @NotBlank(message = "【数据库驱动】不能为空") + private String datasourceDriver; + +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysUser.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysUser.java new file mode 100644 index 0000000..9a27af2 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/SysUser.java @@ -0,0 +1,65 @@ +package com.qiaoba.api.system.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.qiaoba.common.base.entity.BaseEntity; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户表 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:37:43 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("sys_user") +public class SysUser extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "部门ID") + private Long deptId; + + @Schema(description = "登陆账号") + private String username; + + @Schema(description = "昵称") + private String nickname; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "手机号") + private String phone; + + @Schema(description = "性别(0男 1女 2未知)") + private String gender; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "密码") + private String password; + + @Schema(description = "帐号状态(1正常 0停用)") + private String status; + + @Schema(description = "是否是超管") + private Boolean isSuperuser; + + @Schema(description = "是否是管理员") + private Boolean isManager; + + @Schema(description = "是否已删除") + private Boolean isDelete; + + +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/param/SysUserParam.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/param/SysUserParam.java new file mode 100644 index 0000000..4cf14f2 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/entity/param/SysUserParam.java @@ -0,0 +1,24 @@ +package com.qiaoba.api.system.entity.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + * 用户查询参数 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:37:43 + */ +@Getter +@Setter +public class SysUserParam implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "昵称") + private String nickname; +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysTenantApiService.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysTenantApiService.java new file mode 100644 index 0000000..ba9a0ad --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysTenantApiService.java @@ -0,0 +1,29 @@ +package com.qiaoba.api.system.service; + +import com.qiaoba.api.system.entity.SysTenant; + +/** + * 租户对外暴露接口 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-24 19:20:40 + */ +public interface SysTenantApiService { + + /** + * 新增租户 + * + * @param sysTenant sysTenant + * @return > 0 = success + */ + int insert(SysTenant sysTenant); + + /** + * 更新租户 + * + * @param sysTenant sysTenant + * @return > 0 = success + */ + int update(SysTenant sysTenant); +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserApiService.java b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserApiService.java new file mode 100644 index 0000000..92928fd --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/java/com/qiaoba/api/system/service/SysUserApiService.java @@ -0,0 +1,29 @@ +package com.qiaoba.api.system.service; + +import com.qiaoba.api.system.entity.SysUser; + +/** + * 用户对外暴露接口 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 20:33:43 + */ +public interface SysUserApiService { + + /** + * 新增用户 + * + * @param sysUser sysUser + * @return > 0 = success + */ + int insert(SysUser sysUser); + + /** + * 更新租户 + * + * @param sysUser sysUser + * @return > 0 = success + */ + int update(SysUser sysUser); +} diff --git a/qiaoba-apis/qiaoba-api-system/src/main/resources/.gitkeep b/qiaoba-apis/qiaoba-api-system/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-apis/qiaoba-api-system/src/test/java/.gitkeep b/qiaoba-apis/qiaoba-api-system/src/test/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-apis/qiaoba-api-system/src/test/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-application/pom.xml b/qiaoba-application/pom.xml new file mode 100644 index 0000000..6e7c9b3 --- /dev/null +++ b/qiaoba-application/pom.xml @@ -0,0 +1,31 @@ + + + + qiaoba-boot + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-application + + + + com.qiaoba + qiaoba-module-system + + + + + + qiaoba-boot + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/qiaoba-application/src/main/java/com/qiaoba/application/QiaoBaApplication.java b/qiaoba-application/src/main/java/com/qiaoba/application/QiaoBaApplication.java new file mode 100644 index 0000000..89f8d30 --- /dev/null +++ b/qiaoba-application/src/main/java/com/qiaoba/application/QiaoBaApplication.java @@ -0,0 +1,26 @@ +package com.qiaoba.application; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * 启动类 + * + * @author ailanyin + * @version 1.0 + * @date 1/29/23 10:44 AM + */ +@EnableScheduling +@ComponentScan({"com.qiaoba.module.**", "com.qiaoba.application"}) +@MapperScan("com.qiaoba.module.**.mapper") +@SpringBootApplication +public class QiaoBaApplication { + public static void main(String[] args) { + SpringApplication.run(QiaoBaApplication.class, args); + } + +} diff --git a/qiaoba-application/src/main/java/com/qiaoba/application/config/GlobalCorsConfig.java b/qiaoba-application/src/main/java/com/qiaoba/application/config/GlobalCorsConfig.java new file mode 100644 index 0000000..614df3d --- /dev/null +++ b/qiaoba-application/src/main/java/com/qiaoba/application/config/GlobalCorsConfig.java @@ -0,0 +1,37 @@ +package com.qiaoba.application.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * 全局跨域配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@Configuration +public class GlobalCorsConfig { + + @Bean + public CorsFilter corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 有效期 半小时 + config.setMaxAge(1800L); + // 添加映射路径,拦截一切请求 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**" , config); + // 返回新的CorsFilter + return new CorsFilter(source); + } +} diff --git a/qiaoba-application/src/main/resources/application-dev.yml b/qiaoba-application/src/main/resources/application-dev.yml new file mode 100644 index 0000000..7495cd5 --- /dev/null +++ b/qiaoba-application/src/main/resources/application-dev.yml @@ -0,0 +1,11 @@ +spring: + datasource: + url: jdbc:mysql://121.5.136.69:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true + username: root + password: LpYN7LUoL?l0OSpR2 + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 5 #连接池初始化大小 + min-idle: 10 #最小空闲连接数 + max-active: 20 #最大连接数 + diff --git a/qiaoba-application/src/main/resources/application.yml b/qiaoba-application/src/main/resources/application.yml new file mode 100644 index 0000000..6eec581 --- /dev/null +++ b/qiaoba-application/src/main/resources/application.yml @@ -0,0 +1,40 @@ +server: + port: 80 +spring: + application: + name: qiaoba-boot + profiles: + active: dev + servlet: + multipart: + enabled: true #开启文件上传 + max-file-size: 200MB #限制文件上传大小为10M + max-request-size: 200MB #限制文件上传大小为10M + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + main: + allow-bean-definition-overriding: true + + +# springdoc-openapi项目配置 +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + api-docs: + path: /v3/api-docs + group-configs: + - group: '系统管理' + paths-to-match: '/**' + packages-to-scan: com.qiaoba.module.system.controller +# knife4j的增强配置,不需要增强可以不配 +knife4j: + enable: true + setting: + language: zh_cn + enable-swagger-models: false + enable-footer-custom: true + footer-custom-content: create by ailanyin + diff --git a/qiaoba-application/src/test/java/.gitkeep b/qiaoba-application/src/test/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-application/src/test/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-commons/pom.xml b/qiaoba-commons/pom.xml new file mode 100644 index 0000000..aea1807 --- /dev/null +++ b/qiaoba-commons/pom.xml @@ -0,0 +1,23 @@ + + + + qiaoba-boot + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-commons + pom + + qiaoba-common-base + qiaoba-common-datasource + qiaoba-common-web + qiaoba-common-doc + qiaoba-common-redis + + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-base/pom.xml b/qiaoba-commons/qiaoba-common-base/pom.xml new file mode 100644 index 0000000..230e3cc --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/pom.xml @@ -0,0 +1,15 @@ + + + + qiaoba-commons + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-common-base + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java new file mode 100644 index 0000000..3ee02f2 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/constants/BaseConstant.java @@ -0,0 +1,21 @@ +package com.qiaoba.common.base.constants; + +/** + * BaseConstant + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:37:43 + */ +public class BaseConstant { + + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * 默认的字符拼接/切割符号: ','(英文逗号) + */ + public static final String DEFAULT_SPLIT_STR = ","; +} diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/entity/BaseEntity.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/entity/BaseEntity.java new file mode 100644 index 0000000..790209c --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/entity/BaseEntity.java @@ -0,0 +1,53 @@ +package com.qiaoba.common.base.entity; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.Date; + + +/** + * BaseEntity + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:37:43 + */ +@Getter +@Setter +public class BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 创建者 + */ + private String createUser; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新者 + */ + private String updateUser; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 备注 + */ + private String remark; + + /** + * 租户Id + */ + private Long tenantId; + +} diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/enums/BaseEnum.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/enums/BaseEnum.java new file mode 100644 index 0000000..14b9d91 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/enums/BaseEnum.java @@ -0,0 +1,31 @@ +package com.qiaoba.common.base.enums; + +import lombok.Getter; + +/** + * BaseEnum + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:34:59 + */ +@Getter +public enum BaseEnum { + + // 是 + YES("1" , "是"), + // 否 + NO("0" , "否"), + // 正常 + NORMAL("1" , "正常"), + // 不正常 + ABNORMAL("0" , "不正常"); + + private final String code; + private final String info; + + BaseEnum(String code, String info) { + this.code = code; + this.info = info; + } +} diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/exceptions/ServiceException.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/exceptions/ServiceException.java new file mode 100644 index 0000000..9b30134 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/exceptions/ServiceException.java @@ -0,0 +1,47 @@ +package com.qiaoba.common.base.exceptions; + + +import lombok.Getter; +import lombok.Setter; + +/** + * 自定义 业务异常 + * + * @author ailanyin + * @version 1.0 + * @since 2021-08-31 + */ +@Getter +@Setter +public class ServiceException extends RuntimeException { + + /** + * 错误码 + */ + private Integer errorCode; + + /** + * 错误信息 + */ + private String message; + + public ServiceException(String message) { + this.message = message; + } + + public ServiceException(Integer code, String message) { + this.message = message; + this.errorCode = code; + } + + /** + * 控制台不打印自定义错误的堆栈信息, 提高性能 + * + * @return this + */ + @Override + public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/qiaoba-commons/qiaoba-common-base/src/main/resources/.gitkeep b/qiaoba-commons/qiaoba-common-base/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-commons/qiaoba-common-datasource/pom.xml b/qiaoba-commons/qiaoba-common-datasource/pom.xml new file mode 100644 index 0000000..bdce586 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/pom.xml @@ -0,0 +1,36 @@ + + + + qiaoba-commons + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-common-datasource + + + + + com.alibaba + druid-spring-boot-starter + + + + mysql + mysql-connector-java + + + + com.baomidou + mybatis-plus-boot-starter + + + com.qiaoba + qiaoba-common-web + + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java new file mode 100644 index 0000000..07cb818 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceConfig.java @@ -0,0 +1,83 @@ +package com.qiaoba.common.database.config; + +import com.alibaba.druid.pool.DruidDataSource; +import com.qiaoba.common.database.entity.DynamicDataSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +/** + * 全局跨域配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +@Configuration +public class DynamicDataSourceConfig { + /** + * 把DynamicDataSourceContext 纳入容器管理,其他地方使用DynamicDataSourceConfig 类可以直接从容器取对象,并调用freshDataSource方法 + */ + @Bean + @Primary + public static DynamicDataSourceContext dataSource() { + Map targetDataSource = getDataSource(); + //把DynamicDataSourceContext纳入容器管理 + DynamicDataSourceContext dynamicDataSourceContext = new DynamicDataSourceContext(); + dynamicDataSourceContext.freshDataSource(targetDataSource); + return dynamicDataSourceContext; + } + + /** + * 构建初始化数据源 TODO 生成中去其他地方获取初始化数据源(例如:表里面获取) + * + * @return + */ + public static Map getDataSource() { + + DynamicDataSource ds2 = new DynamicDataSource(); + ds2.setTenantCode("1"); + ds2.setDriver("com.mysql.cj.jdbc.Driver"); + ds2.setUrl("jdbc:mysql://121.5.136.69:3306/qiaoba-boot?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai"); + ds2.setUsername("root"); + ds2.setPassword("LpYN7LUoL?l0OSpR2"); + + DynamicDataSource ds1 = new DynamicDataSource(); + ds1.setTenantCode("2"); + ds1.setDriver("com.mysql.cj.jdbc.Driver"); + ds1.setUrl("jdbc:mysql://120.79.217.22:3306/qiaoba-boot?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai"); + ds1.setUsername("root"); + ds1.setPassword("FeyZ7xZr6JtuKibm"); + Map map = new HashMap<>(); + map.put(ds1.getTenantCode(), buildDataSource(ds1)); + map.put(ds2.getTenantCode(), buildDataSource(ds2)); + return map; + } + + /** + * 把数据源对象组装成HikariDataSource + * + * @param DynamicDataSource + * @return + */ + private static Object buildDataSource(DynamicDataSource DynamicDataSource) { + DruidDataSource dataSource = new DruidDataSource(); + dataSource.setUrl(DynamicDataSource.getUrl()); + dataSource.setUsername(DynamicDataSource.getUsername()); + dataSource.setPassword(DynamicDataSource.getPassword()); + dataSource.setDriverClassName(DynamicDataSource.getDriver()); + dataSource.setInitialSize(5); + dataSource.setMinIdle(10); + dataSource.setMaxActive(20); + try { + dataSource.init(); + } catch (SQLException e) { + e.printStackTrace(); + } + return dataSource; + } +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java new file mode 100644 index 0000000..4b23285 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/config/DynamicDataSourceContext.java @@ -0,0 +1,62 @@ +package com.qiaoba.common.database.config; + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +import java.util.Map; + +/** + * 动态数据源上下文对象 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/15 0015 下午 16:43 + */ +public class DynamicDataSourceContext extends AbstractRoutingDataSource { + + + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * 设置默认数据源、全部数据源,及刷新 + */ + public void freshDataSource(Map targetDataSources) { + //默认数据源 + super.setDefaultTargetDataSource(targetDataSources.get("master")); + //设置全部数据源 + super.setTargetDataSources(targetDataSources); + //刷新(即把targetDataSources刷到resolvedDataSources中去,resolvedDataSources才是我们真正存放数据源的map) + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() { + //获取当前指定的数据源 + return getDataSource(); + } + + + @Override + public void afterPropertiesSet() { + } + + /** + * 获取上下文中的数据源 + */ + public String getDataSource() { + return CONTEXT_HOLDER.get(); + } + + /** + * 设置上下文中的数据源 + */ + public void setDataSource(String dataSource) { + CONTEXT_HOLDER.set(dataSource); + } + + /** + * 清除上下文中的数据源 + */ + public void clearDataSource() { + CONTEXT_HOLDER.remove(); + } +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/entity/DynamicDataSource.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/entity/DynamicDataSource.java new file mode 100644 index 0000000..e9e971b --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/entity/DynamicDataSource.java @@ -0,0 +1,46 @@ +package com.qiaoba.common.database.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 动态数据源实体 + * + * @author ailanyin + * @version 1.0 + * @date 2023-04-24 21:47:48 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DynamicDataSource { + + /** + * 租户Code + */ + private String tenantCode; + + /** + * 数据库-url + */ + private String url; + + /** + * 数据库-username + */ + private String username; + + /** + * 数据库-password + */ + private String password; + + /** + * 数据库-驱动 + */ + private String driver; + +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/factories/DynamicDataSourceFactory.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/factories/DynamicDataSourceFactory.java new file mode 100644 index 0000000..450560a --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/factories/DynamicDataSourceFactory.java @@ -0,0 +1,33 @@ +package com.qiaoba.common.database.factories; + +import com.qiaoba.common.database.config.DynamicDataSourceConfig; +import com.qiaoba.common.database.config.DynamicDataSourceContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import java.util.Map; + +/** + * 动态数据源的工厂,主要解决缓存依赖 + * + * @version 1.0 + * @author ailanyin + * @since 2023-04-25 21:47:34 + */ +@Configuration +public class DynamicDataSourceFactory { + + /** + * 把DynamicDataSourceContext 纳入容器管理,其他地方使用DynamicDataSourceConfig 类可以直接从容器取对象,并调用freshDataSource方法 + */ + @Bean + @Primary + public static DynamicDataSourceContext dataSource() { + Map targetDataSource = DynamicDataSourceConfig.getDataSource(); + //把DynamicDataSourceContext纳入容器管理 + DynamicDataSourceContext dynamicDataSourceContext = new DynamicDataSourceContext(); + dynamicDataSourceContext.freshDataSource(targetDataSource); + return dynamicDataSourceContext; + } +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/filters/HandleTenantFilter.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/filters/HandleTenantFilter.java new file mode 100644 index 0000000..999201c --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/filters/HandleTenantFilter.java @@ -0,0 +1,36 @@ +package com.qiaoba.common.database.filters; + +import com.qiaoba.common.database.config.DynamicDataSourceContext; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 动态切换不同租户的数据源 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-25 22:48:43 + */ +@Component +@Order(-10000) +public class HandleTenantFilter implements Filter { + + @Resource + private DynamicDataSourceContext dynamicDataSourceContext; + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + String instanceId = request.getParameter("tenant"); + //设置当前租户对应的数据库 + dynamicDataSourceContext.setDataSource(instanceId); + System.out.println("当前数据源是:" + dynamicDataSourceContext.getDataSource()); + filterChain.doFilter(servletRequest, servletResponse); + dynamicDataSourceContext.clearDataSource(); + } +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/mapper/BaseMapperPlus.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/mapper/BaseMapperPlus.java new file mode 100644 index 0000000..0addbaa --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/mapper/BaseMapperPlus.java @@ -0,0 +1,306 @@ +package com.qiaoba.common.database.mapper; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.*; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.toolkit.Db; +import com.qiaoba.common.web.utils.BeanCopyUtil; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 自定义 Mapper 接口, 实现 自定义扩展 + * + * @param mapper 泛型 + * @param table 泛型 + * @param vo 泛型 + * @author ailanyin + * @since 2023-04-23 17:20:32 + */ +@SuppressWarnings("unchecked") +public interface BaseMapperPlus extends BaseMapper { + + + /** + * currentVoClass + * + * @return Vo + */ + default Class currentVoClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2); + } + + /** + * currentModelClass + * + * @return model + */ + default Class currentModelClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1); + } + + /** + * currentMapperClass + * + * @return mapper + */ + default Class currentMapperClass() { + return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0); + } + + /** + * 查询所有 + * + * @return all lst + */ + default List selectList() { + return this.selectList(new QueryWrapper<>()); + } + + /** + * 批量新增 + * + * @param entityList list + * @return 结果 + */ + default boolean insertBatch(Collection entityList) { + return Db.saveBatch(entityList); + } + + /** + * 批量更新 + * + * @param entityList list + * @return 结果 + */ + default boolean updateBatchById(Collection entityList) { + return Db.updateBatchById(entityList); + } + + + /** + * 批量插入或更新 + * + * @param entityList list + * @return 结果 + */ + default boolean insertOrUpdateBatch(Collection entityList) { + return Db.saveOrUpdateBatch(entityList); + } + + + /** + * 批量插入(包含限制条数) + * + * @param entityList list + * @param batchSize 最大调数 + * @return 结果 + */ + default boolean insertBatch(Collection entityList, int batchSize) { + return Db.saveBatch(entityList, batchSize); + } + + + /** + * 批量更新(包含限制条数) + * + * @param entityList list + * @param batchSize 最大调数 + * @return 结果 + */ + default boolean updateBatchById(Collection entityList, int batchSize) { + return Db.updateBatchById(entityList, batchSize); + } + + + /** + * 批量插入或更新(包含限制条数) + * + * @param entityList list + * @param batchSize 最大调数 + * @return 结果 + */ + default boolean insertOrUpdateBatch(Collection entityList, int batchSize) { + return Db.saveOrUpdateBatch(entityList, batchSize); + } + + + /** + * 插入或更新 + * @param entity entity + * @return 结果 + */ + default boolean insertOrUpdate(T entity) { + return Db.saveOrUpdate(entity); + } + + /** + * 查询Vo by id + * @param id 主键 + * @return Vo + */ + default V selectVoById(Serializable id) { + return selectVoById(id, this.currentVoClass()); + } + + /** + * 根据 ID 查询 + * + * @param id 主键 + * @param voClass Vo + * @param 泛型 + * @return Vo + */ + default C selectVoById(Serializable id, Class voClass) { + T obj = this.selectById(id); + if (ObjectUtil.isNull(obj)) { + return null; + } + return BeanCopyUtil.copy(obj, voClass); + } + + /** + * 通过Ids 查询 list + * + * @param idList ids + * @return list + */ + default List selectVoBatchIds(Collection idList) { + return selectVoBatchIds(idList, this.currentVoClass()); + } + + /** + * 通过Ids 查询 list + * + * @param idList ids + * @param voClass Vo + * @param 泛型 + * @return list + */ + default List selectVoBatchIds(Collection idList, Class voClass) { + List list = this.selectBatchIds(idList); + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + return BeanCopyUtil.copyList(list, voClass); + } + + /** + * selectVoByMap + * + * @param map map + * @return Vo + */ + default List selectVoByMap(Map map) { + return selectVoByMap(map, this.currentVoClass()); + } + + /** + * selectVoByMap + * + * @param map map + * @param voClass Vo + * @param 泛型 + * @return Vo + */ + default List selectVoByMap(Map map, Class voClass) { + List list = this.selectByMap(map); + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + return BeanCopyUtil.copyList(list, voClass); + } + + /** + * 根据条件查询一条记录 + * + * @param wrapper 条件 + * @return Vo + */ + default V selectVoOne(Wrapper wrapper) { + return selectVoOne(wrapper, this.currentVoClass()); + } + + /** + * 根据条件查询一条记录 + * + * @param wrapper 条件 + * @param voClass Vo + * @param 泛型 + * @return Vo + */ + default C selectVoOne(Wrapper wrapper, Class voClass) { + T obj = this.selectOne(wrapper); + if (ObjectUtil.isNull(obj)) { + return null; + } + return BeanCopyUtil.copy(obj, voClass); + } + + /** + * 根据条件查询所有 + * + * @param wrapper 条件 + * @return list + */ + default List selectVoList(Wrapper wrapper) { + return selectVoList(wrapper, this.currentVoClass()); + } + + /** + * 根据条件查询所有 + * + * @param wrapper 条件 + * @param voClass Vo + * @param 泛型 + * @return list vo + */ + default List selectVoList(Wrapper wrapper, Class voClass) { + List list = this.selectList(wrapper); + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + return BeanCopyUtil.copyList(list, voClass); + } + + /** + * 分页查询Vo + * + * @param page 分页对象 + * @param wrapper 条件 + * @param

泛型 + * @return IPage + */ + default

> P selectVoPage(IPage page, Wrapper wrapper) { + return selectVoPage(page, wrapper, this.currentVoClass()); + } + + /** + * 分页查询Vo + * + * @param page 分页对象 + * @param wrapper 条件 + * @param voClass Vo + * @param 泛型 + * @param

泛型 + * @return IPage + */ + default > P selectVoPage(IPage page, Wrapper wrapper, Class voClass) { + IPage pageData = this.selectPage(page, wrapper); + IPage voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal()); + if (CollUtil.isEmpty(pageData.getRecords())) { + return (P) voPage; + } + voPage.setRecords(BeanCopyUtil.copyList(pageData.getRecords(), voClass)); + return (P) voPage; + } + +} diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/resources/META-INF/spring.factories b/qiaoba-commons/qiaoba-common-datasource/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..f13b9e4 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.qiaoba.common.database.config.DynamicDataSourceConfig,\ + com.qiaoba.common.database.filters.HandleTenantFilter + + diff --git a/qiaoba-commons/qiaoba-common-doc/pom.xml b/qiaoba-commons/qiaoba-common-doc/pom.xml new file mode 100644 index 0000000..6f50280 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-doc/pom.xml @@ -0,0 +1,24 @@ + + + + qiaoba-commons + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-common-doc + + + + com.github.xiaoymin + knife4j-openapi3-spring-boot-starter + + + org.springdoc + springdoc-openapi-ui + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-doc/src/main/java/.gitkeep b/qiaoba-commons/qiaoba-common-doc/src/main/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-doc/src/main/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-commons/qiaoba-common-doc/src/main/resources/.gitkeep b/qiaoba-commons/qiaoba-common-doc/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-doc/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-commons/qiaoba-common-redis/pom.xml b/qiaoba-commons/qiaoba-common-redis/pom.xml new file mode 100644 index 0000000..3750505 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/pom.xml @@ -0,0 +1,26 @@ + + + + qiaoba-commons + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-common-redis + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + com.fasterxml.jackson.core + jackson-databind + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/config/RedisConfig.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/config/RedisConfig.java new file mode 100644 index 0000000..80e6e96 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/config/RedisConfig.java @@ -0,0 +1,71 @@ +package com.qiaoba.common.redis.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +/** + * Redis 基础配置 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:44 + */ +@Configuration +@AutoConfigureBefore(RedisAutoConfiguration.class) +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(serializer); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + @Bean + public RedisSerializer redisSerializer() { + //创建JSON序列化器 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + //实体类存在子类继承父类,必须设置 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + //必须设置,否则无法将JSON转化为对象,会转化成Map类型 + objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + //设置Redis缓存有效期为1天 + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + +} diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/constants/CacheConstant.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/constants/CacheConstant.java new file mode 100644 index 0000000..eb11909 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/constants/CacheConstant.java @@ -0,0 +1,51 @@ +package com.qiaoba.common.redis.constants; + +/** + * 缓存的key 常量 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0002 下午 17:41 + */ +public class CacheConstant { + + /** + * 登录用户 redis key + */ + public static final String LOGIN_USER_KEY = "login_users:"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 防重提交 redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 限流 redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 登录账户密码错误次数 redis key + */ + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; + + /** + * 角色拥有的权限Set + */ + public static final String ROLE_PERMS = "role_perms:role_"; +} diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java new file mode 100644 index 0000000..912d90a --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java @@ -0,0 +1,357 @@ +package com.qiaoba.common.redis.service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 自定义Redis接口 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0002 下午 17:41 + */ +public interface RedisService { + + /** + * 保存为 Set + * + * @param key key + * @param value value + * @param time 存活时间 单位秒 + */ + void set(String key, Object value, long time); + + /** + * 保存为 Set, 永久 + * + * @param key key + * @param value value + */ + void set(String key, Object value); + + /** + * 通过 key 获取值 + * + * @param key key + * @return Object + */ + Object get(String key); + + /** + * 删除 key + * + * @param key key + * @return Boolean + */ + Boolean del(String key); + + /** + * 批量删除 + * + * @param collection keys + */ + void del(Collection collection); + + + /** + * 设置过期时间 + * + * @param key key + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean expire(String key, long time); + + /** + * 获取过期时间 + * + * @param key key + * @return long 单位秒 + */ + Long getExpire(String key); + + /** + * 判断是否有该属性 + * + * @param key key + * @return Boolean + */ + Boolean hasKey(String key); + + /** + * 按 delta 递增 + *

+ * value = value + delta + * + * @param key key + * @param delta 值 + * @return Long 操作后的值 + */ + Long incr(String key, long delta); + + /** + * 按 delta 递减 + *

+ * value = value - delta + * + * @param key key + * @param delta 值 + * @return Long 操作后的值 + */ + Long decr(String key, long delta); + + /** + * 获取Hash结构中的属性 + * + * @param key key + * @param hashKey hashKey + * @return Object + */ + Object hGet(String key, String hashKey); + + /** + * 向Hash结构中放入一个属性 + * + * @param key key + * @param hashKey hashKey + * @param value value + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean hSet(String key, String hashKey, Object value, long time); + + /** + * 向Hash结构中放入一个属性 永久 + * + * @param key key + * @param hashKey hashKey + * @param value value + */ + void hSet(String key, String hashKey, Object value); + + /** + * 直接获取整个Hash结构 + * + * @param key key + * @return Map + */ + Map hGetAll(String key); + + /** + * 直接设置整个Hash结构 + * + * @param key key + * @param map map + * @param time 存活时间 单位秒 + * @return Boolean + */ + Boolean hSetAll(String key, Map map, long time); + + /** + * 直接设置整个Hash结构 + * + * @param key key + * @param map map + */ + void hSetAll(String key, Map map); + + /** + * 删除Hash结构中的属性 + * + * @param key key + * @param hashKey hashKey + */ + void hDel(String key, Object... hashKey); + + /** + * 判断Hash结构中是否有该属性 + * + * @param key key + * @param hashKey hashKey + * @return Boolean + */ + Boolean hHasKey(String key, String hashKey); + + /** + * Hash结构中属性递增 + * + * @param key key + * @param hashKey hashKey + * @param delta 数值 + * @return 操作后最终的值 + */ + Long hIncr(String key, String hashKey, Long delta); + + /** + * Hash结构中属性递减 + * + * @param key key + * @param hashKey hashKey + * @param delta 数值 + * @return 操作后最终的值 + */ + Long hDecr(String key, String hashKey, Long delta); + + /** + * 获取Set结构 + * + * @param key key + * @return Set + */ + Set sMembers(String key); + + /** + * 向Set结构中添加属性 + * + * @param key key + * @param values values + * @return 被添加到集合中的新元素的数量,不包括被忽略的元素 + */ + Long sAdd(String key, Object... values); + + /** + * 向Set结构中添加属性 + * + * @param key key + * @param time 存活时间 单位秒 + * @param values values + * @return 被添加到集合中的新元素的数量,不包括被忽略的元素 + */ + Long sAdd(String key, long time, Object... values); + + /** + * 是否为Set中的属性 + * + * @param key key + * @param value value + * @return Boolean + */ + Boolean sIsMember(String key, Object value); + + /** + * 获取Set结构的长度 + * + * @param key key + * @return Set结构的长度 + */ + Long sSize(String key); + + /** + * 删除Set结构中的属性 + * + * @param key key + * @param values values + * @return 被成功移除的元素的数量,不包括被忽略的元素 + */ + Long sRemove(String key, Object... values); + + /** + * 获取List结构中的属性 + * + * @param key key + * @param start 开始索引 + * @param end 结束索引 + * @return List + */ + List lRange(String key, long start, long end); + + /** + * 获取List结构的长度 + * + * @param key key + * @return list.size + */ + Long lSize(String key); + + /** + * 根据索引获取List中的属性 + * + * @param key key + * @param index 索引 + * @return Object + */ + Object lIndex(String key, long index); + + /** + * 向List结构中添加属性 + * + * @param key key + * @param value value + * @return 执行命令后,列表的长度 + */ + Long lPush(String key, Object value); + + /** + * 向List结构中添加属性 + * + * @param key key + * @param value value + * @param time 存活时间 单位秒 + * @return 执行命令后,列表的长度 + */ + Long lPush(String key, Object value, long time); + + /** + * 向List结构中批量添加属性 + * + * @param key key + * @param values values + * @return 执行命令后,列表的长度 + */ + Long lPushAll(String key, Object... values); + + /** + * 向List结构中批量添加属性 + * + * @param key key + * @param time 存活时间 单位秒 + * @param values values + * @return 执行命令后,列表的长度 + */ + Long lPushAll(String key, Long time, Object... values); + + /** + * 从List结构中移除属性 + * + * @param key key + * @param count 数量 + * count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。 + * count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。 + * count = 0 : 移除表中所有与 VALUE 相等的值。 + * @param value value + * @return 被移除元素的数量 + */ + Long lRemove(String key, long count, Object value); + + + /** + * 模糊查询所有key + * + * @param key key + * @return keys + */ + Collection getKeys(String key); + + /** + * get object + * + * @param key key + * @param clazz clazz + * @param T + * @return clazz + */ + T getObject(String key, Class clazz); + + + /** + * get list + * + * @param key key + * @param clazz clazz + * @param T + * @return // List + */ + List getObjectList(String key, Class clazz); +} diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java new file mode 100644 index 0000000..06b2d24 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java @@ -0,0 +1,224 @@ +package com.qiaoba.common.redis.service.impl; + + +import com.qiaoba.common.redis.service.RedisService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * 自定义Redis接口实现类 + * + * @author ailanyin + * @version 1.0 + * @since 2021/10/2 0003 下午 17:44 + */ +@Service +public class RedisServiceImpl implements RedisService { + + @Autowired + private RedisTemplate redisTemplate; + + @Override + public void set(String key, Object value, long time) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } + + @Override + public void set(String key, Object value) { + redisTemplate.opsForValue().set(key, value); + } + + @Override + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + @Override + public Boolean del(String key) { + return redisTemplate.delete(key); + } + + @Override + public void del(Collection collection) { + redisTemplate.delete(collection); + } + + @Override + public Boolean expire(String key, long time) { + return redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + + @Override + public Long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + @Override + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + @Override + public Long incr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, delta); + } + + @Override + public Long decr(String key, long delta) { + return redisTemplate.opsForValue().increment(key, -delta); + } + + @Override + public Object hGet(String key, String hashKey) { + return redisTemplate.opsForHash().get(key, hashKey); + } + + @Override + public Boolean hSet(String key, String hashKey, Object value, long time) { + redisTemplate.opsForHash().put(key, hashKey, value); + return expire(key, time); + } + + @Override + public void hSet(String key, String hashKey, Object value) { + redisTemplate.opsForHash().put(key, hashKey, value); + } + + @Override + public Map hGetAll(String key) { + return redisTemplate.opsForHash().entries(key); + } + + @Override + public Boolean hSetAll(String key, Map map, long time) { + redisTemplate.opsForHash().putAll(key, map); + return expire(key, time); + } + + @Override + public void hSetAll(String key, Map map) { + redisTemplate.opsForHash().putAll(key, map); + } + + @Override + public void hDel(String key, Object... hashKey) { + redisTemplate.opsForHash().delete(key, hashKey); + } + + @Override + public Boolean hHasKey(String key, String hashKey) { + return redisTemplate.opsForHash().hasKey(key, hashKey); + } + + @Override + public Long hIncr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, delta); + } + + @Override + public Long hDecr(String key, String hashKey, Long delta) { + return redisTemplate.opsForHash().increment(key, hashKey, -delta); + } + + @Override + public Set sMembers(String key) { + return redisTemplate.opsForSet().members(key); + } + + @Override + public Long sAdd(String key, Object... values) { + return redisTemplate.opsForSet().add(key, values); + } + + @Override + public Long sAdd(String key, long time, Object... values) { + Long count = redisTemplate.opsForSet().add(key, values); + expire(key, time); + return count; + } + + @Override + public Boolean sIsMember(String key, Object value) { + return redisTemplate.opsForSet().isMember(key, value); + } + + @Override + public Long sSize(String key) { + return redisTemplate.opsForSet().size(key); + } + + @Override + public Long sRemove(String key, Object... values) { + return redisTemplate.opsForSet().remove(key, values); + } + + @Override + public List lRange(String key, long start, long end) { + return redisTemplate.opsForList().range(key, start, end); + } + + @Override + public Long lSize(String key) { + return redisTemplate.opsForList().size(key); + } + + @Override + public Object lIndex(String key, long index) { + return redisTemplate.opsForList().index(key, index); + } + + @Override + public Long lPush(String key, Object value) { + return redisTemplate.opsForList().rightPush(key, value); + } + + @Override + public Long lPush(String key, Object value, long time) { + Long index = redisTemplate.opsForList().rightPush(key, value); + expire(key, time); + return index; + } + + @Override + public Long lPushAll(String key, Object... values) { + return redisTemplate.opsForList().rightPushAll(key, values); + } + + @Override + public Long lPushAll(String key, Long time, Object... values) { + Long count = redisTemplate.opsForList().rightPushAll(key, values); + expire(key, time); + return count; + } + + @Override + public Long lRemove(String key, long count, Object value) { + return redisTemplate.opsForList().remove(key, count, value); + } + + + @Override + public Collection getKeys(String key) { + return redisTemplate.keys(key); + } + + @Override + @SuppressWarnings("unchecked") + public T getObject(String key, Class clazz) { + return (T) get(key); + } + + @Override + @SuppressWarnings("unchecked") + public List getObjectList(String key, Class clazz) { + return (List) get(key); + } + +} diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/resources/META-INF/spring.factories b/qiaoba-commons/qiaoba-common-redis/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..bfd251a --- /dev/null +++ b/qiaoba-commons/qiaoba-common-redis/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + com.qiaoba.common.redis.config.RedisConfig,\ + com.qiaoba.common.redis.service.impl.RedisServiceImpl + + diff --git a/qiaoba-commons/qiaoba-common-web/pom.xml b/qiaoba-commons/qiaoba-common-web/pom.xml new file mode 100644 index 0000000..da92364 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-web/pom.xml @@ -0,0 +1,24 @@ + + + + qiaoba-commons + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-common-web + + + + cn.hutool + hutool-all + + + org.springframework.boot + spring-boot-starter-web + + + \ No newline at end of file diff --git a/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/BeanCopyUtil.java b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/BeanCopyUtil.java new file mode 100644 index 0000000..eefca59 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/BeanCopyUtil.java @@ -0,0 +1,227 @@ +package com.qiaoba.common.web.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.SimpleCache; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.cglib.beans.BeanCopier; +import org.springframework.cglib.beans.BeanMap; +import org.springframework.cglib.core.Converter; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * bean深拷贝工具(基于 cglib 性能优异) + *

+ * 重点 cglib 不支持 拷贝到链式对象 + * 例如: 源对象 拷贝到 目标(链式对象) + * 请区分好`浅拷贝`和`深拷贝`再做使用 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 15:34:59 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class BeanCopyUtil { + + /** + * 单对象基于class创建拷贝 + * + * @param source 数据来源实体 + * @param desc 描述对象 转换后的对象 + * @return desc + */ + public static V copy(T source, Class desc) { + if (ObjectUtil.isNull(source)) { + return null; + } + if (ObjectUtil.isNull(desc)) { + return null; + } + final V target = ReflectUtil.newInstanceIfPossible(desc); + return copy(source, target); + } + + /** + * 单对象基于对象创建拷贝 + * + * @param source 数据来源实体 + * @param desc 转换后的对象 + * @return desc + */ + public static V copy(T source, V desc) { + if (ObjectUtil.isNull(source)) { + return null; + } + if (ObjectUtil.isNull(desc)) { + return null; + } + BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null); + beanCopier.copy(source, desc, null); + return desc; + } + + /** + * 列表对象基于class创建拷贝 + * + * @param sourceList 数据来源实体列表 + * @param desc 描述对象 转换后的对象 + * @return desc + */ + public static List copyList(List sourceList, Class desc) { + if (ObjectUtil.isNull(sourceList)) { + return null; + } + if (CollUtil.isEmpty(sourceList)) { + return CollUtil.newArrayList(); + } + return toList(sourceList, source -> { + V target = ReflectUtil.newInstanceIfPossible(desc); + copy(source, target); + return target; + }); + } + + /** + * bean拷贝到map + * + * @param bean 数据来源实体 + * @return map对象 + */ + @SuppressWarnings("unchecked") + public static Map copyToMap(T bean) { + if (ObjectUtil.isNull(bean)) { + return null; + } + return BeanMap.create(bean); + } + + /** + * map拷贝到bean + * + * @param map 数据来源 + * @param beanClass bean类 + * @return bean对象 + */ + public static T mapToBean(Map map, Class beanClass) { + if (MapUtil.isEmpty(map)) { + return null; + } + if (ObjectUtil.isNull(beanClass)) { + return null; + } + T bean = ReflectUtil.newInstanceIfPossible(beanClass); + return mapToBean(map, bean); + } + + /** + * map拷贝到bean + * + * @param map 数据来源 + * @param bean bean对象 + * @return bean对象 + */ + public static T mapToBean(Map map, T bean) { + if (MapUtil.isEmpty(map)) { + return null; + } + if (ObjectUtil.isNull(bean)) { + return null; + } + BeanMap.create(bean).putAll(map); + return bean; + } + + /** + * map拷贝到map + * + * @param map 数据来源 + * @param clazz 返回的对象类型 + * @return map对象 + */ + public static Map mapToMap(Map map, Class clazz) { + if (MapUtil.isEmpty(map)) { + return null; + } + if (ObjectUtil.isNull(clazz)) { + return null; + } + Map copyMap = new LinkedHashMap<>(map.size()); + map.forEach((k, v) -> copyMap.put(k, copy(v, clazz))); + return copyMap; + } + + /** + * BeanCopier属性缓存
+ * 缓存用于防止多次反射造成的性能问题 + * + * @author Looly + * @since 5.4.1 + */ + public enum BeanCopierCache { + /** + * BeanCopier属性缓存单例 + */ + INSTANCE; + + private final SimpleCache cache = new SimpleCache<>(); + + /** + * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素 + * + * @param srcClass 源Bean的类 + * @param targetClass 目标Bean的类 + * @param converter 转换器 + * @return Map中对应的BeanCopier + */ + public BeanCopier get(Class srcClass, Class targetClass, Converter converter) { + final String key = genKey(srcClass, targetClass, converter); + return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null)); + } + + /** + * 获得类与转换器生成的key + * + * @param srcClass 源Bean的类 + * @param targetClass 目标Bean的类 + * @param converter 转换器 + * @return 属性名和Map映射的key + */ + private String genKey(Class srcClass, Class targetClass, Converter converter) { + final StringBuilder key = StrUtil.builder() + .append(srcClass.getName()).append('#').append(targetClass.getName()); + if (null != converter) { + key.append('#').append(converter.getClass().getName()); + } + return key.toString(); + } + } + + /** + * 将collection转化为List集合,但是两者的泛型不同
+ * {@code Collection ------> List } + * + * @param collection 需要转化的集合 + * @param function collection中的泛型转化为list泛型的lambda表达式 + * @param collection中的泛型 + * @param List中的泛型 + * @return 转化后的list + */ + private static List toList(Collection collection, Function function) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + return collection + .stream() + .map(function) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + +} diff --git a/qiaoba-commons/qiaoba-common-web/src/main/resources/.gitkeep b/qiaoba-commons/qiaoba-common-web/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-web/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-modules/pom.xml b/qiaoba-modules/pom.xml new file mode 100644 index 0000000..e9807b2 --- /dev/null +++ b/qiaoba-modules/pom.xml @@ -0,0 +1,20 @@ + + + + qiaoba-boot + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-modules + pom + + qiaoba-module-system + qiaoba-module-job + + + + \ No newline at end of file diff --git a/qiaoba-modules/qiaoba-module-job/pom.xml b/qiaoba-modules/qiaoba-module-job/pom.xml new file mode 100644 index 0000000..a0f3eb0 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-job/pom.xml @@ -0,0 +1,15 @@ + + + + qiaoba-modules + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-module-job + + + \ No newline at end of file diff --git a/qiaoba-modules/qiaoba-module-job/src/main/java/.gitkeep b/qiaoba-modules/qiaoba-module-job/src/main/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-job/src/main/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-modules/qiaoba-module-job/src/main/resources/.gitkeep b/qiaoba-modules/qiaoba-module-job/src/main/resources/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-job/src/main/resources/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-modules/qiaoba-module-job/src/test/java/.gitkeep b/qiaoba-modules/qiaoba-module-job/src/test/java/.gitkeep new file mode 100644 index 0000000..ffece94 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-job/src/test/java/.gitkeep @@ -0,0 +1 @@ +null not found diff --git a/qiaoba-modules/qiaoba-module-system/pom.xml b/qiaoba-modules/qiaoba-module-system/pom.xml new file mode 100644 index 0000000..062dc0c --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/pom.xml @@ -0,0 +1,20 @@ + + + + qiaoba-modules + com.qiaoba + 1.0 + + 4.0.0 + + qiaoba-module-system + + + + com.qiaoba + qiaoba-api-system + + + \ No newline at end of file diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysUserController.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysUserController.java new file mode 100644 index 0000000..c63841d --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/controller/SysUserController.java @@ -0,0 +1,49 @@ +package com.qiaoba.module.system.controller; + +import cn.hutool.core.util.RandomUtil; +import com.qiaoba.api.system.entity.SysUser; +import com.qiaoba.api.system.entity.param.SysUserParam; +import com.qiaoba.module.system.service.SysUserService; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 用户管理 web层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 20:51:26 + */ +@RestController +@RequestMapping("/system/user") +@Tag(name = "用户管理") +public class SysUserController { + + @Resource + private SysUserService baseService; + + @GetMapping("/add") + public String add() { + SysUser sysUser = new SysUser(); + sysUser.setUsername(RandomUtil.randomString(8)); + sysUser.setNickname(RandomUtil.randomString(8)); + sysUser.setIsSuperuser(false); + sysUser.setIsDelete(true); + sysUser.setIsManager(true); + baseService.insert(sysUser); + return "OK"; + } + + @GetMapping("/list") + public List list(@RequestParam String name) { + SysUserParam dto = new SysUserParam(); + dto.setNickname(name); + return baseService.selectList(dto); + } +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysTenantMapper.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysTenantMapper.java new file mode 100644 index 0000000..dc256ed --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysTenantMapper.java @@ -0,0 +1,14 @@ +package com.qiaoba.module.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qiaoba.api.system.entity.SysTenant; + +/** + * 租户管理 数据层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-24 19:44:48 + */ +public interface SysTenantMapper extends BaseMapper { +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysUserMapper.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..566b372 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/mapper/SysUserMapper.java @@ -0,0 +1,14 @@ +package com.qiaoba.module.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.qiaoba.api.system.entity.SysUser; + +/** + * 用户管理 数据层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 20:38:55 + */ +public interface SysUserMapper extends BaseMapper { +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysTenantService.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysTenantService.java new file mode 100644 index 0000000..c85c77e --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysTenantService.java @@ -0,0 +1,13 @@ +package com.qiaoba.module.system.service; + +import com.qiaoba.api.system.service.SysTenantApiService; + +/** + * 租户管理 服务层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-24 19:23:08 + */ +public interface SysTenantService extends SysTenantApiService { +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysUserService.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysUserService.java new file mode 100644 index 0000000..2f4c05f --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/SysUserService.java @@ -0,0 +1,25 @@ +package com.qiaoba.module.system.service; + +import com.qiaoba.api.system.entity.SysUser; +import com.qiaoba.api.system.entity.param.SysUserParam; +import com.qiaoba.api.system.service.SysUserApiService; + +import java.util.List; + +/** + * 用户管理 服务层 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 20:33:37 + */ +public interface SysUserService extends SysUserApiService { + + /** + * 条件查询列表 + * + * @param sysUserParam 查询参数 + * @return list + */ + List selectList(SysUserParam sysUserParam); +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysTenantServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysTenantServiceImpl.java new file mode 100644 index 0000000..3ebb8df --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,32 @@ +package com.qiaoba.module.system.service.impl; + +import com.qiaoba.api.system.entity.SysTenant; +import com.qiaoba.module.system.mapper.SysTenantMapper; +import com.qiaoba.module.system.service.SysTenantService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 租户管理 业务层实现 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-24 19:46:00 + */ +@Service +public class SysTenantServiceImpl implements SysTenantService { + + @Resource + private SysTenantMapper baseMapper; + + @Override + public int insert(SysTenant sysTenant) { + return baseMapper.insert(sysTenant); + } + + @Override + public int update(SysTenant sysTenant) { + return baseMapper.updateById(sysTenant); + } +} diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..c5eaded --- /dev/null +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,47 @@ +package com.qiaoba.module.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.qiaoba.api.system.entity.SysUser; +import com.qiaoba.api.system.entity.param.SysUserParam; +import com.qiaoba.module.system.mapper.SysUserMapper; +import com.qiaoba.module.system.service.SysUserService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 用户管理 服务层实现 + * + * @author ailanyin + * @version 1.0 + * @since 2023-04-23 20:38:09 + */ +@Service +public class SysUserServiceImpl implements SysUserService { + + @Resource + private SysUserMapper baseMapper; + + @Override + public int insert(SysUser sysUser) { + return baseMapper.insert(sysUser); + } + + @Override + public int update(SysUser sysUser) { + return baseMapper.updateById(sysUser); + } + + @Override + public List selectList(SysUserParam sysUserParam) { + return baseMapper.selectList(param2Wrapper(sysUserParam)); + } + + private QueryWrapper param2Wrapper(SysUserParam sysUserParam) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.lambda().like(StrUtil.isNotBlank(sysUserParam.getNickname()), SysUser::getNickname, sysUserParam.getNickname()); + return wrapper; + } +}