init
This commit is contained in:
25
backend/common/common-api/pom.xml
Normal file
25
backend/common/common-api/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-api</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.k12study.common.api.response;
|
||||
|
||||
import com.k12study.common.core.utils.TraceIdHolder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ApiResponse<T> {
|
||||
private final int code;
|
||||
private final String message;
|
||||
private final T data;
|
||||
private final String traceId;
|
||||
|
||||
private ApiResponse(int code, String message, T data, String traceId) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.traceId = traceId;
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(0, "OK", data, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(String message, T data) {
|
||||
return new ApiResponse<>(0, message, data, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> failure(int code, String message) {
|
||||
return new ApiResponse<>(code, message, null, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
}
|
||||
24
backend/common/common-core/pom.xml
Normal file
24
backend/common/common-core/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-core</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.k12study.common.core.constants;
|
||||
|
||||
public final class SecurityConstants {
|
||||
public static final String TRACE_ID = "X-Trace-Id";
|
||||
public static final String HEADER_USER_ID = "X-User-Id";
|
||||
public static final String HEADER_USERNAME = "X-Username";
|
||||
public static final String HEADER_DISPLAY_NAME = "X-Display-Name";
|
||||
public static final String HEADER_TENANT_ID = "X-Tenant-Id";
|
||||
public static final String HEADER_DEPT_ID = "X-Dept-Id";
|
||||
|
||||
private SecurityConstants() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.common.core.domain;
|
||||
|
||||
public record RouteKey(
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantId,
|
||||
String tenantPath,
|
||||
String deptId,
|
||||
String deptPath
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.k12study.common.core.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class TraceIdHolder {
|
||||
private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<>();
|
||||
|
||||
private TraceIdHolder() {
|
||||
}
|
||||
|
||||
public static String getOrCreate() {
|
||||
String value = TRACE_ID.get();
|
||||
if (value == null || value.isBlank()) {
|
||||
value = UUID.randomUUID().toString().replace("-", "");
|
||||
TRACE_ID.set(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void set(String traceId) {
|
||||
TRACE_ID.set(traceId);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
TRACE_ID.remove();
|
||||
}
|
||||
}
|
||||
28
backend/common/common-mybatis/pom.xml
Normal file
28
backend/common/common-mybatis/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-mybatis</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.k12study.common.mybatis.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MybatisPlusConfiguration {
|
||||
}
|
||||
19
backend/common/common-redis/pom.xml
Normal file
19
backend/common/common-redis/pom.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-redis</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.k12study.common.redis.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfiguration {
|
||||
}
|
||||
38
backend/common/common-security/pom.xml
Normal file
38
backend/common/common-security/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-security</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "auth")
|
||||
public class AuthProperties {
|
||||
private boolean enabled = true;
|
||||
private boolean gatewayMode = false;
|
||||
private String tokenHeader = "Authorization";
|
||||
private String tokenPrefix = "Bearer ";
|
||||
private String secret = "k12study-dev-secret-k12study-dev-secret";
|
||||
private Duration accessTokenTtl = Duration.ofHours(12);
|
||||
private Duration refreshTokenTtl = Duration.ofDays(7);
|
||||
private List<String> whitelist = new ArrayList<>(List.of("/actuator/**", "/auth/login", "/auth/refresh"));
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isGatewayMode() {
|
||||
return gatewayMode;
|
||||
}
|
||||
|
||||
public void setGatewayMode(boolean gatewayMode) {
|
||||
this.gatewayMode = gatewayMode;
|
||||
}
|
||||
|
||||
public String getTokenHeader() {
|
||||
return tokenHeader;
|
||||
}
|
||||
|
||||
public void setTokenHeader(String tokenHeader) {
|
||||
this.tokenHeader = tokenHeader;
|
||||
}
|
||||
|
||||
public String getTokenPrefix() {
|
||||
return tokenPrefix;
|
||||
}
|
||||
|
||||
public void setTokenPrefix(String tokenPrefix) {
|
||||
this.tokenPrefix = tokenPrefix;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public Duration getAccessTokenTtl() {
|
||||
return accessTokenTtl;
|
||||
}
|
||||
|
||||
public void setAccessTokenTtl(Duration accessTokenTtl) {
|
||||
this.accessTokenTtl = accessTokenTtl;
|
||||
}
|
||||
|
||||
public Duration getRefreshTokenTtl() {
|
||||
return refreshTokenTtl;
|
||||
}
|
||||
|
||||
public void setRefreshTokenTtl(Duration refreshTokenTtl) {
|
||||
this.refreshTokenTtl = refreshTokenTtl;
|
||||
}
|
||||
|
||||
public List<String> getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
public void setWhitelist(List<String> whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import com.k12study.common.security.jwt.JwtTokenProvider;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AuthProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public JwtTokenProvider jwtTokenProvider(AuthProperties authProperties) {
|
||||
return new JwtTokenProvider(authProperties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public record RequestUserContext(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public final class RequestUserContextHolder {
|
||||
private static final ThreadLocal<RequestUserContext> CONTEXT = new ThreadLocal<>();
|
||||
|
||||
private RequestUserContextHolder() {
|
||||
}
|
||||
|
||||
public static void set(RequestUserContext context) {
|
||||
CONTEXT.set(context);
|
||||
}
|
||||
|
||||
public static RequestUserContext get() {
|
||||
return CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
import com.k12study.common.security.config.AuthProperties;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class JwtTokenProvider {
|
||||
private final AuthProperties authProperties;
|
||||
private final SecretKey secretKey;
|
||||
|
||||
public JwtTokenProvider(AuthProperties authProperties) {
|
||||
this.authProperties = authProperties;
|
||||
this.secretKey = Keys.hmacShaKeyFor(authProperties.getSecret().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String createAccessToken(JwtUserPrincipal principal) {
|
||||
Instant now = Instant.now();
|
||||
return Jwts.builder()
|
||||
.subject(principal.userId())
|
||||
.claim("username", principal.username())
|
||||
.claim("displayName", principal.displayName())
|
||||
.claim("tenantId", principal.tenantId())
|
||||
.claim("deptId", principal.deptId())
|
||||
.issuedAt(Date.from(now))
|
||||
.expiration(Date.from(now.plus(authProperties.getAccessTokenTtl())))
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public JwtUserPrincipal parse(String token) {
|
||||
Claims claims = Jwts.parser()
|
||||
.verifyWith(secretKey)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
return new JwtUserPrincipal(
|
||||
claims.getSubject(),
|
||||
claims.get("username", String.class),
|
||||
claims.get("displayName", String.class),
|
||||
claims.get("tenantId", String.class),
|
||||
claims.get("deptId", String.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
public record JwtUserPrincipal(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
34
backend/common/common-web/pom.xml
Normal file
34
backend/common/common-web/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-web</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.k12study.common.web.config;
|
||||
|
||||
import com.k12study.common.core.constants.SecurityConstants;
|
||||
import com.k12study.common.core.utils.TraceIdHolder;
|
||||
import com.k12study.common.security.context.RequestUserContext;
|
||||
import com.k12study.common.security.context.RequestUserContextHolder;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Configuration
|
||||
public class CommonWebMvcConfiguration extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
try {
|
||||
String traceId = request.getHeader(SecurityConstants.TRACE_ID);
|
||||
TraceIdHolder.set(traceId == null || traceId.isBlank() ? TraceIdHolder.getOrCreate() : traceId);
|
||||
|
||||
RequestUserContextHolder.set(new RequestUserContext(
|
||||
request.getHeader(SecurityConstants.HEADER_USER_ID),
|
||||
request.getHeader(SecurityConstants.HEADER_USERNAME),
|
||||
request.getHeader(SecurityConstants.HEADER_DISPLAY_NAME),
|
||||
request.getHeader(SecurityConstants.HEADER_TENANT_ID),
|
||||
request.getHeader(SecurityConstants.HEADER_DEPT_ID)
|
||||
));
|
||||
response.setHeader(SecurityConstants.TRACE_ID, TraceIdHolder.getOrCreate());
|
||||
filterChain.doFilter(request, response);
|
||||
} finally {
|
||||
TraceIdHolder.clear();
|
||||
RequestUserContextHolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.common.web.exception;
|
||||
|
||||
public class BizException extends RuntimeException {
|
||||
private final int code;
|
||||
|
||||
public BizException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.k12study.common.web.exception;
|
||||
|
||||
import com.k12study.common.api.response.ApiResponse;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BizException.class)
|
||||
public ApiResponse<Void> handleBizException(BizException exception) {
|
||||
return ApiResponse.failure(exception.getCode(), exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ApiResponse<Void> handleException(Exception exception) {
|
||||
return ApiResponse.failure(500, exception.getMessage());
|
||||
}
|
||||
}
|
||||
24
backend/common/pom.xml
Normal file
24
backend/common/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>common-api</module>
|
||||
<module>common-core</module>
|
||||
<module>common-web</module>
|
||||
<module>common-security</module>
|
||||
<module>common-mybatis</module>
|
||||
<module>common-redis</module>
|
||||
</modules>
|
||||
</project>
|
||||
Reference in New Issue
Block a user