From 9d49cea7204e36b0ae0d63932a3ae1259e48a2a3 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Sun, 9 Feb 2025 19:07:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(openFeign):=20=E5=8A=A0=E5=85=A5OpenFeign?= =?UTF-8?q?=E5=86=85=3D=E5=86=85=E5=AE=B9=E5=92=8C=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common-service/pom.xml | 36 ++++ .../src/main/java/cn/bunny/App.java | 13 ++ .../exception/GlobalExceptionHandler.java | 126 +++++++++++++ common/pom.xml | 25 +++ dao/pom.xml | 43 +++++ .../dao/constant/LocalDateTimeConstant.java | 11 ++ .../cn/bunny/dao/constant/MinioConstant.java | 35 ++++ .../bunny/dao/constant/RedisUserConstant.java | 28 +++ .../cn/bunny/dao/constant/UserConstant.java | 9 + .../java/cn/bunny/dao/entity/BaseEntity.java | 41 +++++ .../cn/bunny/dao/entity/BaseUserEntity.java | 18 ++ .../bunny/dao/enums/EmailTemplateEnums.java | 21 +++ .../java/cn/bunny/dao/enums/JobEnums.java | 20 ++ .../main/java/cn/bunny/dao/vo/BaseUserVo.java | 18 ++ dao/src/main/java/cn/bunny/dao/vo/BaseVo.java | 49 +++++ .../cn/bunny/dao/vo/result/PageResult.java | 34 ++++ .../java/cn/bunny/dao/vo/result/Result.java | 173 ++++++++++++++++++ .../bunny/dao/vo/result/ResultCodeEnum.java | 90 +++++++++ pom.xml | 16 ++ .../main/java/cn/bunny/Cloud1Application.java | 2 + .../java/cn/bunny/config/Knife4jConfig.java | 33 ++++ .../cn/bunny/controller/CloudController.java | 30 +++ .../java/cn/bunny/feign/CloudFeignClient.java | 15 ++ .../src/main/resources/application-cloud.yml | 7 - .../src/main/resources/application-dev.yml | 11 ++ .../src/main/resources/application-prod.yml | 11 ++ .../src/main/resources/application-test.yml | 11 ++ .../src/main/resources/application.yml | 5 +- .../main/java/cn/bunny/Cloud2Application.java | 2 + .../java/cn/bunny/config/Knife4jConfig.java | 33 ++++ .../cn/bunny/controller/CloudController.java | 30 +++ .../java/cn/bunny/feign/CloudFeignClient.java | 11 ++ .../src/main/resources/application-cloud.yml | 32 +++- .../src/main/resources/application.yml | 3 +- service/pom.xml | 15 ++ 35 files changed, 1045 insertions(+), 12 deletions(-) create mode 100644 common/common-service/pom.xml create mode 100644 common/common-service/src/main/java/cn/bunny/App.java create mode 100644 common/common-service/src/main/java/cn/bunny/exception/GlobalExceptionHandler.java create mode 100644 common/pom.xml create mode 100644 dao/pom.xml create mode 100644 dao/src/main/java/cn/bunny/dao/constant/LocalDateTimeConstant.java create mode 100644 dao/src/main/java/cn/bunny/dao/constant/MinioConstant.java create mode 100644 dao/src/main/java/cn/bunny/dao/constant/RedisUserConstant.java create mode 100644 dao/src/main/java/cn/bunny/dao/constant/UserConstant.java create mode 100644 dao/src/main/java/cn/bunny/dao/entity/BaseEntity.java create mode 100644 dao/src/main/java/cn/bunny/dao/entity/BaseUserEntity.java create mode 100644 dao/src/main/java/cn/bunny/dao/enums/EmailTemplateEnums.java create mode 100644 dao/src/main/java/cn/bunny/dao/enums/JobEnums.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/BaseUserVo.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/BaseVo.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/result/PageResult.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/result/Result.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/result/ResultCodeEnum.java create mode 100644 service/cloud-demo1/src/main/java/cn/bunny/config/Knife4jConfig.java create mode 100644 service/cloud-demo1/src/main/java/cn/bunny/controller/CloudController.java create mode 100644 service/cloud-demo1/src/main/java/cn/bunny/feign/CloudFeignClient.java delete mode 100644 service/cloud-demo1/src/main/resources/application-cloud.yml create mode 100644 service/cloud-demo1/src/main/resources/application-prod.yml create mode 100644 service/cloud-demo1/src/main/resources/application-test.yml create mode 100644 service/cloud-demo2/src/main/java/cn/bunny/config/Knife4jConfig.java create mode 100644 service/cloud-demo2/src/main/java/cn/bunny/controller/CloudController.java create mode 100644 service/cloud-demo2/src/main/java/cn/bunny/feign/CloudFeignClient.java diff --git a/common/common-service/pom.xml b/common/common-service/pom.xml new file mode 100644 index 0000000..4256d59 --- /dev/null +++ b/common/common-service/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + cn.bunny + common + 0.0.1-SNAPSHOT + + + common-service + jar + + common-service + https://maven.apache.org + + + UTF-8 + + + + + cn.bunny + dao + 0.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + annotationProcessor + + + diff --git a/common/common-service/src/main/java/cn/bunny/App.java b/common/common-service/src/main/java/cn/bunny/App.java new file mode 100644 index 0000000..d56e7f2 --- /dev/null +++ b/common/common-service/src/main/java/cn/bunny/App.java @@ -0,0 +1,13 @@ +package cn.bunny; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + } +} diff --git a/common/common-service/src/main/java/cn/bunny/exception/GlobalExceptionHandler.java b/common/common-service/src/main/java/cn/bunny/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..658ec68 --- /dev/null +++ b/common/common-service/src/main/java/cn/bunny/exception/GlobalExceptionHandler.java @@ -0,0 +1,126 @@ +package cn.bunny.exception; + +import cn.bunny.dao.vo.result.Result; +import cn.bunny.dao.vo.result.ResultCodeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.nio.file.AccessDeniedException; +import java.sql.SQLIntegrityConstraintViolationException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + // 运行时异常信息 + @ExceptionHandler(RuntimeException.class) + @ResponseBody + public Result exceptionHandler(RuntimeException exception) { + String message = exception.getMessage(); + + // 解析异常 + String jsonParseError = "JSON parse error (.*)"; + Matcher jsonParseErrorMatcher = Pattern.compile(jsonParseError).matcher(message); + if (jsonParseErrorMatcher.find()) { + return Result.error(null, 500, "JSON解析异常 " + jsonParseErrorMatcher.group(1)); + } + + // 数据过大 + String dataTooLongError = "Data too long for column (.*?) at row 1"; + Matcher dataTooLongErrorMatcher = Pattern.compile(dataTooLongError).matcher(message); + if (dataTooLongErrorMatcher.find()) { + return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大"); + } + + // 主键冲突 + String primaryKeyError = "Duplicate entry '(.*?)' for key .*"; + Matcher primaryKeyErrorMatcher = Pattern.compile(primaryKeyError).matcher(message); + if (primaryKeyErrorMatcher.find()) { + return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在"); + } + + // corn表达式错误 + String cronExpression = "CronExpression '(.*?)' is invalid"; + Matcher cronExpressionMatcher = Pattern.compile(cronExpression).matcher(message); + if (cronExpressionMatcher.find()) { + return Result.error(null, 500, "表达式 " + cronExpressionMatcher.group(1) + " 不合法"); + } + + log.error("GlobalExceptionHandler===>运行时异常信息:{}", message); + exception.printStackTrace(); + return Result.error(null, 500, "服务器异常"); + } + + // 捕获系统异常 + @ExceptionHandler(Exception.class) + @ResponseBody + public Result error(Exception exception) { + log.error("捕获系统异常:{}", exception.getMessage()); + log.error("GlobalExceptionHandler===>系统异常信息:{}", (Object) exception.getStackTrace()); + + // 错误消息 + String message = exception.getMessage(); + + // 匹配到内容 + String patternString = "Request method '(\\w+)' is not supported"; + Matcher matcher = Pattern.compile(patternString).matcher(message); + if (matcher.find()) return Result.error(null, 500, "请求方法错误,不是 " + matcher.group(1) + "类型请求"); + + // 请求API不存在 + String noStaticResource = "No static resource (.*)\\."; + Matcher noStaticResourceMatcher = Pattern.compile(noStaticResource).matcher(message); + if (noStaticResourceMatcher.find()) + return Result.error(null, 500, "请求API不存在 " + noStaticResourceMatcher.group(1)); + + // 返回错误内容 + return Result.error(null, 500, "系统异常"); + } + + // 表单验证字段 + @ExceptionHandler(MethodArgumentNotValidException.class) + public Result handleValidationExceptions(MethodArgumentNotValidException ex) { + String errorMessage = ex.getBindingResult().getFieldErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", ")); + return Result.error(null, 201, errorMessage); + } + + // 特定异常处理 + @ExceptionHandler(ArithmeticException.class) + @ResponseBody + public Result error(ArithmeticException exception) { + log.error("GlobalExceptionHandler===>特定异常信息:{}", exception.getMessage()); + + return Result.error(null, 500, exception.getMessage()); + } + + // spring security异常 + @ExceptionHandler(AccessDeniedException.class) + @ResponseBody + public Result error(AccessDeniedException exception) throws AccessDeniedException { + log.error("GlobalExceptionHandler===>spring security异常:{}", exception.getMessage()); + + return Result.error(ResultCodeEnum.SERVICE_ERROR); + } + + // 处理SQL异常 + @ExceptionHandler(SQLIntegrityConstraintViolationException.class) + @ResponseBody + public Result exceptionHandler(SQLIntegrityConstraintViolationException exception) { + log.error("GlobalExceptionHandler===>处理SQL异常:{}", exception.getMessage()); + + String message = exception.getMessage(); + if (message.contains("Duplicate entry")) { + // 错误信息 + return Result.error(ResultCodeEnum.USER_IS_EMPTY); + } else { + return Result.error(ResultCodeEnum.UNKNOWN_EXCEPTION); + } + } +} diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..8704908 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + + cn.bunny + cloud1 + 0.0.1-SNAPSHOT + + + common-service + + common + pom + + common + https://maven.apache.org + + + UTF-8 + + + + + + diff --git a/dao/pom.xml b/dao/pom.xml new file mode 100644 index 0000000..e101b09 --- /dev/null +++ b/dao/pom.xml @@ -0,0 +1,43 @@ + + 4.0.0 + + cn.bunny + cloud1 + 0.0.1-SNAPSHOT + + + dao + jar + + model + https://maven.apache.org + + + UTF-8 + + + + + + org.projectlombok + lombok + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + + + + com.alibaba.fastjson2 + fastjson2 + + + + io.swagger + swagger-annotations + 1.6.14 + + + diff --git a/dao/src/main/java/cn/bunny/dao/constant/LocalDateTimeConstant.java b/dao/src/main/java/cn/bunny/dao/constant/LocalDateTimeConstant.java new file mode 100644 index 0000000..158a036 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/constant/LocalDateTimeConstant.java @@ -0,0 +1,11 @@ +package cn.bunny.dao.constant; + +import lombok.Data; + +@Data +public class LocalDateTimeConstant { + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_SS_SLASH = "yyyy/MM/dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_SS_UNDERLINE = "yyyy_MM_dd_HH_mm_ss_SSS"; +} diff --git a/dao/src/main/java/cn/bunny/dao/constant/MinioConstant.java b/dao/src/main/java/cn/bunny/dao/constant/MinioConstant.java new file mode 100644 index 0000000..21dd2c5 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/constant/MinioConstant.java @@ -0,0 +1,35 @@ +package cn.bunny.dao.constant; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class MinioConstant { + public static final String favicon = "favicon"; + public static final String avatar = "avatar"; + public static final String message = "message"; + public static final String carousel = "carousel"; + public static final String feedback = "feedback"; + public static final String backup = "backup"; + public static final Map typeMap = new HashMap<>(); + + static { + typeMap.put(favicon, "/favicon/"); + typeMap.put(avatar, "/avatar/"); + typeMap.put(message, "/message/"); + typeMap.put(carousel, "/carousel/"); + typeMap.put(feedback, "/feedback/"); + typeMap.put(backup, "/backup/"); + typeMap.put("images", "/images/"); + typeMap.put("video", "/video/"); + typeMap.put("default", "/default/"); + } + + public static String getType(String type) { + String value = typeMap.get(type); + if (value != null) return value; + throw new RuntimeException("上传类型错误或缺失"); + } +} diff --git a/dao/src/main/java/cn/bunny/dao/constant/RedisUserConstant.java b/dao/src/main/java/cn/bunny/dao/constant/RedisUserConstant.java new file mode 100644 index 0000000..6cc314e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/constant/RedisUserConstant.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.constant; + +import lombok.Data; + +/** + * Redis用户前缀设置 + */ +@Data +public class RedisUserConstant { + // 过期时间 + public static final Long REDIS_EXPIRATION_TIME = 7L;// 7 天/分钟 Redis过期 + public static final Integer Cookie_EXPIRATION_TIME = 5 * 60 * 60;// cookies 过期时间 5 分钟 + public static final String WEB_CONFIG_KEY = "webConfig::platformConfig";// web配置 + + private static final String ADMIN_LOGIN_INFO_PREFIX = "admin::login_info::"; + private static final String ADMIN_EMAIL_CODE_PREFIX = "admin::email_code::"; + private static final String USER_LOGIN_INFO_PREFIX = "user::login_info::"; + private static final String USER_EMAIL_CODE_PREFIX = "user::email_code::"; + + public static String getAdminLoginInfoPrefix(String adminUser) { + return ADMIN_LOGIN_INFO_PREFIX + adminUser; + } + + public static String getAdminUserEmailCodePrefix(String adminUser) { + return ADMIN_EMAIL_CODE_PREFIX + adminUser; + } + +} diff --git a/dao/src/main/java/cn/bunny/dao/constant/UserConstant.java b/dao/src/main/java/cn/bunny/dao/constant/UserConstant.java new file mode 100644 index 0000000..5fe7066 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/constant/UserConstant.java @@ -0,0 +1,9 @@ +package cn.bunny.dao.constant; + +import lombok.Data; + +@Data +public class UserConstant { + public static final String USER_AVATAR = "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132"; + public static final String PERSON_DESCRIPTION = "这个人很懒没有介绍..."; +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/BaseEntity.java b/dao/src/main/java/cn/bunny/dao/entity/BaseEntity.java new file mode 100644 index 0000000..88430da --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/BaseEntity.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@Schema(name = "BaseEntity", title = "基础信息字段", description = "基础信息字段") +public class BaseEntity implements Serializable { + + @Schema(name = "id", title = "唯一标识") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @Schema(name = "createTime", title = "创建时间") + private LocalDateTime createTime; + + @Schema(name = "updateTime", title = "更新时间") + private LocalDateTime updateTime; + + @Schema(name = "createUser", title = "创建用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long createUser; + + @Schema(name = "updateUser", title = "操作用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long updateUser; + + @Schema(name = "isDeleted", title = "是否被删除") + private Boolean isDeleted; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/BaseUserEntity.java b/dao/src/main/java/cn/bunny/dao/entity/BaseUserEntity.java new file mode 100644 index 0000000..da9de85 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/BaseUserEntity.java @@ -0,0 +1,18 @@ +package cn.bunny.dao.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(name = "BaseUserEntity", title = "基础信息字段包含用户信息", description = "基础信息字段包含用户信息") +public class BaseUserEntity extends BaseEntity { + + @Schema(name = "username", title = "用户名") + private String createUsername; + + @Schema(name = "nickname", title = "昵称") + private String updateUsername; + +} diff --git a/dao/src/main/java/cn/bunny/dao/enums/EmailTemplateEnums.java b/dao/src/main/java/cn/bunny/dao/enums/EmailTemplateEnums.java new file mode 100644 index 0000000..ad841b8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/enums/EmailTemplateEnums.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.enums; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema(description = "Email Template Types") +public enum EmailTemplateEnums { + VERIFICATION_CODE("verification_code", "邮箱验证码发送"), + NOTIFICATION("notification", "通知型邮件"), + WARNING("warning", "警告型邮件"), + ; + + private final String type; + private final String summary; + + EmailTemplateEnums(String type, String summary) { + this.type = type; + this.summary = summary; + } +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/enums/JobEnums.java b/dao/src/main/java/cn/bunny/dao/enums/JobEnums.java new file mode 100644 index 0000000..370c704 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/enums/JobEnums.java @@ -0,0 +1,20 @@ +package cn.bunny.dao.enums; + +import lombok.Getter; + +@Getter +public enum JobEnums { + FINISH("finish", "完成"), + UNFINISHED("unfinished", "未完成"), + RUNNING("running", "正在运行"), + ERROR("error", "错误"), + ; + + private final String type; + private final String summary; + + JobEnums(String type, String summary) { + this.type = type; + this.summary = summary; + } +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/BaseUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/BaseUserVo.java new file mode 100644 index 0000000..c14c5ec --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/BaseUserVo.java @@ -0,0 +1,18 @@ +package cn.bunny.dao.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(name = "BaseVo", title = "基础返回对象内容包含用户信息", description = "基础返回对象内容包含用户信息") +public class BaseUserVo extends BaseVo { + + @Schema(name = "username", title = "用户名") + private String createUsername; + + @Schema(name = "nickname", title = "昵称") + private String updateUsername; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/BaseVo.java b/dao/src/main/java/cn/bunny/dao/vo/BaseVo.java new file mode 100644 index 0000000..0ba9a58 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/BaseVo.java @@ -0,0 +1,49 @@ +package cn.bunny.dao.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@Schema(name = "BaseVo", title = "基础返回对象内容", description = "基础返回对象内容") +public class BaseVo implements Serializable { + + @Schema(name = "id", title = "主键") + @JsonProperty("id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "updateTime", title = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime updateTime; + + @Schema(name = "createTime", title = "发布时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime createTime; + + @Schema(name = "createUser", title = "创建用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long createUser; + + @Schema(name = "updateUser", title = "操作用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long updateUser; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/result/PageResult.java b/dao/src/main/java/cn/bunny/dao/vo/result/PageResult.java new file mode 100644 index 0000000..aeb883c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/result/PageResult.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.vo.result; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 封装分页查询结果 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PageResult 对象", title = "分页返回结果", description = "分页返回结果") +public class PageResult implements Serializable { + + @Schema(name = "pageNo", title = "当前页") + private Long pageNo; + + @Schema(name = "pageSize", title = "每页记录数") + private Long pageSize; + + @Schema(name = "total", title = "总记录数") + private Long total; + + @Schema(name = "list", title = "当前页数据集合") + private List list; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/result/Result.java b/dao/src/main/java/cn/bunny/dao/vo/result/Result.java new file mode 100644 index 0000000..cb74d9f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/result/Result.java @@ -0,0 +1,173 @@ +package cn.bunny.dao.vo.result; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Result { + // 状态码 + private Integer code; + // 返回消息 + private String message; + // 返回数据 + private T data; + + /** + * * 自定义返回体 + * + * @param data 返回体 + * @return Result + */ + protected static Result build(T data) { + Result result = new Result<>(); + result.setData(data); + return result; + } + + /** + * * 自定义返回体,使用ResultCodeEnum构建 + * + * @param body 返回体 + * @param codeEnum 返回状态码 + * @return Result + */ + public static Result build(T body, ResultCodeEnum codeEnum) { + Result result = build(body); + result.setCode(codeEnum.getCode()); + result.setMessage(codeEnum.getMessage()); + return result; + } + + /** + * * 自定义返回体 + * + * @param body 返回体 + * @param code 返回状态码 + * @param message 返回消息 + * @return Result + */ + public static Result build(T body, Integer code, String message) { + Result result = build(body); + result.setCode(code); + result.setMessage(message); + result.setData(null); + return result; + } + + /** + * * 操作成功 + * + * @return Result + */ + public static Result success() { + return success(null, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功 + * + * @param data baseCategory1List + */ + public static Result success(T data) { + return build(data, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功-状态码 + * + * @param codeEnum 状态码 + */ + public static Result success(ResultCodeEnum codeEnum) { + return success(null, codeEnum); + } + + /** + * * 操作成功-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result success(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result success(T data, String message) { + return build(data, 200, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result success(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败 + */ + public static Result error() { + return Result.build(null); + } + + /** + * * 操作失败-自定义返回数据 + * + * @param data 返回体 + */ + public static Result error(T data) { + return build(data, ResultCodeEnum.FAIL); + } + + /** + * * 操作失败-状态码 + * + * @param codeEnum 状态码 + */ + public static Result error(ResultCodeEnum codeEnum) { + return build(null, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result error(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result error(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result error(T data, String message) { + return build(null, 500, message); + } +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/result/ResultCodeEnum.java b/dao/src/main/java/cn/bunny/dao/vo/result/ResultCodeEnum.java new file mode 100644 index 0000000..9bc0fee --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/result/ResultCodeEnum.java @@ -0,0 +1,90 @@ +package cn.bunny.dao.vo.result; + +import lombok.Getter; + +/** + * 统一返回结果状态信息类 + */ +@Getter +public enum ResultCodeEnum { + // 成功操作 200 + SUCCESS(200, "操作成功"), + ADD_SUCCESS(200, "添加成功"), + UPDATE_SUCCESS(200, "修改成功"), + DELETE_SUCCESS(200, "删除成功"), + SORT_SUCCESS(200, "排序成功"), + SUCCESS_UPLOAD(200, "上传成功"), + SUCCESS_LOGOUT(200, "退出成功"), + LOGOUT_SUCCESS(200, "退出成功"), + EMAIL_CODE_REFRESH(200, "邮箱验证码已刷新"), + EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"), + + // 验证错误 201 + USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"), + EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"), + SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"), + EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"), + LOGIN_ERROR(201, "账号或密码错误"), + LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"), + GET_BUCKET_EXCEPTION(201, "获取文件信息失败"), + SEND_MAIL_CODE_ERROR(201, "邮件发送失败"), + EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"), + EMAIL_EXIST(201, "邮箱已存在"), + REQUEST_IS_EMPTY(201, "请求数据为空"), + DATA_TOO_LARGE(201, "请求数据为空"), + UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD(201, "新密码与密码相同"), + + // 数据相关 206 + ILLEGAL_REQUEST(206, "非法请求"), + REPEAT_SUBMIT(206, "重复提交"), + DATA_ERROR(206, "数据异常"), + EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_USER_IS_EMPTY(206, "关联邮件用户配置为空"), + DATA_EXIST(206, "数据已存在"), + DATA_NOT_EXIST(206, "数据不存在"), + ALREADY_USER_EXCEPTION(206, "用户已存在"), + USER_IS_EMPTY(206, "用户不存在"), + FILE_NOT_EXIST(206, "文件不存在"), + NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"), + MISSING_TEMPLATE_FILES(206, "缺少模板文件"), + + // 身份过期 208 + LOGIN_AUTH(208, "请先登陆"), + AUTHENTICATION_EXPIRED(208, "身份验证过期"), + SESSION_EXPIRATION(208, "会话过期"), + + // 209 + THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"), + + // 提示错误 + UPDATE_ERROR(216, "修改失败"), + URL_ENCODE_ERROR(216, "URL编码失败"), + ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"), + FETCH_USERINFO_ERROR(219, "获取用户信息失败"), + ILLEGAL_DATA_REQUEST(219, "非法数据请求"), + CLASS_NOT_FOUND(219, "类名不存在"), + ADMIN_ROLE_CAN_NOT_DELETED(219, "无法删除admin角色"), + ROUTER_RANK_NEED_LARGER_THAN_THE_PARENT(219, "设置路由等级需要大于或等于父级的路由等级"), + + // 无权访问 403 + FAIL_NO_ACCESS_DENIED(403, "无权访问"), + FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"), + TOKEN_PARSING_FAILED(403, "token解析失败"), + FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"), + + // 系统错误 500 + UNKNOWN_EXCEPTION(500, "服务异常"), + SERVICE_ERROR(500, "服务异常"), + UPLOAD_ERROR(500, "上传失败"), + FAIL(500, "失败"), + ; + + private final Integer code; + private final String message; + + ResultCodeEnum(Integer code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 742c4df..2938d55 100644 --- a/pom.xml +++ b/pom.xml @@ -17,10 +17,14 @@ cloud1 service + common + dao 17 + 4.5.0 + 2.0.47 @@ -46,6 +50,18 @@ pom import + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j.version} + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson2.version} + diff --git a/service/cloud-demo1/src/main/java/cn/bunny/Cloud1Application.java b/service/cloud-demo1/src/main/java/cn/bunny/Cloud1Application.java index b74e1e4..3aaf5b0 100644 --- a/service/cloud-demo1/src/main/java/cn/bunny/Cloud1Application.java +++ b/service/cloud-demo1/src/main/java/cn/bunny/Cloud1Application.java @@ -3,7 +3,9 @@ package cn.bunny; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +@EnableFeignClients// 开启服务调用 @EnableDiscoveryClient// 开启服务发现 @SpringBootApplication public class Cloud1Application { diff --git a/service/cloud-demo1/src/main/java/cn/bunny/config/Knife4jConfig.java b/service/cloud-demo1/src/main/java/cn/bunny/config/Knife4jConfig.java new file mode 100644 index 0000000..acf29df --- /dev/null +++ b/service/cloud-demo1/src/main/java/cn/bunny/config/Knife4jConfig.java @@ -0,0 +1,33 @@ +package cn.bunny.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +public class Knife4jConfig { + @Bean + public OpenAPI openAPI() { + // 作者等信息 + Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://z-bunny.cn"); + // 使用协议 + License license = new License().name("MIT").url("https://MUT.com"); + // 相关信息 + Info info = new Info().title("Bunny-Order").description("权限管理模板").version("v1.0.0").contact(contact).license(license).termsOfService("MIT"); + + return new OpenAPI().info(info).externalDocs(new ExternalDocumentation()); + } + + // 管理员相关分类接口 + @Bean + public GroupedOpenApi groupedOpenAdminApi() { + return GroupedOpenApi.builder().group("默认请求接口").pathsToMatch("/api/**").build(); + } +} diff --git a/service/cloud-demo1/src/main/java/cn/bunny/controller/CloudController.java b/service/cloud-demo1/src/main/java/cn/bunny/controller/CloudController.java new file mode 100644 index 0000000..ead5330 --- /dev/null +++ b/service/cloud-demo1/src/main/java/cn/bunny/controller/CloudController.java @@ -0,0 +1,30 @@ +package cn.bunny.controller; + +import cn.bunny.feign.CloudFeignClient; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Tag(name = "云服务接口", description = "云服务接口") +@RequestMapping("/api") +public class CloudController { + + @Autowired + private CloudFeignClient cloudFeignClient; + + @Operation(summary = "本体接口调用", description = "feignCloud2") + @GetMapping("feignCloud1") + public String getFeignCloud1(Long id) { + return "feignCloud1:" + id; + } + + @Operation(summary = "调用服务2中接口", description = "feignByCloud2") + @GetMapping("feignByCloud2") + public String feignByCloud2(Long id) { + return cloudFeignClient.getFeignCloud2(id); + } +} diff --git a/service/cloud-demo1/src/main/java/cn/bunny/feign/CloudFeignClient.java b/service/cloud-demo1/src/main/java/cn/bunny/feign/CloudFeignClient.java new file mode 100644 index 0000000..92bf00e --- /dev/null +++ b/service/cloud-demo1/src/main/java/cn/bunny/feign/CloudFeignClient.java @@ -0,0 +1,15 @@ +package cn.bunny.feign; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Component +@FeignClient(value = "service-cloud2", path = "/api") +public interface CloudFeignClient { + + // 调用时如果请求类型不同需要考虑加上 @RequestParam + @GetMapping("feignCloud2") + String getFeignCloud2(@RequestParam Long id); +} diff --git a/service/cloud-demo1/src/main/resources/application-cloud.yml b/service/cloud-demo1/src/main/resources/application-cloud.yml deleted file mode 100644 index b36f046..0000000 --- a/service/cloud-demo1/src/main/resources/application-cloud.yml +++ /dev/null @@ -1,7 +0,0 @@ -spring: - cloud: - nacos: - server-addr: 192.168.3.132 - config: - import-check: - enabled: false diff --git a/service/cloud-demo1/src/main/resources/application-dev.yml b/service/cloud-demo1/src/main/resources/application-dev.yml index e69de29..d304bba 100644 --- a/service/cloud-demo1/src/main/resources/application-dev.yml +++ b/service/cloud-demo1/src/main/resources/application-dev.yml @@ -0,0 +1,11 @@ +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + cloud: + nacos: + server-addr: 192.168.3.132 + config: + import-check: + enabled: false \ No newline at end of file diff --git a/service/cloud-demo1/src/main/resources/application-prod.yml b/service/cloud-demo1/src/main/resources/application-prod.yml new file mode 100644 index 0000000..d304bba --- /dev/null +++ b/service/cloud-demo1/src/main/resources/application-prod.yml @@ -0,0 +1,11 @@ +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + cloud: + nacos: + server-addr: 192.168.3.132 + config: + import-check: + enabled: false \ No newline at end of file diff --git a/service/cloud-demo1/src/main/resources/application-test.yml b/service/cloud-demo1/src/main/resources/application-test.yml new file mode 100644 index 0000000..d304bba --- /dev/null +++ b/service/cloud-demo1/src/main/resources/application-test.yml @@ -0,0 +1,11 @@ +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + cloud: + nacos: + server-addr: 192.168.3.132 + config: + import-check: + enabled: false \ No newline at end of file diff --git a/service/cloud-demo1/src/main/resources/application.yml b/service/cloud-demo1/src/main/resources/application.yml index 2de9588..a60fd10 100644 --- a/service/cloud-demo1/src/main/resources/application.yml +++ b/service/cloud-demo1/src/main/resources/application.yml @@ -3,7 +3,6 @@ server: spring: application: - name: cloud-demo1 + name: service-cloud1 profiles: - include: - - cloud + active: dev diff --git a/service/cloud-demo2/src/main/java/cn/bunny/Cloud2Application.java b/service/cloud-demo2/src/main/java/cn/bunny/Cloud2Application.java index f10a3af..13d3a95 100644 --- a/service/cloud-demo2/src/main/java/cn/bunny/Cloud2Application.java +++ b/service/cloud-demo2/src/main/java/cn/bunny/Cloud2Application.java @@ -3,7 +3,9 @@ package cn.bunny; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +@EnableFeignClients// 开启服务调用 @EnableDiscoveryClient @SpringBootApplication public class Cloud2Application { diff --git a/service/cloud-demo2/src/main/java/cn/bunny/config/Knife4jConfig.java b/service/cloud-demo2/src/main/java/cn/bunny/config/Knife4jConfig.java new file mode 100644 index 0000000..acf29df --- /dev/null +++ b/service/cloud-demo2/src/main/java/cn/bunny/config/Knife4jConfig.java @@ -0,0 +1,33 @@ +package cn.bunny.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +public class Knife4jConfig { + @Bean + public OpenAPI openAPI() { + // 作者等信息 + Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://z-bunny.cn"); + // 使用协议 + License license = new License().name("MIT").url("https://MUT.com"); + // 相关信息 + Info info = new Info().title("Bunny-Order").description("权限管理模板").version("v1.0.0").contact(contact).license(license).termsOfService("MIT"); + + return new OpenAPI().info(info).externalDocs(new ExternalDocumentation()); + } + + // 管理员相关分类接口 + @Bean + public GroupedOpenApi groupedOpenAdminApi() { + return GroupedOpenApi.builder().group("默认请求接口").pathsToMatch("/api/**").build(); + } +} diff --git a/service/cloud-demo2/src/main/java/cn/bunny/controller/CloudController.java b/service/cloud-demo2/src/main/java/cn/bunny/controller/CloudController.java new file mode 100644 index 0000000..2b759a6 --- /dev/null +++ b/service/cloud-demo2/src/main/java/cn/bunny/controller/CloudController.java @@ -0,0 +1,30 @@ +package cn.bunny.controller; + +import cn.bunny.feign.CloudFeignClient; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Tag(name = "云服务接口", description = "云服务接口") +@RequestMapping("/api") +public class CloudController { + + @Autowired + private CloudFeignClient cloudFeignClient; + + @Operation(summary = "本体接口调用", description = "feignCloud2") + @GetMapping("feignCloud2") + public String getFeignCloud2(Long id) { + return "feign:" + id; + } + + @Operation(summary = "调用服务1中接口", description = "feignByCloud1") + @GetMapping("feignByCloud1") + public String feignByCloud1(Long id) { + return cloudFeignClient.getFeignCloud1(id); + } +} diff --git a/service/cloud-demo2/src/main/java/cn/bunny/feign/CloudFeignClient.java b/service/cloud-demo2/src/main/java/cn/bunny/feign/CloudFeignClient.java new file mode 100644 index 0000000..e194ab6 --- /dev/null +++ b/service/cloud-demo2/src/main/java/cn/bunny/feign/CloudFeignClient.java @@ -0,0 +1,11 @@ +package cn.bunny.feign; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient(value = "service-cloud1") +public interface CloudFeignClient { + + @GetMapping("feignCloud1") + String getFeignCloud1(Long id); +} diff --git a/service/cloud-demo2/src/main/resources/application-cloud.yml b/service/cloud-demo2/src/main/resources/application-cloud.yml index 43744ed..bcbdea3 100644 --- a/service/cloud-demo2/src/main/resources/application-cloud.yml +++ b/service/cloud-demo2/src/main/resources/application-cloud.yml @@ -4,4 +4,34 @@ spring: server-addr: 192.168.3.132 config: import-check: - enabled: false \ No newline at end of file + enabled: false +# 后期其实可以将这些配置写入单独的开发环境中 +--- +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + activate: + on-profile: dev +--- + +--- +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + activate: + on-profile: prod +--- + +--- +spring: + config: + import: + - nacos:common.yml?group=order + - nacos:database.yml?group=order + activate: + on-profile: test +--- diff --git a/service/cloud-demo2/src/main/resources/application.yml b/service/cloud-demo2/src/main/resources/application.yml index 4633b17..352e0bc 100644 --- a/service/cloud-demo2/src/main/resources/application.yml +++ b/service/cloud-demo2/src/main/resources/application.yml @@ -2,8 +2,9 @@ server: port: 8001 spring: application: - name: cloud-demo2 + name: service-cloud2 profiles: + active: dev include: - cloud cloud: diff --git a/service/pom.xml b/service/pom.xml index 8cdc05c..2d7cd45 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -21,6 +21,12 @@ + + cn.bunny + common-service + 0.0.1-SNAPSHOT + + org.springframework.boot spring-boot-starter-web @@ -71,5 +77,14 @@ org.springframework.cloud spring-cloud-starter-loadbalancer + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter +