From ddf106c2e6a6aac6a6a3a185a3f3db68249c484c Mon Sep 17 00:00:00 2001 From: LingandRX Date: Thu, 5 Jun 2025 22:44:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20-=20=E6=B7=BB=E5=8A=A0logback-spring.xm?= =?UTF-8?q?l=E9=85=8D=E7=BD=AE=20-=20=E6=B7=BB=E5=8A=A0GlobalExceptionHand?= =?UTF-8?q?ler=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=20-?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0JsonException=E5=92=8CPageException?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- .idea/dataSources.xml | 14 ++ .../asia/yulinling/workflow/WorkFlowMain.java | 11 +- .../yulinling/workflow/aspectj/AopLog.java | 1 - .../yulinling/workflow/constant/Status.java | 50 +++++++ .../workflow/controller/TestController.java | 15 +++ .../workflow/exception/BaseException.java | 32 +++++ .../workflow/exception/JsonException.java | 24 ++++ .../workflow/exception/PageException.java | 23 ++++ .../handler/GlobalExceptionHandler.java | 52 ++++++++ .../yulinling/workflow/mapper/UserMapper.java | 2 +- .../yulinling/workflow/model/ApiResponse.java | 125 ++++++++++++++++++ .../workflow/{ => model}/entity/User.java | 2 +- src/main/resources/logback-spring.xml | 62 +++++++++ src/main/resources/templates/error.html | 11 ++ .../workflow/mapper/UserMapperTest.java | 2 +- 16 files changed, 423 insertions(+), 6 deletions(-) create mode 100644 src/main/java/asia/yulinling/workflow/constant/Status.java create mode 100644 src/main/java/asia/yulinling/workflow/exception/BaseException.java create mode 100644 src/main/java/asia/yulinling/workflow/exception/JsonException.java create mode 100644 src/main/java/asia/yulinling/workflow/exception/PageException.java create mode 100644 src/main/java/asia/yulinling/workflow/handler/GlobalExceptionHandler.java create mode 100644 src/main/java/asia/yulinling/workflow/model/ApiResponse.java rename src/main/java/asia/yulinling/workflow/{ => model}/entity/User.java (95%) create mode 100644 src/main/resources/logback-spring.xml create mode 100644 src/main/resources/templates/error.html diff --git a/.gitignore b/.gitignore index 5ff6309..702ebff 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ build/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store +/logs/ diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 928d353..143c39f 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -13,5 +13,19 @@ $ProjectFileDir$ + + mysql.8 + true + true + $PROJECT_DIR$/src/main/resources/application.properties + com.mysql.cj.jdbc.Driver + jdbc:mysql://122.152.201.90:9912/workflow?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT + + + + + + $ProjectFileDir$ + \ No newline at end of file diff --git a/src/main/java/asia/yulinling/workflow/WorkFlowMain.java b/src/main/java/asia/yulinling/workflow/WorkFlowMain.java index dd8b718..ee8de92 100644 --- a/src/main/java/asia/yulinling/workflow/WorkFlowMain.java +++ b/src/main/java/asia/yulinling/workflow/WorkFlowMain.java @@ -1,12 +1,21 @@ package asia.yulinling.workflow; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication +@Slf4j public class WorkFlowMain { public static void main(String[] args) { - SpringApplication.run(WorkFlowMain.class, args); + ConfigurableApplicationContext context = SpringApplication.run(WorkFlowMain.class, args); + int length = context.getBeanDefinitionCount(); + log.trace("Number of beans in application context: " + length); + log.debug("Number of beans in application context: " + length); + log.info("Number of beans in application context: " + length); + log.warn("Number of beans in application context: " + length); + log.error("Number of beans in application context: " + length); } } \ No newline at end of file diff --git a/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java b/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java index a4c1d36..af608d4 100644 --- a/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java +++ b/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java @@ -4,7 +4,6 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.json.JSONUtil; -import cn.hutool.log.Log; import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/asia/yulinling/workflow/constant/Status.java b/src/main/java/asia/yulinling/workflow/constant/Status.java new file mode 100644 index 0000000..c1dd399 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/constant/Status.java @@ -0,0 +1,50 @@ +package asia.yulinling.workflow.constant; + +import lombok.Getter; + +/** + *

+ * 状态码封装 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@Getter +public enum Status { + /** 操作成功 */ + OK(200, "success"), + + /** 未知异常 */ + UNKNOWN_ERROR(500, "Unknown error"); + + /** + * 状态码 + */ + private final Integer code; + + /** + * 内容 + */ + private final String message; + + Status(Integer code, String message) { + this.code = code; + this.message = message; + } + + /** + * 根据code反查枚举 + * + * @param code 状态码 + * @return Status + */ + public static Status fromCode(int code) { + for (Status status : Status.values()) { + if (status.getCode().equals(code)) { + return status; + } + } + return UNKNOWN_ERROR; + } +} diff --git a/src/main/java/asia/yulinling/workflow/controller/TestController.java b/src/main/java/asia/yulinling/workflow/controller/TestController.java index 0543736..cc6f692 100644 --- a/src/main/java/asia/yulinling/workflow/controller/TestController.java +++ b/src/main/java/asia/yulinling/workflow/controller/TestController.java @@ -1,5 +1,9 @@ package asia.yulinling.workflow.controller; +import asia.yulinling.workflow.constant.Status; +import asia.yulinling.workflow.exception.JsonException; +import asia.yulinling.workflow.exception.PageException; +import asia.yulinling.workflow.model.ApiResponse; import cn.hutool.core.lang.Dict; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; @@ -43,4 +47,15 @@ public class TestController { log.info(jsonStr); return Dict.create().set("json", jsonStr); } + + @GetMapping("/json") + public ApiResponse jsonException() { + throw new JsonException(Status.UNKNOWN_ERROR); + } + + @GetMapping("/page") + public ApiResponse PageException() { + throw new PageException(Status.UNKNOWN_ERROR); + } + } diff --git a/src/main/java/asia/yulinling/workflow/exception/BaseException.java b/src/main/java/asia/yulinling/workflow/exception/BaseException.java new file mode 100644 index 0000000..a20a574 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/exception/BaseException.java @@ -0,0 +1,32 @@ +package asia.yulinling.workflow.exception; + +import asia.yulinling.workflow.constant.Status; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 异常基类 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class BaseException extends RuntimeException{ + private final Integer code; + private final String message; + + public BaseException(Status status) { + super(status.getMessage()); + this.code = status.getCode(); + this.message = status.getMessage(); + } + + public BaseException(Integer code, String message) { + super(message); + this.code = code; + this.message = message; + } +} diff --git a/src/main/java/asia/yulinling/workflow/exception/JsonException.java b/src/main/java/asia/yulinling/workflow/exception/JsonException.java new file mode 100644 index 0000000..91ae02b --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/exception/JsonException.java @@ -0,0 +1,24 @@ +package asia.yulinling.workflow.exception; + +import asia.yulinling.workflow.constant.Status; +import lombok.Getter; + +/** + *

+ * JSON异常 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@Getter +public class JsonException extends BaseException { + + public JsonException(Status status) { + super(status); + } + + public JsonException(Integer code, String message) { + super(code, message); + } +} diff --git a/src/main/java/asia/yulinling/workflow/exception/PageException.java b/src/main/java/asia/yulinling/workflow/exception/PageException.java new file mode 100644 index 0000000..8d8c3f4 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/exception/PageException.java @@ -0,0 +1,23 @@ +package asia.yulinling.workflow.exception; + +import asia.yulinling.workflow.constant.Status; +import lombok.Getter; + +/** + *

+ * 页面异常 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@Getter +public class PageException extends BaseException { + public PageException(Status status) { + super(status); + } + + public PageException(Integer code, String message) { + super(code, message); + } +} diff --git a/src/main/java/asia/yulinling/workflow/handler/GlobalExceptionHandler.java b/src/main/java/asia/yulinling/workflow/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..dc40aae --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/handler/GlobalExceptionHandler.java @@ -0,0 +1,52 @@ +package asia.yulinling.workflow.handler; + +import asia.yulinling.workflow.exception.JsonException; +import asia.yulinling.workflow.exception.PageException; +import asia.yulinling.workflow.model.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +/** + *

+ * 全局异常处理 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@ControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + private static final String DEFAULT_ERROR_VIEW = "error"; + + /** + * 统一 json 异常处理 + * + * @param e JsonException + * @return 统一返回 json 格式 + */ + @ExceptionHandler(Exception.class) + @ResponseBody + public ApiResponse jsonErrorHandler(JsonException e) { + log.error(e.getMessage()); + return ApiResponse.ofException(e); + } + + /** + * 统一 页面 异常处理 + * + * @param e PageException + * @return 统一跳转到异常页面 + */ + @ExceptionHandler(PageException.class) + public ModelAndView pageErrorHandler(PageException e) { + log.error(e.getMessage()); + ModelAndView view = new ModelAndView(); + view.addObject("exception", e); + view.setViewName(DEFAULT_ERROR_VIEW); + return view; + } +} diff --git a/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java b/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java index 5afb11c..b5a65f9 100644 --- a/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java +++ b/src/main/java/asia/yulinling/workflow/mapper/UserMapper.java @@ -1,6 +1,6 @@ package asia.yulinling.workflow.mapper; -import asia.yulinling.workflow.entity.User; +import asia.yulinling.workflow.model.entity.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; diff --git a/src/main/java/asia/yulinling/workflow/model/ApiResponse.java b/src/main/java/asia/yulinling/workflow/model/ApiResponse.java new file mode 100644 index 0000000..a603977 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/model/ApiResponse.java @@ -0,0 +1,125 @@ +package asia.yulinling.workflow.model; + +import asia.yulinling.workflow.constant.Status; +import asia.yulinling.workflow.exception.BaseException; +import lombok.Data; + +/** + *

+ * 通用API接口封装 + *

+ * + * @author yulinling + * @since 2025/6/5 + */ +@Data +public class ApiResponse { + /** + * 状态码 + */ + private Integer code; + + /** + * 返回内容 + */ + private String message; + + /** + * 返回数据 + */ + private Object data; + + /** + * 无参构造器 + */ + private ApiResponse() {} + + /** + * 全参构造器 + * + * @param code 状态码 + * @param message 返回内容 + * @param data 返回数据 + */ + private ApiResponse(Integer code, String message, Object data) { + this.code = code; + this.message = message; + this.data = data; + } + + /** + * 构造一个自定义的Api返回 + * + * @param code 状态码 + * @param message 返回内容 + * @param data 返回数据 + * @return ApiResponse + */ + public static ApiResponse of(Integer code, String message, Object data) { + return new ApiResponse(code, message, data); + } + + /** + * 构造一个成功且带数据的Api返回 + * + * @param data 返回数据 + * @return ApiResponse + */ + public static ApiResponse ofSuccess(Object data) { + return ofStatus(Status.OK, data); + } + + /** + * 构造一个成功且自定义数据的Api返回 + * + * @param message 返回内容 + * @return ApiResponse + */ + public static ApiResponse ofMessage(String message) { + return ofStatus(Status.OK, message); + } + + /** + * 构造一个有状态不带数据的Api返回 + * + * @param status 状态{@link Status} + * @return ApiResponse + */ + public static ApiResponse ofStatus(Status status) { + return ofStatus(status, null); + } + + /** + * 构造一个有状态且带数据的Api返回 + * + * @param status 状态{@link Status} + * @param data 返回数据 + * @return ApiResponse + */ + public static ApiResponse ofStatus(Status status, Object data) { + return of(status.getCode(), status.getMessage(), data); + } + + + /** + * 构造一个异常且带数据的Api返回 + * + * @param t 异常 + * @param data 返回数据 + * @return ApiResponse + * @param {@link BaseException} 子类 + */ + public static ApiResponse ofException(T t, Object data) { + return of(t.getCode(), t.getMessage(), data); + } + /** + * 构造一个异常且不带数据的Api返回 + * + * @param t 异常 + * @return ApiResponse + * @param {@link BaseException} 子类 + */ + public static ApiResponse ofException(T t) { + return ofException(t, null); + } +} diff --git a/src/main/java/asia/yulinling/workflow/entity/User.java b/src/main/java/asia/yulinling/workflow/model/entity/User.java similarity index 95% rename from src/main/java/asia/yulinling/workflow/entity/User.java rename to src/main/java/asia/yulinling/workflow/model/entity/User.java index f1a2c4d..9a4a8a5 100644 --- a/src/main/java/asia/yulinling/workflow/entity/User.java +++ b/src/main/java/asia/yulinling/workflow/model/entity/User.java @@ -1,4 +1,4 @@ -package asia.yulinling.workflow.entity; +package asia.yulinling.workflow.model.entity; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..9df9757 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + + + + ${LOG_PATH}/info.log + + ERROR + DENY + ACCEPT + + + ${LOG_PATH}/info.%d{yyyy-MM-dd}.%i.log + 2MB + 30 + 1GB + + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + + + + ${LOG_PATH}/error.log + + ERROR + + + ${LOG_PATH}/error.%d{yyyy-MM-dd}.%i.log + 2MB + 30 + 1GB + + + ${LOG_PATTERN} + ${LOG_CHARSET} + + + + + + + + + + + diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html new file mode 100644 index 0000000..0794d8e --- /dev/null +++ b/src/main/resources/templates/error.html @@ -0,0 +1,11 @@ + + + + + 统一页面异常处理 + + +

统一页面异常处理

+
+ + \ No newline at end of file diff --git a/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java b/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java index a4892f6..4e95a0b 100644 --- a/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java +++ b/src/test/java/asia/yulinling/workflow/mapper/UserMapperTest.java @@ -1,7 +1,7 @@ package asia.yulinling.workflow.mapper; import asia.yulinling.workflow.WorkFlowMainTests; -import asia.yulinling.workflow.entity.User; +import asia.yulinling.workflow.model.entity.User; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.util.IdUtil;