Compare commits
2 Commits
d689a39a98
...
3eb651e039
| Author | SHA1 | Date | |
|---|---|---|---|
| 3eb651e039 | |||
| 531d99b3df |
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -8,8 +8,12 @@
|
|||||||
<processorPath useClasspath="false">
|
<processorPath useClasspath="false">
|
||||||
<entry name="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.42/8365263844ebb62398e0dc33057ba10ba472d3b8/lombok-1.18.42.jar" />
|
<entry name="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.42/8365263844ebb62398e0dc33057ba10ba472d3b8/lombok-1.18.42.jar" />
|
||||||
</processorPath>
|
</processorPath>
|
||||||
<module name="weblog-springboot.weblog-web.main" />
|
|
||||||
<module name="weblog-springboot.weblog-web.test" />
|
<module name="weblog-springboot.weblog-web.test" />
|
||||||
|
<module name="weblog-springboot.weblog-module-admin.test" />
|
||||||
|
<module name="weblog-springboot.weblog-module-common.test" />
|
||||||
|
<module name="weblog-springboot.weblog-module-admin.main" />
|
||||||
|
<module name="weblog-springboot.weblog-module-common.main" />
|
||||||
|
<module name="weblog-springboot.weblog-web.main" />
|
||||||
</profile>
|
</profile>
|
||||||
</annotationProcessing>
|
</annotationProcessing>
|
||||||
<bytecodeTargetLevel target="21" />
|
<bytecodeTargetLevel target="21" />
|
||||||
|
|||||||
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -3,8 +3,8 @@
|
|||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/weblog-springboot.iml" filepath="$PROJECT_DIR$/weblog-springboot.iml" />
|
<module fileurl="file://$PROJECT_DIR$/weblog-springboot.iml" filepath="$PROJECT_DIR$/weblog-springboot.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-module-common/weblog-springboot.weblog-module-common.main.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.main.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.test.iml" filepath="$PROJECT_DIR$/.idea/modules/weblog-web/weblog-springboot.weblog-web.test.iml" />
|
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
|
// Spring Boot 插件:声明,但不应用到父工程
|
||||||
id("org.springframework.boot") version "3.5.8" apply false
|
id("org.springframework.boot") version "3.5.8" apply false
|
||||||
id("io.spring.dependency-management") version "1.1.7" apply false
|
|
||||||
|
// Spring 的 dependency-management 插件:父工程和子工程都需要
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.hanserwei"
|
group = "com.hanserwei"
|
||||||
version = "0.0.1-SNAPSHOT"
|
version = "0.0.1-SNAPSHOT"
|
||||||
description = "weblog-springboot"
|
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
@@ -14,12 +16,6 @@ java {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "com.hanserwei"
|
group = "com.hanserwei"
|
||||||
version = "0.0.1-SNAPSHOT"
|
version = "0.0.1-SNAPSHOT"
|
||||||
@@ -30,15 +26,28 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
|
||||||
apply(plugin = "java")
|
apply(plugin = "java")
|
||||||
apply(plugin = "io.spring.dependency-management")
|
apply(plugin = "io.spring.dependency-management")
|
||||||
|
|
||||||
java.sourceCompatibility = JavaVersion.VERSION_21
|
java.sourceCompatibility = JavaVersion.VERSION_21
|
||||||
java.targetCompatibility = JavaVersion.VERSION_21
|
java.targetCompatibility = JavaVersion.VERSION_21
|
||||||
|
|
||||||
|
// ========= 统一版本管理(类似 Maven dependencyManagement)=========
|
||||||
|
dependencyManagement {
|
||||||
|
imports {
|
||||||
|
// Spring Boot 官方 BOM(最重要,统一管理绝大部分依赖版本)
|
||||||
|
mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
|
// Lombok (compileOnly + annotationProcessor)
|
||||||
compileOnly("org.projectlombok:lombok")
|
compileOnly("org.projectlombok:lombok")
|
||||||
annotationProcessor("org.projectlombok:lombok")
|
annotationProcessor("org.projectlombok:lombok")
|
||||||
|
|
||||||
|
// 如果你的测试也使用 Lombok
|
||||||
testCompileOnly("org.projectlombok:lombok")
|
testCompileOnly("org.projectlombok:lombok")
|
||||||
testAnnotationProcessor("org.projectlombok:lombok")
|
testAnnotationProcessor("org.projectlombok:lombok")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ dependencies {
|
|||||||
implementation("com.google.guava:guava:33.5.0-jre")
|
implementation("com.google.guava:guava:33.5.0-jre")
|
||||||
// commons-lang3
|
// commons-lang3
|
||||||
implementation("org.apache.commons:commons-lang3:3.20.0")
|
implementation("org.apache.commons:commons-lang3:3.20.0")
|
||||||
|
|
||||||
// test
|
// test
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
// jackson
|
||||||
|
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||||
|
implementation("com.fasterxml.jackson.core:jackson-core")
|
||||||
|
// aop
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-aop")
|
||||||
|
// web
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.hanserwei.common.aspect;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Documented
|
||||||
|
public @interface ApiOperationLog {
|
||||||
|
/**
|
||||||
|
* API 功能描述
|
||||||
|
*
|
||||||
|
* @return API 功能描述
|
||||||
|
*/
|
||||||
|
String description() default "";
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package com.hanserwei.common.aspect;
|
||||||
|
|
||||||
|
import com.hanserwei.common.utils.JsonUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.MDC;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class ApiOperationLogAspect {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码
|
||||||
|
*/
|
||||||
|
@Pointcut("@annotation(com.hanserwei.common.aspect.ApiOperationLog)")
|
||||||
|
public void apiOperationLog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 环绕通知处理方法
|
||||||
|
*
|
||||||
|
* @param joinPoint 连接点对象,包含目标方法的信息
|
||||||
|
* @return 目标方法执行结果
|
||||||
|
* @throws Throwable 目标方法可能抛出的异常
|
||||||
|
*/
|
||||||
|
@Around("apiOperationLog()")
|
||||||
|
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
try {
|
||||||
|
// 记录请求开始时间
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// 设置追踪ID到MDC中,用于日志追踪
|
||||||
|
MDC.put("traceId", UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
// 获取被请求的类名和方法名
|
||||||
|
String className = joinPoint.getTarget().getClass().getSimpleName();
|
||||||
|
String methodName = joinPoint.getSignature().getName();
|
||||||
|
|
||||||
|
// 获取请求参数
|
||||||
|
Object[] args = joinPoint.getArgs();
|
||||||
|
// 将请求参数转换为JSON字符串格式
|
||||||
|
String argsJsonStr = Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(", "));
|
||||||
|
|
||||||
|
// 获取API操作日志注解中的描述信息
|
||||||
|
String description = getApiOperationLogDescription(joinPoint);
|
||||||
|
|
||||||
|
// 记录请求开始日志,包括功能描述、请求参数、类名和方法名
|
||||||
|
log.info("====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== ",
|
||||||
|
description, argsJsonStr, className, methodName);
|
||||||
|
|
||||||
|
// 执行目标方法
|
||||||
|
Object result = joinPoint.proceed();
|
||||||
|
|
||||||
|
// 计算方法执行耗时
|
||||||
|
long executionTime = System.currentTimeMillis() - startTime;
|
||||||
|
|
||||||
|
// 记录请求结束日志,包括功能描述、执行耗时和返回结果
|
||||||
|
log.info("====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== ",
|
||||||
|
description, executionTime, JsonUtils.toJsonString(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
// 清理MDC中的追踪ID
|
||||||
|
MDC.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取API操作日志注解的描述信息
|
||||||
|
*
|
||||||
|
* @param joinPoint 连接点对象
|
||||||
|
* @return 注解中的描述信息
|
||||||
|
*/
|
||||||
|
private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) {
|
||||||
|
// 1. 从 ProceedingJoinPoint 获取 MethodSignature
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
|
||||||
|
// 2. 使用 MethodSignature 获取当前被注解的 Method
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
|
||||||
|
// 3. 从 Method 中提取 ApiOperationLog 注解
|
||||||
|
ApiOperationLog apiOperationLog = method.getAnnotation(ApiOperationLog.class);
|
||||||
|
|
||||||
|
// 4. 从 ApiOperationLog 注解中获取 description 属性
|
||||||
|
return apiOperationLog.description();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换对象为JSON字符串的函数
|
||||||
|
*
|
||||||
|
* @return 转换函数
|
||||||
|
*/
|
||||||
|
private Function<Object, String> toJsonStr() {
|
||||||
|
return JsonUtils::toJsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.hanserwei.common.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class JacksonConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ObjectMapper objectMapper() {
|
||||||
|
// 初始化一个 ObjectMapper 对象,用于自定义 Jackson 的行为
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
// 忽略未知字段(前端有传入某个字段,但是后端未定义接受该字段值,则一律忽略掉)
|
||||||
|
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
|
||||||
|
// JavaTimeModule 用于指定序列化和反序列化规则
|
||||||
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
|
|
||||||
|
// 支持 LocalDateTime、LocalDate、LocalTime
|
||||||
|
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
|
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
|
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
|
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
|
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||||
|
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||||
|
|
||||||
|
objectMapper.registerModule(javaTimeModule);
|
||||||
|
|
||||||
|
// 设置时区
|
||||||
|
objectMapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
|
||||||
|
|
||||||
|
// 设置凡是为 null 的字段,返参中均不返回,请根据项目组约定是否开启
|
||||||
|
// objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
|
|
||||||
|
return objectMapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.hanserwei.common.enums;
|
||||||
|
|
||||||
|
import com.hanserwei.common.exception.BaseExceptionInterface;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||||
|
|
||||||
|
// ----------- 通用异常状态码 -----------
|
||||||
|
SYSTEM_ERROR("10000", "出错啦,后台小哥正在努力修复中..."),
|
||||||
|
PARAM_NOT_VALID("10001", "参数错误"),
|
||||||
|
|
||||||
|
// ----------- 业务异常状态码 -----------
|
||||||
|
;
|
||||||
|
|
||||||
|
// 异常码
|
||||||
|
private final String errorCode;
|
||||||
|
// 错误信息
|
||||||
|
private final String errorMsg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.hanserwei.common.exception;
|
||||||
|
|
||||||
|
public interface BaseExceptionInterface {
|
||||||
|
String getErrorCode();
|
||||||
|
|
||||||
|
String getErrorMsg();
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hanserwei.common.exception;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class BizException extends RuntimeException {
|
||||||
|
// 异常码
|
||||||
|
private String errorCode;
|
||||||
|
// 错误信息
|
||||||
|
private String errorMsg;
|
||||||
|
|
||||||
|
public BizException(BaseExceptionInterface baseExceptionInterface) {
|
||||||
|
this.errorCode = baseExceptionInterface.getErrorCode();
|
||||||
|
this.errorMsg = baseExceptionInterface.getErrorMsg();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.hanserwei.common.exception;
|
||||||
|
|
||||||
|
import com.hanserwei.common.enums.ResponseCodeEnum;
|
||||||
|
import com.hanserwei.common.utils.Response;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 捕获自定义业务异常
|
||||||
|
*
|
||||||
|
* @return 错误信息
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({BizException.class})
|
||||||
|
@ResponseBody
|
||||||
|
public Response<Object> handleBizException(HttpServletRequest request, BizException e) {
|
||||||
|
log.warn("{} request fail, errorCode: {}, errorMessage: {}", request.getRequestURI(), e.getErrorCode(), e.getErrorMsg());
|
||||||
|
return Response.fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他类型异常
|
||||||
|
*
|
||||||
|
* @param request 请求
|
||||||
|
* @param e 异常
|
||||||
|
* @return 错误信息
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({Exception.class})
|
||||||
|
@ResponseBody
|
||||||
|
public Response<Object> handleOtherException(HttpServletRequest request, Exception e) {
|
||||||
|
log.error("{} request error, ", request.getRequestURI(), e);
|
||||||
|
return Response.fail(ResponseCodeEnum.SYSTEM_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 捕获参数校验异常
|
||||||
|
*
|
||||||
|
* @return 错误信息
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({MethodArgumentNotValidException.class})
|
||||||
|
@ResponseBody
|
||||||
|
public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
|
||||||
|
// 参数错误异常码
|
||||||
|
String errorCode = ResponseCodeEnum.PARAM_NOT_VALID.getErrorCode();
|
||||||
|
|
||||||
|
// 获取 BindingResult
|
||||||
|
BindingResult bindingResult = e.getBindingResult();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// 获取校验不通过的字段,并组合错误信息,格式为: email 邮箱格式不正确, 当前值: '123124qq.com';
|
||||||
|
Optional.of(bindingResult.getFieldErrors()).ifPresent(errors -> errors.forEach(error ->
|
||||||
|
sb.append(error.getField())
|
||||||
|
.append(" ")
|
||||||
|
.append(error.getDefaultMessage())
|
||||||
|
.append(", 当前值: '")
|
||||||
|
.append(error.getRejectedValue())
|
||||||
|
.append("'; ")
|
||||||
|
));
|
||||||
|
|
||||||
|
// 错误信息
|
||||||
|
String errorMessage = sb.toString();
|
||||||
|
|
||||||
|
log.warn("{} request error, errorCode: {}, errorMessage: {}", request.getRequestURI(), errorCode, errorMessage);
|
||||||
|
|
||||||
|
return Response.fail(errorCode, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.hanserwei.common.utils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class JsonUtils {
|
||||||
|
private static final ObjectMapper INSTANCE = new ObjectMapper();
|
||||||
|
|
||||||
|
public static String toJsonString(Object obj) {
|
||||||
|
try {
|
||||||
|
return INSTANCE.writeValueAsString(obj);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
return obj.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.hanserwei.common.utils;
|
||||||
|
|
||||||
|
import com.hanserwei.common.exception.BaseExceptionInterface;
|
||||||
|
import com.hanserwei.common.exception.BizException;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Response<T> implements Serializable {
|
||||||
|
|
||||||
|
// 是否成功,默认为 true
|
||||||
|
private boolean success = true;
|
||||||
|
// 响应消息
|
||||||
|
private String message;
|
||||||
|
// 异常码
|
||||||
|
private String errorCode;
|
||||||
|
// 响应数据
|
||||||
|
private T data;
|
||||||
|
|
||||||
|
// =================================== 成功响应 ===================================
|
||||||
|
public static <T> Response<T> success() {
|
||||||
|
return new Response<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> success(T data) {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setData(data);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================================== 失败响应 ===================================
|
||||||
|
public static <T> Response<T> fail() {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setSuccess(false);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> fail(String errorMessage) {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setSuccess(false);
|
||||||
|
response.setMessage(errorMessage);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> fail(String errorCode, String errorMessage) {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setSuccess(false);
|
||||||
|
response.setErrorCode(errorCode);
|
||||||
|
response.setMessage(errorMessage);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> fail(BizException bizException) {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setSuccess(false);
|
||||||
|
response.setErrorCode(bizException.getErrorCode());
|
||||||
|
response.setMessage(bizException.getErrorMsg());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Response<T> fail(BaseExceptionInterface baseExceptionInterface) {
|
||||||
|
Response<T> response = new Response<>();
|
||||||
|
response.setSuccess(false);
|
||||||
|
response.setErrorCode(baseExceptionInterface.getErrorCode());
|
||||||
|
response.setMessage(baseExceptionInterface.getErrorMsg());
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,9 @@ dependencies {
|
|||||||
// Test
|
// Test
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
|
||||||
|
// jsr380
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-validation")
|
||||||
|
|
||||||
// 其他依赖…
|
// 其他依赖…
|
||||||
implementation(project(":weblog-module-common"))
|
implementation(project(":weblog-module-common"))
|
||||||
implementation(project(":weblog-module-admin"))
|
implementation(project(":weblog-module-admin"))
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package com.hanserwei.web;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
|
@ComponentScan({"com.hanserwei.*"})
|
||||||
public class WeblogWebApplication {
|
public class WeblogWebApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(WeblogWebApplication.class, args);
|
SpringApplication.run(WeblogWebApplication.class, args);
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.hanserwei.web.controller;
|
||||||
|
|
||||||
|
import com.hanserwei.common.aspect.ApiOperationLog;
|
||||||
|
import com.hanserwei.web.model.User;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.validation.FieldError;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@Slf4j
|
||||||
|
public class TestController {
|
||||||
|
|
||||||
|
@PostMapping("/test")
|
||||||
|
@ApiOperationLog(description = "测试接口")
|
||||||
|
public ResponseEntity<String> test(@RequestBody @Validated User user, BindingResult bindingResult) {
|
||||||
|
// 是否存在校验错误
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
// 获取校验不通过字段的提示信息
|
||||||
|
String errorMsg = bindingResult.getFieldErrors()
|
||||||
|
.stream()
|
||||||
|
.map(FieldError::getDefaultMessage)
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
|
||||||
|
return ResponseEntity.badRequest().body(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返参
|
||||||
|
return ResponseEntity.ok("参数没有任何问题");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
weblog-web/src/main/java/com/hanserwei/web/model/User.java
Normal file
25
weblog-web/src/main/java/com/hanserwei/web/model/User.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package com.hanserwei.web.model;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.*;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class User {
|
||||||
|
// 用户名
|
||||||
|
@NotBlank(message = "用户名不能为空") // 注解确保用户名不为空
|
||||||
|
private String username;
|
||||||
|
// 性别
|
||||||
|
@NotNull(message = "性别不能为空") // 注解确保性别不为空
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
// 年龄
|
||||||
|
@NotNull(message = "年龄不能为空")
|
||||||
|
@Min(value = 18, message = "年龄必须大于或等于 18") // 注解确保年龄大于等于 18
|
||||||
|
@Max(value = 100, message = "年龄必须小于或等于 100") // 注解确保年龄小于等于 100
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
// 邮箱
|
||||||
|
@NotBlank(message = "邮箱不能为空")
|
||||||
|
@Email(message = "邮箱格式不正确") // 注解确保邮箱格式正确
|
||||||
|
private String email;
|
||||||
|
}
|
||||||
@@ -7,7 +7,8 @@
|
|||||||
<property scope="context" name="appName" value="weblog"/>
|
<property scope="context" name="appName" value="weblog"/>
|
||||||
<!-- 自定义日志输出路径,以及日志名称前缀 -->
|
<!-- 自定义日志输出路径,以及日志名称前缀 -->
|
||||||
<property name="LOG_FILE" value="/app/weblog/logs/${appName}.%d{yyyy-MM-dd}"/>
|
<property name="LOG_FILE" value="/app/weblog/logs/${appName}.%d{yyyy-MM-dd}"/>
|
||||||
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
|
<property name="FILE_LOG_PATTERN"
|
||||||
|
value="[TraceId: %X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
|
||||||
<!--<property name="CONSOLE_LOG_PATTERN" value="${FILE_LOG_PATTERN}"/>-->
|
<!--<property name="CONSOLE_LOG_PATTERN" value="${FILE_LOG_PATTERN}"/>-->
|
||||||
|
|
||||||
<!-- 按照每天生成日志文件 -->
|
<!-- 按照每天生成日志文件 -->
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
<!-- dev 环境(仅输出到控制台) -->
|
<!-- dev 环境(仅输出到控制台) -->
|
||||||
<springProfile name="dev">
|
<springProfile name="dev">
|
||||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||||
<root level="info">
|
<root level="INFO">
|
||||||
<appender-ref ref="CONSOLE"/>
|
<appender-ref ref="CONSOLE"/>
|
||||||
</root>
|
</root>
|
||||||
</springProfile>
|
</springProfile>
|
||||||
|
|||||||
Reference in New Issue
Block a user