This commit is contained in:
Kevin-Laptop 2025-04-08 14:29:54 +08:00
commit 26fc4370dc
52 changed files with 1045 additions and 0 deletions

View File

@ -0,0 +1,57 @@
---
description:
globs:
alwaysApply: true
---
您是Java编程、Spring Boot、Spring Framework、Maven、JUnit和相关Java技术方面的专家。
代码风格和结构
-使用准确的Spring Boot示例编写干净、高效且文档齐全的Java代码。
-在整个代码中使用Spring Boot最佳实践和约定。
-在创建Web服务时实施RESTful API设计模式。
-按照camelCase约定使用描述性方法和变量名。
-构建Spring Boot应用程序控制器、服务、存储库、模型、配置。
Spring Boot规范
-使用Spring Boot启动器进行快速项目设置和依赖管理。
-正确使用注释(例如@SpringBootApplication、@RestController、@Service
-有效利用Spring Boot的自动配置功能。
-使用@ControlllerAddge和@ExceptionHandler实施正确的异常处理。
命名约定
-将PascalCase用于类名例如UserController、OrderService
-将camelCase用于方法和变量名例如findUserById、isOrderValid
-将ALL_CAPS用于常量例如MAX_RETRY_ATTEMPTS、DEFAULT_PAGE_SIZE
Java和Spring Boot用法
-在适用的情况下使用Java21或更高版本的功能例如记录、密封类、模式匹配
-利用Spring Boot 3.x功能和最佳实践。
-在适用的情况下将Spring Data JPA用于数据库操作。
-使用Bean验证例如@Valid、自定义验证器实现正确的验证。
配置和属性
-使用application.properties或application.yml进行配置。
-使用Spring Profiles实现environment-specific配置。
-使用@ConfigurationProperties进行类型安全的配置属性。依赖注入和IoC
-使用构造函数注入而不是字段注入以获得更好的可测试性。
-利用Spring的IoC容器来管理bean生命周期。
测试
-使用JUnit 5和Spring Boot Test编写单元测试。
-使用@SpringBootTest实现集成测试。
-使用@DataJpaTest进行存储库层测试。性能和可扩展性
-使用Spring Cache抽象实现缓存策略。-使用@Async进行异步处理进行非阻塞操作。
-实施适当的数据库索引和查询优化。
日志记录和监控
-使用SLF4J和Logback进行日志记录。
-实施适当的日志级别ERROR、WARN、INFO、DEBUG
-使用Spring Boot Actuator进行应用程序监控和指标。
API文档
-使用Springdoc OpenAPI以前的Swagger进行API留档。
数据访问和ORM
-使用mybatis plus进行数据库操作。
-实现适当的实体关系和级联。
构建和部署
-使用Maven进行依赖管理和构建流程。
-为不同的环境(开发、测试、产品)实施适当的配置文件。
遵循以下最佳实践:
-RESTful API设计正确使用HTTP方法、状态代码等
-微服务架构(如果适用)。
-使用Spring的@Async进行异步处理.
所有生成的代码都需要加上java注释注意父级maven依赖,尽量使用lombok的getter和setter
工程依赖的包使用的版本号都使用父项目中定义的版本,如果父项目不存在则空

22
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"maven.view": "hierarchical",
"java.configuration.updateBuildConfiguration": "automatic",
"cSpell.words": [
"Appender",
"Appenders",
"baomidou",
"Hikari",
"ibatis",
"jdbc",
"jsqlparser",
"mybatis",
"Nacos",
"projectlombok",
"springframework",
"wjbl",
"xiaoymin",
"zaxxer"
],
"java.compile.nullAnalysis.mode": "automatic",
"java.format.settings.url": ".vscode/java-formatter.xml"
}

108
pom.xml Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<java.version>21</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.3.10</spring-boot.version>
<spring-cloud.version>2023.0.5</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
<mybatis-plus.version>3.5.11</mybatis-plus.version>
<knife4j.version>4.5.0</knife4j.version>
</properties>
<modules>
<module>weight-loss-camp-api-base</module>
<module>weight-loss-camp-api-data</module>
<module>weight-loss-camp-service-api</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-bom</artifactId>
<version>${mybatis-plus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
</build>
</project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>weight-loss-camp-api-base</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,11 @@
package com.wjbl.weightlosscamp.api.base.constant;
/**
* Web参数常量
*/
public class WebParamConstant {
public static final String TENANT_ID = "tenantId";
public static final String OPERATOR = "operator";
public static final String OPERATOR_ID = "operatorId";
public static final String SEQ = "seq";
}

View File

@ -0,0 +1,20 @@
package com.wjbl.weightlosscamp.api.base.core;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* API错误码枚举
*/
@Getter
@AllArgsConstructor
public enum ApiErrorCode {
SUCCESS(200, "操作成功"),
FAILED(500, "操作失败"),
VALIDATE_FAILED(404, "参数检验失败"),
UNAUTHORIZED(401, "暂未登录或token已经过期"),
FORBIDDEN(403, "没有相关权限");
private final int code;
private final String msg;
}

View File

@ -0,0 +1,40 @@
package com.wjbl.weightlosscamp.api.base.core;
import lombok.Data;
/**
* API响应结果
* @param <T> 数据类型
*/
@Data
public class ApiResult<T> {
private int code;
private String msg;
private T data;
private ApiResult(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static <T> ApiResult<T> success() {
return new ApiResult<>(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMsg(), null);
}
public static <T> ApiResult<T> success(T data) {
return new ApiResult<>(ApiErrorCode.SUCCESS.getCode(), ApiErrorCode.SUCCESS.getMsg(), data);
}
public static <T> ApiResult<T> failed(String msg) {
return new ApiResult<>(ApiErrorCode.FAILED.getCode(), msg, null);
}
public static <T> ApiResult<T> failed(ApiErrorCode errorCode) {
return new ApiResult<>(errorCode.getCode(), errorCode.getMsg(), null);
}
public static <T> ApiResult<T> failed(int code, String msg) {
return new ApiResult<>(code, msg, null);
}
}

View File

@ -0,0 +1,11 @@
package com.wjbl.weightlosscamp.api.base.core;
import lombok.Data;
/**
* ID请求参数
*/
@Data
public class IdParam {
private String id;
}

View File

@ -0,0 +1,14 @@
package com.wjbl.weightlosscamp.api.base.core;
import lombok.Data;
/**
* 分页请求参数
* @param <T> 数据类型
*/
@Data
public class PageParam<T> {
private Integer page = 1;
private Integer pageSize = 10;
private T data;
}

View File

@ -0,0 +1,69 @@
package com.wjbl.weightlosscamp.api.base.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 基础实体类
*/
@Data
public class BaseEntity {
/**
* 租户ID
*/
@TableField(fill = FieldFill.INSERT)
private String tenantId;
/**
* 创建人ID
*/
@TableField(fill = FieldFill.INSERT)
private String createdById;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private String createdBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
/**
* 更新人ID
*/
@TableField(fill = FieldFill.UPDATE)
private String updatedById;
/**
* 更新人
*/
@TableField(fill = FieldFill.UPDATE)
private String updatedBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updatedTime;
/**
* 逻辑删除
*/
@TableLogic
private Integer deleted;
/**
* 版本号
*/
@Version
private Integer revision;
}

View File

@ -0,0 +1,27 @@
package com.wjbl.weightlosscamp.api.base.exception;
import com.wjbl.weightlosscamp.api.base.core.ApiErrorCode;
import lombok.Getter;
/**
* API异常
*/
@Getter
public class ApiException extends RuntimeException {
private final int code;
public ApiException(String message) {
super(message);
this.code = ApiErrorCode.FAILED.getCode();
}
public ApiException(ApiErrorCode errorCode) {
super(errorCode.getMsg());
this.code = errorCode.getCode();
}
public ApiException(int code, String message) {
super(message);
this.code = code;
}
}

View File

@ -0,0 +1,83 @@
package com.wjbl.weightlosscamp.api.base.filter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
/**
* Web日志过滤器
*/
@Slf4j
@Component
@Order(2)
public class WebLogFilter extends OncePerRequestFilter {
private final ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("null")
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
try {
// 记录请求信息
logRequest(requestWrapper);
filterChain.doFilter(requestWrapper, responseWrapper);
// 记录响应信息
logResponse(responseWrapper);
responseWrapper.copyBodyToResponse();
} finally {
responseWrapper.resetBuffer();
}
}
private void logRequest(ContentCachingRequestWrapper request) throws IOException {
Map<String, Object> requestInfo = new HashMap<>();
requestInfo.put("uri", request.getRequestURI());
requestInfo.put("method", request.getMethod());
requestInfo.put("params", request.getParameterMap());
byte[] content = request.getContentAsByteArray();
if (content.length > 0) {
requestInfo.put("body", new String(content, request.getCharacterEncoding()));
}
log.info("Request: {}", objectMapper.writeValueAsString(requestInfo));
}
private void logResponse(ContentCachingResponseWrapper response) throws IOException {
Map<String, Object> responseInfo = new HashMap<>();
responseInfo.put("status", response.getStatus());
byte[] content = response.getContentAsByteArray();
if (content.length > 0) {
String responseBody = new String(content, response.getCharacterEncoding());
// 如果响应体过长只记录前1000个字符
if (responseBody.length() > 1000) {
responseBody = responseBody.substring(0, 1000) + "...";
}
responseInfo.put("body", responseBody);
}
log.info("Response: {}", objectMapper.writeValueAsString(responseInfo));
}
}

View File

@ -0,0 +1,56 @@
package com.wjbl.weightlosscamp.api.base.filter;
import java.io.IOException;
import java.util.UUID;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.wjbl.weightlosscamp.api.base.constant.WebParamConstant;
import com.wjbl.weightlosscamp.api.base.web.WebContextHolder;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* Web参数过滤器
*/
@Component
@Order(1)
public class WebParamFilter extends OncePerRequestFilter {
@SuppressWarnings("null")
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
// 设置租户ID
String tenantId = request.getHeader(WebParamConstant.TENANT_ID);
WebContextHolder.setTenantId(tenantId);
// 设置操作人
String operator = request.getHeader(WebParamConstant.OPERATOR);
WebContextHolder.setOperator(operator);
// 设置操作人ID
String operatorId = request.getHeader(WebParamConstant.OPERATOR_ID);
WebContextHolder.setOperatorId(operatorId);
// 设置序列号
String seq = request.getHeader(WebParamConstant.SEQ);
if (seq == null || seq.isEmpty()) {
seq = UUID.randomUUID().toString();
}
MDC.put(WebParamConstant.SEQ, seq);
filterChain.doFilter(request, response);
} finally {
WebContextHolder.clear();
MDC.clear();
}
}
}

View File

@ -0,0 +1,33 @@
package com.wjbl.weightlosscamp.api.base.util;
import com.wjbl.weightlosscamp.api.base.exception.ApiException;
import org.springframework.util.ObjectUtils;
/**
* 业务断言类
*/
public class ApiAssert {
public static void isTrue(boolean expression, String message) {
if (!expression) {
throw new ApiException(message);
}
}
public static void isEmpty(Object object, String message) {
if (!ObjectUtils.isEmpty(object)) {
throw new ApiException(message);
}
}
public static void notEmpty(Object object, String message) {
if (ObjectUtils.isEmpty(object)) {
throw new ApiException(message);
}
}
public static void equals(Object obj1, Object obj2, String message) {
if (!ObjectUtils.nullSafeEquals(obj1, obj2)) {
throw new ApiException(message);
}
}
}

View File

@ -0,0 +1,7 @@
package com.wjbl.weightlosscamp.api.base.validation.group;
/**
* 创建验证分组
*/
public interface Create {
}

View File

@ -0,0 +1,7 @@
package com.wjbl.weightlosscamp.api.base.validation.group;
/**
* 更新验证分组
*/
public interface Update {
}

View File

@ -0,0 +1,43 @@
package com.wjbl.weightlosscamp.api.base.web;
import com.wjbl.weightlosscamp.api.base.core.ApiErrorCode;
import com.wjbl.weightlosscamp.api.base.core.ApiResult;
import com.wjbl.weightlosscamp.api.base.exception.ApiException;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ApiException.class)
public ApiResult<Void> handleApiException(ApiException e) {
log.error("API异常", e);
return ApiResult.failed(e.getCode(), e.getMessage());
}
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
public ApiResult<Void> handleValidException(Exception e) {
log.error("参数校验异常", e);
return ApiResult.failed(ApiErrorCode.VALIDATE_FAILED);
}
@ExceptionHandler(ConstraintViolationException.class)
public ApiResult<Void> handleConstraintViolationException(ConstraintViolationException e) {
log.error("参数校验异常", e);
return ApiResult.failed(ApiErrorCode.VALIDATE_FAILED);
}
@ExceptionHandler(Exception.class)
public ApiResult<Void> handleException(Exception e) {
log.error("系统异常", e);
return ApiResult.failed(ApiErrorCode.FAILED);
}
}

View File

@ -0,0 +1,40 @@
package com.wjbl.weightlosscamp.api.base.web;
/**
* Web上下文持有者
*/
public class WebContextHolder {
private static final ThreadLocal<String> tenantThreadLocal = new ThreadLocal<>();
private static final ThreadLocal<String> operatorThreadLocal = new ThreadLocal<>();
private static final ThreadLocal<String> operatorIdThreadLocal = new ThreadLocal<>();
public static void setTenantId(String tenantId) {
tenantThreadLocal.set(tenantId);
}
public static String getTenantId() {
return tenantThreadLocal.get();
}
public static void setOperator(String operator) {
operatorThreadLocal.set(operator);
}
public static String getOperator() {
return operatorThreadLocal.get();
}
public static void setOperatorId(String operatorId) {
operatorIdThreadLocal.set(operatorId);
}
public static String getOperatorId() {
return operatorIdThreadLocal.get();
}
public static void clear() {
tenantThreadLocal.remove();
operatorThreadLocal.remove();
operatorIdThreadLocal.remove();
}
}

View File

@ -0,0 +1,3 @@
artifactId=weight-loss-camp-api-base
groupId=com.wjbl
version=1.0.0-SNAPSHOT

View File

@ -0,0 +1,14 @@
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\constant\WebParamConstant.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\core\ApiErrorCode.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\core\ApiResult.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\core\IdParam.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\core\PageParam.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\entity\BaseEntity.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\exception\ApiException.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\filter\WebLogFilter.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\filter\WebParamFilter.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\util\ApiAssert.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\validation\group\Create.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\validation\group\Update.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\web\GlobalExceptionHandler.java
C:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-base\src\main\java\com\wjbl\weightlosscamp\api\base\web\WebContextHolder.java

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>weight-loss-camp-api-data</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- 基础模块依赖 -->
<dependency>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp-api-base</artifactId>
<version>${project.version}</version>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- HikariCP连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,30 @@
package com.wjbl.weightlosscamp.api.data.config;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.wjbl.weightlosscamp.api.base.web.WebContextHolder;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
/**
* 自定义租户处理器
*/
public class CustomTenantHandler implements TenantLineHandler {
@Override
public Expression getTenantId() {
String tenantId = WebContextHolder.getTenantId();
return new StringValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean ignoreTable(String tableName) {
// 这里可以配置不需要进行租户过滤的表
return false;
}
}

View File

@ -0,0 +1,32 @@
package com.wjbl.weightlosscamp.api.data.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatis Plus配置类
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(CustomTenantHandler tenantHandler) {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加租户插件
TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor();
tenantLineInnerInterceptor.setTenantLineHandler(tenantHandler);
interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
// 添加分页插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(100L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}

View File

@ -0,0 +1,35 @@
package com.wjbl.weightlosscamp.api.data.config;
import java.time.LocalDateTime;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.wjbl.weightlosscamp.api.base.web.WebContextHolder;
/**
* MyBatis Plus字段填充配置
*/
@Component
public class MybatisPlusFieldFillConfig implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// this.strictInsertFill(metaObject, "tenantId", String.class,
// WebContextHolder.getTenantId());
this.strictInsertFill(metaObject, "createdById", String.class, WebContextHolder.getOperatorId());
this.strictInsertFill(metaObject, "createdBy", String.class, WebContextHolder.getOperator());
this.strictInsertFill(metaObject, "createdTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "deleted", Integer.class, 0);
this.strictInsertFill(metaObject, "revision", Integer.class, 1);
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updatedById", String.class,
WebContextHolder.getOperatorId());
this.strictUpdateFill(metaObject, "updatedBy", String.class, WebContextHolder.getOperatorId());
this.strictUpdateFill(metaObject, "updatedTime", LocalDateTime.class, LocalDateTime.now());
}
}

View File

@ -0,0 +1,3 @@
artifactId=weight-loss-camp-api-data
groupId=com.wjbl
version=1.0.0-SNAPSHOT

View File

@ -0,0 +1,3 @@
c:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-data\src\main\java\com\wjbl\weightlosscamp\api\data\config\CustomTenantHandler.java
c:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-data\src\main\java\com\wjbl\weightlosscamp\api\data\config\MybatisPlusConfig.java
c:\kevin\PROJECT\weigtht-loss-camp\code\service\weight-loss-camp\weight-loss-camp-api-data\src\main\java\com\wjbl\weightlosscamp\api\data\config\MybatisPlusFieldFillConfig.java

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>weight-loss-camp-service-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- 基础模块依赖 -->
<dependency>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp-api-base</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 数据模块依赖 -->
<dependency>
<groupId>com.wjbl</groupId>
<artifactId>weight-loss-camp-api-data</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,17 @@
package com.wjbl.weightlosscamp.service.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 服务启动类
*/
@SpringBootApplication
@EnableDiscoveryClient
public class WeightLossCampServiceApiApplication {
public static void main(String[] args) {
SpringApplication.run(WeightLossCampServiceApiApplication.class, args);
}
}

View File

@ -0,0 +1,37 @@
server:
port: 8080
servlet:
context-path: /weight-loss-camp-service-api
spring:
application:
name: weight-loss-camp-service-api
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/kevin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
cloud:
nacos:
discovery:
server-addr: 60.205.225.2:8848
group: weight-loss-camp
username: nacos
password: nacos
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
knife4j:
enable: true
setting:
language: zh-CN
swagger-model-name: 实体类列表
basic:
enable: false

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{36} - %msg%n</Property>
<Property name="LOG_FILE_PATH">logs</Property>
<Property name="LOG_FILE_NAME">weight-loss-camp-service-api</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="FileAppender" fileName="${LOG_FILE_PATH}/${LOG_FILE_NAME}.log" filePattern="${LOG_FILE_PATH}/${LOG_FILE_NAME}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>

View File

@ -0,0 +1,37 @@
server:
port: 8080
servlet:
context-path: /weight-loss-camp-service-api
spring:
application:
name: weight-loss-camp-service-api
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/kevin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
cloud:
nacos:
discovery:
server-addr: 60.205.225.2:8848
group: weight-loss-camp
username: nacos
password: nacos
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
knife4j:
enable: true
setting:
language: zh-CN
swagger-model-name: 实体类列表
basic:
enable: false

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{36} - %msg%n</Property>
<Property name="LOG_FILE_PATH">logs</Property>
<Property name="LOG_FILE_NAME">weight-loss-camp-service-api</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="FileAppender" fileName="${LOG_FILE_PATH}/${LOG_FILE_NAME}.log" filePattern="${LOG_FILE_PATH}/${LOG_FILE_NAME}-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>