From 53e153e787b129e1168b903ff5e5cc34a300eabb Mon Sep 17 00:00:00 2001 From: zhuyijun Date: Sat, 24 Sep 2022 00:11:25 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BF=AE=E6=94=B9shardingjdbc?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=202=E3=80=81=E6=96=B0=E5=A2=9Eapi?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E6=8E=A7=E5=88=B6=EF=BC=8C=203=E3=80=81?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E8=A7=92=E8=89=B2=E5=85=B3?= =?UTF-8?q?=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 - server/zyjblogs-gateway/pom.xml | 4 + .../config/security/ResourceServerConfig.java | 4 +- .../user/controller/AuthController.java | 7 +- .../user/controller/LoginController.java | 8 +- .../cn/zyjblogs/server/user/po/UserPo.java | 8 -- .../src/main/resources/bootstrap.yml | 68 ++++++++++++ .../role/controller/RoleController.java | 19 ++-- .../zyjblogs/server/role/dto/RolePageDto.java | 49 ++------- .../cn/zyjblogs/server/role/po/RolePo.java | 2 + .../server/role/service/RoleService.java | 2 +- .../role/service/impl/RoleServiceImpl.java | 4 +- .../cn/zyjblogs/server/role/vo/RoleVo.java | 30 +++--- .../user/controller/UserController.java | 12 ++- .../cn/zyjblogs/server/user/dto/UserDto.java | 41 ++++--- .../zyjblogs/server/user/dto/UserPageDto.java | 16 ++- .../zyjblogs/server/user/dto/UserRoleDto.java | 31 ++++++ .../server/user/mapper/UserRoleMapper.java | 12 +++ .../cn/zyjblogs/server/user/po/UserPo.java | 6 -- .../zyjblogs/server/user/po/UserRolePo.java | 28 +++++ .../server/user/service/UserRoleService.java | 54 ++++++++++ .../server/user/service/UserService.java | 10 ++ .../service/impl/UserRoleServiceImpl.java | 101 ++++++++++++++++++ .../user/service/impl/UserServiceImpl.java | 11 +- .../zyjblogs/server/user/vo/UserRoleVo.java | 29 +++++ .../cn/zyjblogs/server/user/vo/UserVo.java | 41 ++++--- .../src/main/resources/bootstrap.yml | 72 ++++++++++++- .../mapper/mysql/role/RoleMapper.xml | 11 +- .../mapper/mysql/user/UserMapper.xml | 36 +------ .../mapper/postgresql/role/RoleMapper.xml | 11 +- .../mapper/postgresql/user/UserMapper.xml | 13 ++- .../exception/AbstractBusinessException.java | 5 +- .../exception/CommonBusinessException.java | 18 ++++ .../ResourceAuthenticationEntryPoint.java | 2 +- .../oauth/resource/ResourceServerConfig.java | 3 +- .../starter/web/apiversion/ApiVersion.java | 20 ++++ .../web/apiversion/ApiVersionCondition.java | 49 +++++++++ ...piVersionRequestMappingHandlerMapping.java | 38 +++++++ .../ApiVersionWebMvcAutoConfiguration.java | 18 ++++ ...obalExceptionHandlerAutoConfiguration.java | 4 +- .../Knife4jAutoConfigurationConfig.java | 12 +-- .../web/exception/ApiVersionException.java | 19 ++++ .../main/resources/META-INF/spring.factories | 3 +- 43 files changed, 749 insertions(+), 187 deletions(-) create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserRoleDto.java create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/mapper/UserRoleMapper.java create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserRolePo.java create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserRoleService.java create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserRoleServiceImpl.java create mode 100644 server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserRoleVo.java create mode 100644 stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/CommonBusinessException.java create mode 100644 stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersion.java create mode 100644 stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionCondition.java create mode 100644 stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionRequestMappingHandlerMapping.java create mode 100644 stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/ApiVersionWebMvcAutoConfiguration.java create mode 100644 stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/exception/ApiVersionException.java diff --git a/pom.xml b/pom.xml index d3b6581..0952d36 100644 --- a/pom.xml +++ b/pom.xml @@ -129,11 +129,6 @@ knife4j-spring-boot-starter ${knife4j.version} - - com.github.xiaoymin - knife4j-micro-spring-boot-starter - ${knife4j.version} - diff --git a/server/zyjblogs-gateway/pom.xml b/server/zyjblogs-gateway/pom.xml index d67c88b..9d8e7d2 100644 --- a/server/zyjblogs-gateway/pom.xml +++ b/server/zyjblogs-gateway/pom.xml @@ -90,5 +90,9 @@ com.github.xiaoymin knife4j-spring-boot-starter + + javax.servlet + javax.servlet-api + \ No newline at end of file diff --git a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/config/security/ResourceServerConfig.java b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/config/security/ResourceServerConfig.java index 0813163..a5e5b12 100644 --- a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/config/security/ResourceServerConfig.java +++ b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/config/security/ResourceServerConfig.java @@ -51,14 +51,14 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter { .csrf() .disable() //限制资源服务器作用范围为 "/user/**", "/demo/**" - .requestMatchers().antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", "/user/**", "/demo/**", + .requestMatchers().antMatchers("/v*/**,/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", "/v*/user/**", "/demo/**", String.join(",", whiteListProperties.getAllowPaths())) .and() .formLogin().and() .authorizeRequests() .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**", String.join(",", whiteListProperties.getAllowPaths())) .permitAll() - .antMatchers("/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll() + .antMatchers("/login", "/oauth/**", "/v*/user/login", "/v*/auth/refresh/token").permitAll() //以下请求必须认证通过 .anyRequest() .authenticated().and() diff --git a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/AuthController.java b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/AuthController.java index a90dae8..0aa6937 100644 --- a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/AuthController.java +++ b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/AuthController.java @@ -6,6 +6,7 @@ import cn.zyjblogs.server.user.service.AuthService; import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo; import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import cn.zyjblogs.starter.web.apiversion.ApiVersion; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -21,24 +22,28 @@ import org.springframework.web.bind.annotation.RestController; @Api(tags = {"token管理"}) @RestController @RequiredArgsConstructor -@RequestMapping("/auth") +@ApiVersion(1) +@RequestMapping("/{v}/auth") public class AuthController { private final AuthService authService; @ApiOperation(value = "刷新token", notes = "刷新token") @PostMapping("/refresh/token") + @ApiVersion(1) public ResponseObject refreshToken(@RequestBody @Validated OAuth2AccessTokenDto oAuth2AccessTokenDto) { return ResponseResult.success(authService.refreshToken(oAuth2AccessTokenDto)); } @ApiOperation(value = "检测token", notes = "刷新token") @PostMapping("/check/token") + @ApiVersion(1) public ResponseObject checkToken(@RequestBody @Validated OAuth2AccessTokenDto oAuth2AccessTokenDto) { return ResponseResult.success(authService.checkToken(oAuth2AccessTokenDto)); } @ApiOperation(value = "获取授权码", notes = "刷新token") @PostMapping("/authorize") + @ApiVersion(1) public void getAuthorizationCode(@RequestBody @Validated AuthorizationCodeDto authorizationCodeDto) { authService.getAuthorizationCode(authorizationCodeDto); } diff --git a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/LoginController.java b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/LoginController.java index 252652e..073e948 100644 --- a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/LoginController.java +++ b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/controller/LoginController.java @@ -5,9 +5,11 @@ import cn.zyjblogs.server.user.service.LoginService; import cn.zyjblogs.server.user.vo.OAuth2AccessTokenVo; import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import cn.zyjblogs.starter.web.apiversion.ApiVersion; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -20,17 +22,21 @@ import org.springframework.web.bind.annotation.RestController; @Api(tags = {"登录认证管理"}) @RestController @RequiredArgsConstructor -@RequestMapping("/user") +@Log4j2 +@ApiVersion(1) +@RequestMapping("/{v}/user") public class LoginController { private final LoginService loginService; @ApiOperation(value = "用户登录", notes = "用户登录") + @ApiVersion(1) @PostMapping("/login") public ResponseObject login(@RequestBody @Validated UserLoginDto userLoginDto) { return ResponseResult.success(loginService.login(userLoginDto)); } @ApiOperation(value = "用户注销", notes = "用户注销") + @ApiVersion(1) @PostMapping("/logout") public void logout() { loginService.logout(); diff --git a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/po/UserPo.java b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/po/UserPo.java index 357bacd..c81d609 100644 --- a/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/po/UserPo.java +++ b/server/zyjblogs-oauth/src/main/java/cn/zyjblogs/server/user/po/UserPo.java @@ -1,6 +1,5 @@ package cn.zyjblogs.server.user.po; -import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -14,7 +13,6 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; -import java.sql.Timestamp; import java.time.LocalDateTime; /** @@ -57,12 +55,6 @@ public class UserPo implements Serializable { @TableField("status") private Integer status; - @TableField("follow_num") - private Integer followNum; - - @TableField("fans_num") - private Integer fansNum; - @TableField("deleted") private Integer deleted; diff --git a/server/zyjblogs-oauth/src/main/resources/bootstrap.yml b/server/zyjblogs-oauth/src/main/resources/bootstrap.yml index 07f3b38..7ce61ea 100644 --- a/server/zyjblogs-oauth/src/main/resources/bootstrap.yml +++ b/server/zyjblogs-oauth/src/main/resources/bootstrap.yml @@ -29,6 +29,74 @@ spring: namespace: ${spring.cloud.nacos.config.namespace} group: public + shardingsphere: + datasource: + names: write-ds,read-ds-0 + write-ds: + jdbc-url: jdbc:mysql://127.0.0.1:3306/zyjblogs_rbac?allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: 123456 + connectionTimeoutMilliseconds: 3000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 50 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000\ + hikari: + minimum-idle: 10 + maximum-pool-size: 100 + auto-commit: true + idle-timeout: 1800000 + pool-name: DatebookHikariCP + max-lifetime: 1800000 + connection-timeout: 60000 + connection-test-query: SELECT 1 + read-ds-0: + jdbc-url: jdbc:mysql://127.0.0.1:3306/zyjblogs_rbac?allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + username: read + password: 123456 + connectionTimeoutMilliseconds: 3000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 50 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000 + hikari: + minimum-idle: 10 + maximum-pool-size: 100 + auto-commit: true + idle-timeout: 1800000 + pool-name: DatebookHikariCP + max-lifetime: 1800000 + connection-timeout: 60000 + connection-test-query: SELECT 1 + sharding: + master-slave-rules: + master0: + master-data-source-name: write-ds + slave-data-source-names: read-ds-0 + # rules: + # readwrite-splitting: + # data-sources: + # readwrite_ds: + # static-strategy: + # write-data-source-name: write-ds + # read-data-source-names: + # - read-ds-0 + # # 负载均衡算法名称 + # load-balancer-name: roundRobin + # load-balancers: + # # 一共两种一种是 RANDOM(随机),一种是 ROUND_ROBIN(轮询) + # roundRobin: + # type: ROUND_ROBIN + props: + sql: + show: true + logging: config: classpath:logback-spring.xml diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/controller/RoleController.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/controller/RoleController.java index c00ecb2..3c43c3d 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/controller/RoleController.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/controller/RoleController.java @@ -4,9 +4,11 @@ import cn.zyjblogs.server.role.dto.RolePageDto; import cn.zyjblogs.server.role.po.RolePo; import cn.zyjblogs.server.role.service.RoleService; import cn.zyjblogs.server.role.vo.RoleVo; +import cn.zyjblogs.starter.common.entity.context.BaseContext; import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseResult; import cn.zyjblogs.starter.common.utils.bean.BeanUtils; +import cn.zyjblogs.starter.web.apiversion.ApiVersion; import com.baomidou.mybatisplus.core.metadata.IPage; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -25,8 +27,9 @@ import java.util.List; */ @Api(tags = {"角色管理"}) @RestController -@RequestMapping("/role") +@RequestMapping("/{v}/role") @ResponseBody +@ApiVersion(1) @RequiredArgsConstructor public class RoleController { private final RoleService roleService; @@ -39,7 +42,8 @@ public class RoleController { * @author zhuyijun * @date 2022/9/19 上午12:06 */ - @ApiOperation(value = "1", notes = "通过id查询用户") + @ApiOperation(value = "通过id查询用户", notes = "通过id查询用户") + @ApiVersion(1) @GetMapping("/id") public ResponseObject findById(@RequestParam String id) { RolePo byId = roleService.getById(id); @@ -53,7 +57,8 @@ public class RoleController { * @author zhuyijun * @date 2022/9/19 上午1:14 */ - @ApiOperation(value = "page=1&limit=10", notes = "分页查询") + @ApiOperation(value = "分页查询", notes = "分页查询") + @ApiVersion(1) @GetMapping("/page") public ResponseObject> findPage(RolePageDto rolePageDto) { IPage page = roleService.findPage(rolePageDto); @@ -66,10 +71,11 @@ public class RoleController { * @author zhuyijun * @date 2022/9/22 下午11:33 */ - @ApiOperation(value = "", notes = "查询所有角色") + @ApiOperation(value = "查询当前租户下所有角色", notes = "查询所有角色") + @ApiVersion(1) @GetMapping("/list") public ResponseObject> findList() { - return ResponseResult.success(roleService.findList()); + return ResponseResult.success(roleService.findList(BaseContext.getTenantId())); } /** @@ -80,7 +86,8 @@ public class RoleController { * @author zhuyijun * @date 2022/9/19 上午1:14 */ - @ApiOperation(value = "1", notes = "通过角色id查询") + @ApiOperation(value = "通过角色id查询", notes = "通过角色id查询") + @ApiVersion(1) @PostMapping("/findByIds") public ResponseObject> findByIds(List ids) { return ResponseResult.success(roleService.findByIds(ids)); diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/dto/RolePageDto.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/dto/RolePageDto.java index e618717..3ac05f5 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/dto/RolePageDto.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/dto/RolePageDto.java @@ -1,66 +1,35 @@ package cn.zyjblogs.server.role.dto; -import cn.zyjblogs.starter.common.entity.constant.CommonConstant; import cn.zyjblogs.starter.common.entity.dto.PageDto; -import com.alibaba.fastjson.annotation.JSONField; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import lombok.AllArgsConstructor; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; -import java.time.LocalDateTime; /** * @author zhuyijun */ +@ApiModel(description = "角色分页查询") @Data -@AllArgsConstructor @NoArgsConstructor public class RolePageDto extends PageDto implements Serializable { - private String id; + @ApiModelProperty(value = "名称") private String name; - - + @ApiModelProperty(value = "状态") private Integer status; + @ApiModelProperty(value = "类型") + private Integer roleType; + @ApiModelProperty(value = "是否删除") private Integer deleted; - private String description; - - private String createUserId; - - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - @JSONField(format = CommonConstant.DATETIME_PATTERN) - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN) - private LocalDateTime createTime; - - private String editUserId; - - @JsonSerialize(using = LocalDateTimeSerializer.class) - @JsonDeserialize(using = LocalDateTimeDeserializer.class) - @JSONField(format = CommonConstant.DATETIME_PATTERN) - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN) - private LocalDateTime editTime; - private String tenantId; - @Builder - public RolePageDto(Integer page, Integer limit, String id, String name, Integer status, Integer deleted, String description, String createUserId, LocalDateTime createTime, String editUserId, LocalDateTime editTime, String tenantId) { + public RolePageDto(Integer page, Integer limit, String name, Integer status, Integer deleted) { super(page, limit); - this.id = id; this.name = name; this.status = status; this.deleted = deleted; - this.description = description; - this.createUserId = createUserId; - this.createTime = createTime; - this.editUserId = editUserId; - this.editTime = editTime; - this.tenantId = tenantId; } } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/po/RolePo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/po/RolePo.java index 00a6ea5..5eb7f3b 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/po/RolePo.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/po/RolePo.java @@ -31,6 +31,8 @@ public class RolePo implements Serializable { private String name; @TableField("status") private Integer status; + @TableField("role_type") + private Integer roleType; @TableField("deleted") private Integer deleted; diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/RoleService.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/RoleService.java index b4aa331..c64e83e 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/RoleService.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/RoleService.java @@ -35,6 +35,6 @@ public interface RoleService extends IService { * * @return */ - List findList(); + List findList(String tenantId); } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/impl/RoleServiceImpl.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/impl/RoleServiceImpl.java index 45fc2f3..549fdd3 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/impl/RoleServiceImpl.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/service/impl/RoleServiceImpl.java @@ -68,9 +68,9 @@ public class RoleServiceImpl extends ServiceImpl implements * @date 2022/9/22 下午11:32 */ @Override - public List findList() { + public List findList(String tenantId) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); - wrapper.eq(RolePo::getTenantId, BaseContext.getTenantId()); + wrapper.eq(tenantId != null, RolePo::getTenantId, tenantId); List rolePos = roleMapper.selectList(wrapper); if (CollectionUtils.isEmpty(rolePos)) { return new ArrayList<>(); diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/vo/RoleVo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/vo/RoleVo.java index 20a6db3..80e39d5 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/vo/RoleVo.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/role/vo/RoleVo.java @@ -1,12 +1,10 @@ package cn.zyjblogs.server.role.vo; -import com.alibaba.fastjson.annotation.JSONField; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -18,40 +16,42 @@ import java.time.LocalDateTime; /** * @author zhuyijun */ +@ApiModel(description = "角色实体类") @Data @Builder @AllArgsConstructor @NoArgsConstructor -@TableName("role") public class RoleVo implements Serializable { - @TableId("id") + @ApiModelProperty(value = "主键id") private String id; - @TableField("name") + @ApiModelProperty(value = "名称") private String name; - @TableField("status") + @ApiModelProperty(value = "状态") private Integer status; - @TableField("deleted") + @ApiModelProperty(value = "类型") + private Integer roleType; + @ApiModelProperty(value = "是否删除") private Integer deleted; - @TableField("description") + @ApiModelProperty(value = "描述") private String description; - @TableField("create_user_id") + @ApiModelProperty(value = "创建人") private String createUserId; + @ApiModelProperty(value = "创建时间") @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @TableField("create_time") private LocalDateTime createTime; - @TableField("edit_user_id") + @ApiModelProperty(value = "编辑人") private String editUserId; + @ApiModelProperty(value = "编辑时间") @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @TableField("edit_time") private LocalDateTime editTime; - @TableField("tenant_id") + @ApiModelProperty(value = "租户id") private String tenantId; } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/controller/UserController.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/controller/UserController.java index 07e8c6c..1edd5b2 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/controller/UserController.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/controller/UserController.java @@ -5,8 +5,10 @@ import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.po.UserPo; import cn.zyjblogs.server.user.service.UserService; import cn.zyjblogs.server.user.vo.UserVo; +import cn.zyjblogs.starter.common.entity.response.HttpCode; import cn.zyjblogs.starter.common.entity.response.ResponseObject; import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import cn.zyjblogs.starter.web.apiversion.ApiVersion; import com.baomidou.mybatisplus.core.metadata.IPage; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -29,10 +31,11 @@ import java.util.List; */ @Api(tags = {"用户管理"}) @RestController -@RequestMapping("/user") +@RequestMapping("/{v}/user") @RequiredArgsConstructor @ResponseBody @Log4j2 +@ApiVersion(1) public class UserController { private final UserService userService; @@ -47,6 +50,7 @@ public class UserController { */ @ApiOperation(value = "", notes = "通过id查询用户") @GetMapping("/id") + @ApiVersion(1) public ResponseObject findById(@RequestParam String id) { return ResponseResult.success(userService.getById(id)); } @@ -60,6 +64,7 @@ public class UserController { */ @ApiOperation(value = "", notes = "分页查询") @GetMapping("/page") + @ApiVersion(1) public ResponseObject> findPage(UserPageDto userPageDto) { IPage page = userService.findPage(userPageDto); return ResponseResult.success(page.getTotal(), page.getRecords()); @@ -75,13 +80,18 @@ public class UserController { */ @ApiOperation(value = "", notes = "通过id集合查询用户") @PostMapping("/findByIds") + @ApiVersion(1) public ResponseObject> findByIds(List ids) { return ResponseResult.success(userService.findByIds(ids)); } @ApiOperation(value = "", notes = "用户保存") @PutMapping("/saveUser") + @ApiVersion(1) public ResponseObject saveUser(@RequestBody @Validated UserDto userDto) { + if (userService.checkUser(userDto)) { + return ResponseResult.error(HttpCode.BAD_REQUEST, "该账号已存在"); + } return userService.saveUser(userDto); } } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserDto.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserDto.java index 6e3b1bc..8c5908e 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserDto.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserDto.java @@ -8,13 +8,16 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; +import java.util.Set; /** * @author zhuyijun @@ -25,48 +28,52 @@ import java.time.LocalDateTime; @NoArgsConstructor @Builder public class UserDto { + @ApiModelProperty(value = "主键id") private String id; + @ApiModelProperty(value = "账号(用户名)") @NotBlank(message = "账号不能为空") private String username; + @ApiModelProperty(value = "姓名") private String name; - + @ApiModelProperty(value = "年龄") private Integer age; - - private String avatar; - + @ApiModelProperty(value = "手机号") private String phone; - + @ApiModelProperty(value = "邮箱") private String email; - - private String inviteUserId; - + @ApiModelProperty(value = "状态") private Integer status; - - private Integer followNum; - - private Integer fansNum; - + @ApiModelProperty(value = "logo") + private String avatar; + @ApiModelProperty(value = "邀请人") + private String inviteUserId; + @ApiModelProperty(value = "是否删除 0未删除") private Integer deleted; - + @ApiModelProperty(value = "备注") private String description; - + @ApiModelProperty(value = "创建人") private String createUserId; + @ApiModelProperty(value = "创建时间") @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) @JSONField(format = CommonConstant.DATETIME_PATTERN) @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN) private LocalDateTime createTime; - + @ApiModelProperty(value = "编辑人") private String editUserId; - + @ApiModelProperty(value = "编辑时间") @JSONField(format = CommonConstant.DATETIME_PATTERN) @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = CommonConstant.DATETIME_PATTERN) @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime editTime; + @ApiModelProperty(value = "角色id集合") + @NotNull(message = "角色不能为空") + private Set roleIds; + @ApiModelProperty(value = "租户id") private String tenantId; } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserPageDto.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserPageDto.java index 29388f8..73e4c07 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserPageDto.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserPageDto.java @@ -1,26 +1,32 @@ package cn.zyjblogs.server.user.dto; import cn.zyjblogs.starter.common.entity.dto.PageDto; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; /** * 分页查询 * * @author zhuyijun */ +@ApiModel(description = "用户查询dto") @Data +@NoArgsConstructor public class UserPageDto extends PageDto { + @ApiModelProperty(value = "账号(用户名)") private String username; - + @ApiModelProperty(value = "姓名") private String name; - + @ApiModelProperty(value = "年龄") private Integer age; - + @ApiModelProperty(value = "手机号") private String phone; - + @ApiModelProperty(value = "邮箱") private String email; - + @ApiModelProperty(value = "状态") private Integer status; @Builder diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserRoleDto.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserRoleDto.java new file mode 100644 index 0000000..e44a22c --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/dto/UserRoleDto.java @@ -0,0 +1,31 @@ +package cn.zyjblogs.server.user.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author zhuyijun + */ +@ApiModel(description = "用户角色关联表") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("user_role") +public class UserRoleDto { + @ApiModelProperty(value = "主键id") + private String id; + @ApiModelProperty(value = "用户id") + private String userId; + @ApiModelProperty(value = "角色id") + private String roleId; + @ApiModelProperty(value = "租户id") + private String tenantId; +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/mapper/UserRoleMapper.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/mapper/UserRoleMapper.java new file mode 100644 index 0000000..65765dc --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/mapper/UserRoleMapper.java @@ -0,0 +1,12 @@ +package cn.zyjblogs.server.user.mapper; + +import cn.zyjblogs.server.user.po.UserRolePo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author zhuyijun + */ +@Mapper +public interface UserRoleMapper extends BaseMapper { +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserPo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserPo.java index 44a7f3d..d72900e 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserPo.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserPo.java @@ -57,12 +57,6 @@ public class UserPo implements Serializable { @TableField("status") private Integer status; - @TableField("follow_num") - private Integer followNum; - - @TableField("fans_num") - private Integer fansNum; - @TableField("deleted") private Integer deleted; diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserRolePo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserRolePo.java new file mode 100644 index 0000000..b709dc0 --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/po/UserRolePo.java @@ -0,0 +1,28 @@ +package cn.zyjblogs.server.user.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author zhuyijun + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("user_role") +public class UserRolePo { + @TableId("id") + private String id; + @TableField("user_id") + private String userId; + @TableField("role_id") + private String roleId; + @TableField("tenant_id") + private String tenantId; +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserRoleService.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserRoleService.java new file mode 100644 index 0000000..e722669 --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserRoleService.java @@ -0,0 +1,54 @@ +package cn.zyjblogs.server.user.service; + +import cn.zyjblogs.server.user.po.UserRolePo; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.Collection; +import java.util.List; + +/** + * @author zhuyijun + */ +public interface UserRoleService extends IService { + /** + * 保存或用户角色关联 + * + * @param userId 用户id + * @param roleIds 角色id集合 + * @param needClear 是否清除该用户旧关联 + * @return boolean + * @author zhuyijun + * @date 2022/9/23 下午11:10 + */ + boolean saveOrUpdate(String userId, Collection roleIds, boolean needClear); + + /** + * 通过用户id删除用户角色关联 + * + * @param userId 用户id + * @return int + * @author zhuyijun + * @date 2022/9/23 下午10:56 + */ + int deleteByUserId(String userId); + + /** + * 通过用户id集合删除用户角色关联 + * + * @param userIds 用户id集合 + * @return int + * @author zhuyijun + * @date 2022/9/23 下午10:56 + */ + int deleteByUserIds(Collection userIds); + + /** + * 通过用户id查询角色id + * + * @param userId 用户id + * @return int + * @author zhuyijun + * @date 2022/9/23 下午11:00 + */ + List findRoleListByUserId(String userId); +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserService.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserService.java index 8ac15e0..655ef2b 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserService.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/UserService.java @@ -41,4 +41,14 @@ public interface UserService extends IService { */ ResponseObject saveUser(@RequestBody UserDto userDto); + /** + * 检测账号是否存在 + * + * @param userDto + * @return boolean + * @author zhuyijun + * @date 2022/9/23 下午5:41 + */ + boolean checkUser(UserDto userDto); + } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserRoleServiceImpl.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..81267a0 --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,101 @@ +package cn.zyjblogs.server.user.service.impl; + +import cn.zyjblogs.server.user.mapper.UserRoleMapper; +import cn.zyjblogs.server.user.po.UserRolePo; +import cn.zyjblogs.server.user.service.UserRoleService; +import cn.zyjblogs.starter.common.entity.context.BaseContext; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author zhuyijun + */ +@Service +@RequiredArgsConstructor +public class UserRoleServiceImpl extends ServiceImpl implements UserRoleService { + private final UserRoleMapper userRoleMapper; + + /** + * 保存或用户角色关联 + * + * @param userId 用户id + * @param roleIds 角色id集合 + * @param needClear 是否清除该用户旧关联 + * @author zhuyijun + * @date 2022/9/23 下午11:10 + */ + @Transactional(rollbackFor = Exception.class) + @Override + public boolean saveOrUpdate(String userId, Collection roleIds, boolean needClear) { + if (needClear) { + deleteByUserId(userId); + } + List userRolePos = new ArrayList<>(roleIds.size()); + String tenantId = BaseContext.getTenantId(); + roleIds.forEach(roleId -> userRolePos.add(UserRolePo.builder() + .roleId(roleId) + .userId(userId) + .tenantId(tenantId) + .build())); + + return this.saveBatch(userRolePos); + } + + /** + * 通过用户id集合删除用户角色关联表 + * + * @param userId 用户id + * @author zhuyijun + * @date 2022/9/23 下午11:00 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteByUserId(String userId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); + queryWrapper.eq(UserRolePo::getUserId, userId) + .eq(UserRolePo::getTenantId, BaseContext.getTenantId()); + return userRoleMapper.delete(queryWrapper); + } + + /** + * 通过用户id集合删除用户角色关联表 + * + * @param userIds 用户id集合 + * @author zhuyijun + * @date 2022/9/23 下午11:00 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteByUserIds(Collection userIds) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); + queryWrapper.in(UserRolePo::getUserId, userIds) + .eq(UserRolePo::getTenantId, BaseContext.getTenantId()); + return userRoleMapper.delete(queryWrapper); + } + + /** + * 通过用户id查询角色id集合 + * + * @param userId 用户id + * @author zhuyijun + * @date 2022/9/23 下午11:00 + */ + @Override + public List findRoleListByUserId(String userId) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); + queryWrapper.select(UserRolePo::getRoleId) + .eq(UserRolePo::getUserId, userId) + .eq(UserRolePo::getTenantId, BaseContext.getTenantId()); + List userRolePos = userRoleMapper.selectList(queryWrapper); + return userRolePos.stream().map(UserRolePo::getRoleId).collect(Collectors.toList()); + } +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserServiceImpl.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserServiceImpl.java index d353faa..1b77dba 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserServiceImpl.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/service/impl/UserServiceImpl.java @@ -5,6 +5,7 @@ import cn.zyjblogs.server.user.dto.UserDto; import cn.zyjblogs.server.user.dto.UserPageDto; import cn.zyjblogs.server.user.mapper.UserMapper; import cn.zyjblogs.server.user.po.UserPo; +import cn.zyjblogs.server.user.service.UserRoleService; import cn.zyjblogs.server.user.service.UserService; import cn.zyjblogs.server.user.vo.UserVo; import cn.zyjblogs.starter.common.entity.context.BaseContext; @@ -17,6 +18,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.Collections; @@ -29,6 +31,7 @@ import java.util.List; @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl implements UserService { private final UserMapper userMapper; + private final UserRoleService userRoleService; /** * 分页查询 @@ -68,16 +71,15 @@ public class UserServiceImpl extends ServiceImpl implements * @date 2022/9/22 下午6:04 */ @Override + @Transactional(rollbackFor = Exception.class) public ResponseObject saveUser(UserDto userDto) { - if (checkUser(userDto)) { - return ResponseResult.error(HttpCode.BAD_REQUEST, "该账号已存在"); - } UserPo userPo = BeanUtils.map(userDto, UserPo.class); int count = userMapper.insert(userPo); if (count > 0) { + userRoleService.saveOrUpdate(userPo.getId(), userDto.getRoleIds(), false); return ResponseResult.success("用户创建成功"); } - return ResponseResult.error(HttpCode.BAD_REQUEST, "用户创建是失败"); + return ResponseResult.error(HttpCode.BAD_REQUEST, "用户创建成功"); } /** @@ -86,6 +88,7 @@ public class UserServiceImpl extends ServiceImpl implements * @param userDto * @return */ + @Override public boolean checkUser(UserDto userDto) { return userMapper.checkUserCount(userDto) > 0; } diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserRoleVo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserRoleVo.java new file mode 100644 index 0000000..7567578 --- /dev/null +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserRoleVo.java @@ -0,0 +1,29 @@ +package cn.zyjblogs.server.user.vo; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author zhuyijun + */ +@ApiModel(description = "用户角色关联表") +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@TableName("user_role") +public class UserRoleVo { + @ApiModelProperty(value = "主键id") + private String id; + @ApiModelProperty(value = "用户id") + private String userId; + @ApiModelProperty(value = "角色id") + private String roleId; + @ApiModelProperty(value = "租户id") + private String tenantId; +} diff --git a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserVo.java b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserVo.java index 2971a8f..d117869 100644 --- a/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserVo.java +++ b/server/zyjblogs-rbac/src/main/java/cn/zyjblogs/server/user/vo/UserVo.java @@ -4,11 +4,14 @@ import cn.zyjblogs.starter.common.entity.constant.CommonConstant; import com.alibaba.fastjson.annotation.JSONField; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import javax.validation.constraints.NotBlank; import java.io.Serializable; import java.time.LocalDateTime; @@ -19,46 +22,50 @@ import java.time.LocalDateTime; @AllArgsConstructor @NoArgsConstructor @Builder +@ApiModel(description = "用户vo类") public class UserVo implements Serializable { + @ApiModelProperty(value = "主键id") private String id; + @ApiModelProperty(value = "账号(用户名)") + @NotBlank(message = "账号不能为空") private String username; + @ApiModelProperty(value = "姓名") private String name; - + @ApiModelProperty(value = "年龄") private Integer age; - - private String avatar; - + @ApiModelProperty(value = "手机号") private String phone; - + @ApiModelProperty(value = "邮箱") private String email; - - private String inviteUserId; - + @ApiModelProperty(value = "状态") private Integer status; - - private Integer followNum; - - private Integer fansNum; - + @ApiModelProperty(value = "logo") + private String avatar; + @ApiModelProperty(value = "邀请人") + private String inviteUserId; + @ApiModelProperty(value = "是否删除 0未删除") private Integer deleted; - + @ApiModelProperty(value = "备注") private String description; - + @ApiModelProperty(value = "创建人") private String createUserId; + @ApiModelProperty(value = "创建时间") @JsonSerialize(using = LocalDateTimeSerializer.class) @JSONField(format = CommonConstant.DATETIME_PATTERN) private LocalDateTime createTime; + @ApiModelProperty(value = "编辑人") private String editUserId; - - @JsonSerialize(using = LocalDateTimeSerializer.class) + @ApiModelProperty(value = "编辑时间") @JSONField(format = CommonConstant.DATETIME_PATTERN) + @JsonSerialize(using = LocalDateTimeSerializer.class) private LocalDateTime editTime; + @ApiModelProperty(value = "租户id") private String tenantId; } diff --git a/server/zyjblogs-rbac/src/main/resources/bootstrap.yml b/server/zyjblogs-rbac/src/main/resources/bootstrap.yml index 7873535..c76a6c9 100644 --- a/server/zyjblogs-rbac/src/main/resources/bootstrap.yml +++ b/server/zyjblogs-rbac/src/main/resources/bootstrap.yml @@ -28,6 +28,73 @@ spring: password: ${spring.cloud.nacos.config.password} namespace: ${spring.cloud.nacos.config.namespace} group: public + shardingsphere: + datasource: + names: write-ds,read-ds-0 + write-ds: + jdbc-url: jdbc:mysql://127.0.0.1:3306/zyjblogs_rbac?allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: 123456 + connectionTimeoutMilliseconds: 3000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 50 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000\ + hikari: + minimum-idle: 10 + maximum-pool-size: 100 + auto-commit: true + idle-timeout: 1800000 + pool-name: DatebookHikariCP + max-lifetime: 1800000 + connection-timeout: 60000 + connection-test-query: SELECT 1 + read-ds-0: + jdbc-url: jdbc:mysql://127.0.0.1:3306/zyjblogs_rbac?allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + username: read + password: 123456 + connectionTimeoutMilliseconds: 3000 + idleTimeoutMilliseconds: 60000 + maxLifetimeMilliseconds: 1800000 + maxPoolSize: 50 + minPoolSize: 1 + maintenanceIntervalMilliseconds: 30000 + hikari: + minimum-idle: 10 + maximum-pool-size: 100 + auto-commit: true + idle-timeout: 1800000 + pool-name: DatebookHikariCP + max-lifetime: 1800000 + connection-timeout: 60000 + connection-test-query: SELECT 1 + sharding: + master-slave-rules: + master0: + master-data-source-name: write-ds + slave-data-source-names: read-ds-0 + # rules: + # readwrite-splitting: + # data-sources: + # readwrite_ds: + # static-strategy: + # write-data-source-name: write-ds + # read-data-source-names: + # - read-ds-0 + # # 负载均衡算法名称 + # load-balancer-name: roundRobin + # load-balancers: + # # 一共两种一种是 RANDOM(随机),一种是 ROUND_ROBIN(轮询) + # roundRobin: + # type: ROUND_ROBIN + props: + sql: + show: true logging: config: classpath:logback-spring.xml @@ -36,4 +103,7 @@ security: oauth2: client: client-id: ${spring.application.name} - client-secret: secret \ No newline at end of file + client-secret: secret + resource: + id: resourceId + diff --git a/server/zyjblogs-rbac/src/main/resources/mapper/mysql/role/RoleMapper.xml b/server/zyjblogs-rbac/src/main/resources/mapper/mysql/role/RoleMapper.xml index 3defc63..5b1305d 100644 --- a/server/zyjblogs-rbac/src/main/resources/mapper/mysql/role/RoleMapper.xml +++ b/server/zyjblogs-rbac/src/main/resources/mapper/mysql/role/RoleMapper.xml @@ -1,8 +1,15 @@ + + id,name,status,role_type,deleted,description, + create_user_id,create_time,edit_user_id, + edit_time,tenant_id + diff --git a/server/zyjblogs-rbac/src/main/resources/mapper/mysql/user/UserMapper.xml b/server/zyjblogs-rbac/src/main/resources/mapper/mysql/user/UserMapper.xml index b62c684..a0ed812 100644 --- a/server/zyjblogs-rbac/src/main/resources/mapper/mysql/user/UserMapper.xml +++ b/server/zyjblogs-rbac/src/main/resources/mapper/mysql/user/UserMapper.xml @@ -1,32 +1,9 @@ - - - - - - - - - - - - - - - - - - - - - - id,username,name,age,avatar,phone, - email,invite_user_id,status,follow_num, - fans_num,deleted,description,create_user_id, + email,invite_user_id,status,deleted,description,create_user_id, create_time,edit_user_id,edit_time,tenant_id \ No newline at end of file diff --git a/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/role/RoleMapper.xml b/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/role/RoleMapper.xml index 3defc63..5b1305d 100644 --- a/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/role/RoleMapper.xml +++ b/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/role/RoleMapper.xml @@ -1,8 +1,15 @@ + + id,name,status,role_type,deleted,description, + create_user_id,create_time,edit_user_id, + edit_time,tenant_id + diff --git a/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/user/UserMapper.xml b/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/user/UserMapper.xml index 2a52b75..2211795 100644 --- a/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/user/UserMapper.xml +++ b/server/zyjblogs-rbac/src/main/resources/mapper/postgresql/user/UserMapper.xml @@ -1,6 +1,11 @@ + + id,username,name,age,avatar,phone, + email,invite_user_id,status,deleted,description,create_user_id, + create_time,edit_user_id,edit_time,tenant_id + \ No newline at end of file diff --git a/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/AbstractBusinessException.java b/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/AbstractBusinessException.java index e463d42..a2f3b89 100644 --- a/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/AbstractBusinessException.java +++ b/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/AbstractBusinessException.java @@ -2,6 +2,9 @@ package cn.zyjblogs.starter.common.exception; import cn.zyjblogs.starter.common.entity.response.HttpCode; +/** + * @author zhuyijun + */ public class AbstractBusinessException extends RuntimeException { private static final long serialVersionUID = -6583471361241853199L; /** @@ -23,7 +26,7 @@ public class AbstractBusinessException extends RuntimeException { * 创建业务异常对象 * * @param responseCode 错误码 - * @param message 错误消息 + * @param message 错误消息 */ public AbstractBusinessException(HttpCode responseCode, String message) { super(message); diff --git a/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/CommonBusinessException.java b/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/CommonBusinessException.java new file mode 100644 index 0000000..18efaee --- /dev/null +++ b/stater/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/starter/common/exception/CommonBusinessException.java @@ -0,0 +1,18 @@ +package cn.zyjblogs.starter.common.exception; + +import cn.zyjblogs.starter.common.entity.response.HttpCode; + +/** + * 公共异常处理类 + * + * @author zhuyijun + */ +public class CommonBusinessExcetion extends AbstractBusinessException { + public CommonBusinessExcetion() { + super(); + } + + public CommonBusinessExcetion(HttpCode responseCode, String message) { + super(responseCode, message); + } +} diff --git a/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java b/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java index f893c12..420cf95 100644 --- a/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java +++ b/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java @@ -26,7 +26,7 @@ public class ResourceAuthenticationEntryPoint implements AuthenticationEntryPoin log.error("认证失败 {}", e.getMessage()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); OBJECT_MAPPER.writeValue(response.getOutputStream(), - ResponseResult.error(HttpCode.UNAUTHORIZED, "认证失败,token无效!")); + ResponseResult.error(HttpCode.UNAUTHORIZED, "认证失败!")); } } diff --git a/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java b/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java index ba66f5d..2597c48 100644 --- a/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java +++ b/stater/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java @@ -31,7 +31,8 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { - resources.resourceId(resourceId) + resources + .resourceId(resourceId) // 验证令牌的服务 .tokenStore(tokenStore) .stateless(true) diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersion.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersion.java new file mode 100644 index 0000000..97a3925 --- /dev/null +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersion.java @@ -0,0 +1,20 @@ +package cn.zyjblogs.starter.web.apiversion; + +import org.springframework.web.bind.annotation.Mapping; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author zhuyijun + */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Mapping +public @interface ApiVersion { + int value(); +} \ No newline at end of file diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionCondition.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionCondition.java new file mode 100644 index 0000000..d0e5189 --- /dev/null +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionCondition.java @@ -0,0 +1,49 @@ +package cn.zyjblogs.starter.web.apiversion; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.servlet.mvc.condition.RequestCondition; + +import javax.servlet.http.HttpServletRequest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author zhuyijun + */ +@Slf4j +public class ApiVersionCondition implements RequestCondition { + + private static final Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/"); + private int apiVersion; + + public ApiVersionCondition(int apiVersion) { + this.apiVersion = apiVersion; + } + + @Override + public ApiVersionCondition combine(ApiVersionCondition other) { + return new ApiVersionCondition(other.getApiVersion()); + } + + @Override + public ApiVersionCondition getMatchingCondition(HttpServletRequest request) { + Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI()); + if (m.find()) { + int version = Integer.parseInt(m.group(1)); + if (version >= this.apiVersion) { + return this; + } + } + + return null; + } + + @Override + public int compareTo(ApiVersionCondition other, HttpServletRequest request) { + return other.getApiVersion() - this.apiVersion; + } + + public int getApiVersion() { + return this.apiVersion; + } +} \ No newline at end of file diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionRequestMappingHandlerMapping.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionRequestMappingHandlerMapping.java new file mode 100644 index 0000000..af04b3c --- /dev/null +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/apiversion/ApiVersionRequestMappingHandlerMapping.java @@ -0,0 +1,38 @@ +package cn.zyjblogs.starter.web.apiversion; + +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.stereotype.Controller; +import org.springframework.web.servlet.mvc.condition.RequestCondition; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.lang.reflect.Method; + +/** + * @author zhuyijun + */ +public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping { + + @Override + protected boolean isHandler(Class beanType) { + return AnnotatedElementUtils.hasAnnotation(beanType, Controller.class); + } + + @Override + protected RequestCondition getCustomTypeCondition(Class handlerType) { + ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class); + return createCondition(apiVersion); + } + + @Override + protected RequestCondition getCustomMethodCondition(Method method) { + ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class); + return createCondition(apiVersion); + } + + private RequestCondition createCondition(ApiVersion apiVersion) { + return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value()); + } + +} + \ No newline at end of file diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/ApiVersionWebMvcAutoConfiguration.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/ApiVersionWebMvcAutoConfiguration.java new file mode 100644 index 0000000..76fefd1 --- /dev/null +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/ApiVersionWebMvcAutoConfiguration.java @@ -0,0 +1,18 @@ +package cn.zyjblogs.starter.web.autoconfig; + +import cn.zyjblogs.starter.web.apiversion.ApiVersionRequestMappingHandlerMapping; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * @author zhuyijun + */ +@Configuration +public class ApiVersionWebMvcAutoConfiguration extends WebMvcConfigurationSupport { + + @Override + public RequestMappingHandlerMapping createRequestMappingHandlerMapping() { + return new ApiVersionRequestMappingHandlerMapping(); + } +} \ No newline at end of file diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/GlobalExceptionHandlerAutoConfiguration.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/GlobalExceptionHandlerAutoConfiguration.java index 6af5091..d160708 100644 --- a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/GlobalExceptionHandlerAutoConfiguration.java +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/GlobalExceptionHandlerAutoConfiguration.java @@ -1,7 +1,6 @@ package cn.zyjblogs.starter.web.autoconfig; import cn.zyjblogs.starter.web.hander.GlobalExceptionHandler; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -15,7 +14,8 @@ public class GlobalExceptionHandlerAutoConfiguration { @ConditionalOnMissingBean( name = {"globalExceptionHandler"} ) - public GlobalExceptionHandler globalExceptionHandler(){ + public GlobalExceptionHandler globalExceptionHandler() { return new GlobalExceptionHandler(); } + } diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/Knife4jAutoConfigurationConfig.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/Knife4jAutoConfigurationConfig.java index 2f69274..2255f94 100644 --- a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/Knife4jAutoConfigurationConfig.java +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/autoconfig/Knife4jAutoConfigurationConfig.java @@ -1,14 +1,10 @@ package cn.zyjblogs.starter.web.autoconfig; import com.google.common.collect.Lists; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Value; -import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; @@ -23,19 +19,18 @@ import springfox.documentation.service.SecurityScheme; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider; -import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; -import java.lang.reflect.Field; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZonedDateTime; import java.util.Date; import java.util.List; -import java.util.stream.Collectors; +/** + * @author zhuyijun + */ @EnableOpenApi @Configuration @Import(BeanValidatorPluginsConfiguration.class) @@ -80,6 +75,7 @@ public class Knife4jAutoConfigurationConfig { @Bean(value = "defaultApi") public Docket defaultApi() { return new Docket(DocumentationType.SWAGGER_2) + .enable(true) .directModelSubstitute(LocalDateTime.class, Date.class) .directModelSubstitute(LocalDate.class, String.class) .directModelSubstitute(LocalTime.class, String.class) diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/exception/ApiVersionException.java b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/exception/ApiVersionException.java new file mode 100644 index 0000000..6888484 --- /dev/null +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/java/cn/zyjblogs/starter/web/exception/ApiVersionException.java @@ -0,0 +1,19 @@ +package cn.zyjblogs.starter.web.exception; + +import cn.zyjblogs.starter.common.exception.AbstractFrameworkException; + +/** + * 版本控制异常 + * + * @author zhuyijun + */ +public class ApiVersionException extends AbstractFrameworkException { + + public ApiVersionException(String message) { + super(message); + } + + public ApiVersionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/stater/zyjblogs-web-spring-boot-starter/src/main/resources/META-INF/spring.factories b/stater/zyjblogs-web-spring-boot-starter/src/main/resources/META-INF/spring.factories index 221ae97..a34bea2 100644 --- a/stater/zyjblogs-web-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/stater/zyjblogs-web-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ ## Auto Configure org.springframework.boot.cn.zyjblogs.starter.feign.autoconfigure.EnableAutoConfiguration=\ cn.zyjblogs.starter.web.autoconfig.GlobalExceptionHandlerAutoConfiguration,\ - cn.zyjblogs.starter.web.autoconfig.Knife4jAutoConfigurationConfig + cn.zyjblogs.starter.web.autoconfig.Knife4jAutoConfigurationConfig,\ + cn.zyjblogs.starter.web.autoconfig.ApiVersionWebMvcAutoConfiguration