diff --git a/README.md b/README.md index 9814cb8..bb9e126 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,9 @@ flowchart LR demo-service-aaa-->demo-common demo-service-bbb-->demo-common - demo-service-bbb-->demo-sdk - demo-common-->demo-core - demo-sdk--> demo-core ``` - demo - - demo-core - - demo-sdk - demo-common - demo-service - demo-service-aaa @@ -40,16 +35,11 @@ flowchart LR demo 是一个系统的顶级POM,其 parent 为公司的顶级POM,对系统内部的依赖进行管理。 -demo-service 下是该系统的全部后端服务,每一个子模块对应一个后端服务。最终发布为一个 Docker 镜像。 +demo-service 下是该系统的全部后端服务,每一个子模块对应一个后端服务。 demo-service 的 POM 中添加所有服务的公共依赖,如 spring-boot-starter-web、mybatis-spring-boot-starter 等。 demo-common 中为该系统内服务的公共配置、公共接口、异常定义等。 -demo-sdk 是各服务之间相互调用的 SDK,最终发布为一个 jar 包。 -当 aaa 服务需要调用 bbb 服务时,则引入 demo-sdk 依赖,并使用其中的 BbbClient 进行调用。 - -demo-core 包含本系统内使用的 util 和服务间通信模型 DTO。 - ### 包结构 XxxService 是该包的逻辑组织中枢。 @@ -76,10 +66,6 @@ XxxRepository 是对 XxxMapper 的封装。 在 application-local.yml 中修改配置,其中的配置项会覆盖 application.yml,但不会提交到 git。 -### 项目发布 - -通过 jib-maven-plugin 发布 Docker 镜像到镜像仓库。 - ### 线上部署 将 opentelemetry-javaagent.jar 映射到容器中的 /opt/agent 目录。 diff --git a/common/pom.xml b/common/pom.xml index 28970bf..108196d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -18,11 +18,6 @@ - - net.rzdata - demo-core - 5.1.0-SNAPSHOT - org.springframework.boot spring-boot-starter-web diff --git a/core/src/main/java/net/rzdata/domain/Id.java b/common/src/main/java/net/rzdata/demo/core/domain/Id.java similarity index 73% rename from core/src/main/java/net/rzdata/domain/Id.java rename to common/src/main/java/net/rzdata/demo/core/domain/Id.java index 2c4aa5b..db01afa 100644 --- a/core/src/main/java/net/rzdata/domain/Id.java +++ b/common/src/main/java/net/rzdata/demo/core/domain/Id.java @@ -1,4 +1,4 @@ -package net.rzdata.domain; +package net.rzdata.demo.core.domain; public record Id(String id) { diff --git a/common/src/main/java/net/rzdata/demo/exception/GlobalExceptionHandler.java b/common/src/main/java/net/rzdata/demo/exception/GlobalExceptionHandler.java index 40a1ca3..ecb6658 100644 --- a/common/src/main/java/net/rzdata/demo/exception/GlobalExceptionHandler.java +++ b/common/src/main/java/net/rzdata/demo/exception/GlobalExceptionHandler.java @@ -3,162 +3,161 @@ package net.rzdata.demo.exception; import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.exception.NotPermissionException; import cn.dev33.satoken.exception.NotRoleException; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpStatus; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; -import net.rzdata.domain.Result; -import net.rzdata.exception.ClientException; -import net.rzdata.exception.ServerException; -import net.rzdata.exception.ThirdPartyException; +import net.rzdata.demo.core.domain.R; +import net.rzdata.demo.core.exception.ServiceException; +import net.rzdata.demo.core.exception.base.BaseException; +import net.rzdata.demo.core.utils.StreamUtils; import org.springframework.context.support.DefaultMessageSourceResolvable; -import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingPathVariableException; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; - -import java.util.stream.Collectors; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; /** - * 全局异常处理 + * 全局异常处理器 + * + * @author Lion Li */ @Slf4j +@RestControllerAdvice public class GlobalExceptionHandler { - protected final transient String errorMessage = "系统错误,请联系系统管理员"; - /** * 权限码异常 */ @ExceptionHandler(NotPermissionException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) - public Result handleNotPermissionException(NotPermissionException e, HttpServletRequest request) { + public R handleNotPermissionException(NotPermissionException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage()); - ClientException ce = new ClientException("没有访问权限,请联系管理员授权", e); - return Result.fail(ce); + return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权"); } /** * 角色权限异常 */ @ExceptionHandler(NotRoleException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) - public Result handleNotRoleException(NotRoleException e, HttpServletRequest request) { + public R handleNotRoleException(NotRoleException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage()); - ClientException ce = new ClientException("没有访问权限,请联系管理员授权", e); - return Result.fail(ce); + return R.fail(HttpStatus.HTTP_FORBIDDEN, "没有访问权限,请联系管理员授权"); } /** * 认证失败 */ @ExceptionHandler(NotLoginException.class) - @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Result handleNotLoginException(NotLoginException e, HttpServletRequest request) { + public R handleNotLoginException(NotLoginException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); - ClientException ce = new ClientException("没有访问权限,请联系管理员授权", e); - return Result.fail(ce); + return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源"); } /** * 请求方式不支持 */ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { + public R handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); - ServerException se = new ServerException("请求方式不支持", e); - return Result.fail(se, errorMessage); + return R.fail(e.getMessage()); } - @ExceptionHandler(ClientException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleClientException(ClientException e) { - log.error("客户端异常: {}", e.getMessage(), e); - return Result.fail(e); + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public R handleServiceException(ServiceException e, HttpServletRequest request) { + log.error(e.getMessage()); + Integer code = e.getCode(); + return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage()); } - @ExceptionHandler(ServerException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleServerException(ServerException e) { - log.error("服务端异常: {}", e.getMessage(), e); - return Result.fail(e, errorMessage); + /** + * 业务异常 + */ + @ExceptionHandler(BaseException.class) + public R handleBaseException(BaseException e, HttpServletRequest request) { + log.error(e.getMessage()); + return R.fail(e.getMessage()); } - @ExceptionHandler(ThirdPartyException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleThirdPartyException(ThirdPartyException e) { - log.error("第三方服务异常: {}", e.getMessage(), e); - return Result.fail(e, errorMessage); + /** + * 请求路径中缺少必需的路径变量 + */ + @ExceptionHandler(MissingPathVariableException.class) + public R handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI); + return R.fail(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName())); + } + + /** + * 请求参数类型不匹配 + */ + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI); + return R.fail(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue())); } /** * 拦截未知的运行时异常 */ @ExceptionHandler(RuntimeException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleRuntimeException(RuntimeException e, HttpServletRequest request) { + public R handleRuntimeException(RuntimeException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生未知异常.", requestURI, e); - ServerException se = new ServerException(errorMessage, e); - return Result.fail(se); + return R.fail(e.getMessage()); } /** * 系统异常 */ @ExceptionHandler(Exception.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleException(Exception e, HttpServletRequest request) { + public R handleException(Exception e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生系统异常.", requestURI, e); - ServerException se = new ServerException(errorMessage, e); - return Result.fail(se); + return R.fail(e.getMessage()); } /** * 自定义验证异常 */ @ExceptionHandler(BindException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleBindException(BindException e) { - log.error(e.getMessage(), e); - String message = e.getAllErrors().parallelStream() - .map(DefaultMessageSourceResolvable::getDefaultMessage) - .collect(Collectors.joining(", ")); - ClientException ce = new ClientException(message, e); - return Result.fail(ce); + public R handleBindException(BindException e) { + log.error(e.getMessage()); + String message = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", "); + return R.fail(message); } /** * 自定义验证异常 */ @ExceptionHandler(ConstraintViolationException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result constraintViolationException(ConstraintViolationException e) { - log.error(e.getMessage(), e); - String message = e.getConstraintViolations().parallelStream() - .map(ConstraintViolation::getMessage) - .collect(Collectors.joining(", ")); - ClientException ce = new ClientException(message, e); - return Result.fail(ce); + public R constraintViolationException(ConstraintViolationException e) { + log.error(e.getMessage()); + String message = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ", "); + return R.fail(message); } /** * 自定义验证异常 */ @ExceptionHandler(MethodArgumentNotValidException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - log.error(e.getMessage(), e); + public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + log.error(e.getMessage()); String message = e.getBindingResult().getFieldError().getDefaultMessage(); - ClientException ce = new ClientException(message, e); - return Result.fail(ce); + return R.fail(message); } } diff --git a/core/src/main/java/net/rzdata/trait/IConverter.java b/common/src/main/java/net/rzdata/demo/trait/IConverter.java similarity index 82% rename from core/src/main/java/net/rzdata/trait/IConverter.java rename to common/src/main/java/net/rzdata/demo/trait/IConverter.java index 94679f4..7afe46f 100644 --- a/core/src/main/java/net/rzdata/trait/IConverter.java +++ b/common/src/main/java/net/rzdata/demo/trait/IConverter.java @@ -1,4 +1,4 @@ -package net.rzdata.trait; +package net.rzdata.demo.trait; /** * 实体转换类 diff --git a/core/src/main/java/net/rzdata/trait/IQuery.java b/common/src/main/java/net/rzdata/demo/trait/IQuery.java similarity index 77% rename from core/src/main/java/net/rzdata/trait/IQuery.java rename to common/src/main/java/net/rzdata/demo/trait/IQuery.java index b2f891e..faa8344 100644 --- a/core/src/main/java/net/rzdata/trait/IQuery.java +++ b/common/src/main/java/net/rzdata/demo/trait/IQuery.java @@ -1,4 +1,4 @@ -package net.rzdata.trait; +package net.rzdata.demo.trait; /** * 请求实体类 diff --git a/core/pom.xml b/core/pom.xml deleted file mode 100644 index 474f2ff..0000000 --- a/core/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - net.rzdata - demo - 5.1.0-SNAPSHOT - - demo-core - jar - - - 17 - 17 - UTF-8 - - - - - org.projectlombok - lombok - provided - - - diff --git a/core/src/main/java/net/rzdata/domain/Result.java b/core/src/main/java/net/rzdata/domain/Result.java deleted file mode 100644 index 65e4a47..0000000 --- a/core/src/main/java/net/rzdata/domain/Result.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.rzdata.domain; - -import lombok.*; -import net.rzdata.exception.BaseException; - -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor(access = AccessLevel.PROTECTED) -public class Result { - - public static final String SUCCESS_CODE = "00000"; - public static final String SUCCESS_MESSAGE = "操作成功"; - - private String code; - private String message; - private T data; - - public static Result ok() { - return new Result<>(SUCCESS_CODE, SUCCESS_MESSAGE, null); - } - - public static Result ok(T data) { - return new Result<>(SUCCESS_CODE, SUCCESS_MESSAGE, data); - } - - public static Result fail(BaseException e) { - return new Result<>(e.getCode(), e.getMessage(), null); - } - - public static Result fail(BaseException e, T data) { - return new Result<>(e.getCode(), e.getMessage(), data); - } - - public static Result fail(BaseException e, String message) { - return new Result<>(e.getCode(), message, null); - } - - public static Result fail(BaseException e, String message, T data) { - return new Result<>(e.getCode(), message, data); - } -} diff --git a/core/src/main/java/net/rzdata/exception/BaseException.java b/core/src/main/java/net/rzdata/exception/BaseException.java deleted file mode 100644 index 48c21cf..0000000 --- a/core/src/main/java/net/rzdata/exception/BaseException.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.rzdata.exception; - -public abstract sealed class BaseException extends RuntimeException - permits ClientException, ServerException, ThirdPartyException { - - private final String code; - - protected BaseException(String code, String message) { - super(message); - this.code = code; - } - - protected BaseException(String code, String message, Throwable cause) { - super(message, cause); - this.code = code; - } - - public String getCode() { - return this.code; - } -} diff --git a/core/src/main/java/net/rzdata/exception/ClientException.java b/core/src/main/java/net/rzdata/exception/ClientException.java deleted file mode 100644 index 0a63d41..0000000 --- a/core/src/main/java/net/rzdata/exception/ClientException.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.rzdata.exception; - -/** - * 客户端异常 - */ -public non-sealed class ClientException extends BaseException { - - public static final String CLIENT_ERROR_CODE = "A0001"; - - public ClientException(String message) { - super(CLIENT_ERROR_CODE, message); - } - - public ClientException(String message, Throwable cause) { - super(CLIENT_ERROR_CODE, message, cause); - } - - protected ClientException(String code, String message) { - super(code, message); - } - - protected ClientException(String code, String message, Throwable cause) { - super(code, message, cause); - } -} diff --git a/core/src/main/java/net/rzdata/exception/ServerException.java b/core/src/main/java/net/rzdata/exception/ServerException.java deleted file mode 100644 index f436288..0000000 --- a/core/src/main/java/net/rzdata/exception/ServerException.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.rzdata.exception; - -/** - * 服务端异常 - */ -public non-sealed class ServerException extends BaseException { - - public static final String SERVER_ERROR_CODE = "B0001"; - - public ServerException(String message) { - super(SERVER_ERROR_CODE, message); - } - - public ServerException(String message, Throwable cause) { - super(SERVER_ERROR_CODE, message, cause); - } - - protected ServerException(String code, String message) { - super(code, message); - } - - protected ServerException(String code, String message, Throwable cause) { - super(code, message, cause); - } -} diff --git a/core/src/main/java/net/rzdata/exception/ThirdPartyException.java b/core/src/main/java/net/rzdata/exception/ThirdPartyException.java deleted file mode 100644 index dc287e3..0000000 --- a/core/src/main/java/net/rzdata/exception/ThirdPartyException.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.rzdata.exception; - -/** - * 第三方服务异常 - */ -public non-sealed class ThirdPartyException extends BaseException { - - public static final String THIRD_PARTY_ERROR_CODE = "C0001"; - - public ThirdPartyException(String message) { - super(THIRD_PARTY_ERROR_CODE, message); - } - - public ThirdPartyException(String message, Throwable cause) { - super(THIRD_PARTY_ERROR_CODE, message, cause); - } - - protected ThirdPartyException(String code, String message) { - super(code, message); - } - - protected ThirdPartyException(String code, String message, Throwable cause) { - super(code, message, cause); - } -} diff --git a/pom.xml b/pom.xml index 3f167bb..f91a35f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,6 @@ service common - core