初始化 V1

This commit is contained in:
陈博文
2025-06-10 15:04:49 +08:00
parent cbed9f13d1
commit b412a44ec7
1986 changed files with 1774358 additions and 59 deletions

19
yudao-gateway/Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
## 感谢复旦核博士的建议!灰子哥,牛皮!
FROM eclipse-temurin:21-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /yudao-gateway
WORKDIR /yudao-gateway
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/yudao-gateway.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m"
## 暴露后端项目的 48080 端口
EXPOSE 48080
## 启动后端项目
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

95
yudao-gateway/pom.xml Normal file
View File

@@ -0,0 +1,95 @@
<?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>
<artifactId>yudao</artifactId>
<groupId>cn.iocoder.cloud</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-gateway</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>API 服务网关,基于 Spring Cloud Gateway 实现</description>
<url>https://github.com/YunaiV/yudao-cloud</url>
<dependencies>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
<exclusions>
<exclusion>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Gateway 网关相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Config 配置中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version> <!-- 如果 spring.boot.version 版本修改,则这里也要跟着修改 -->
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,14 @@
package cn.iocoder.yudao.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
// 启动 Spring Boot 应用
SpringApplication.run(GatewayServerApplication.class, args);
}
}

View File

@@ -0,0 +1,48 @@
package cn.iocoder.yudao.gateway.filter.cors;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/**
* 跨域 Filter
*
* @author 芋道源码
*/
@Component
public class CorsFilter implements WebFilter {
private static final String ALL = "*";
private static final String MAX_AGE = "3600L";
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
// 非跨域请求,直接放行
ServerHttpRequest request = exchange.getRequest();
if (!CorsUtils.isCorsRequest(request)) {
return chain.filter(exchange);
}
// 设置跨域响应头
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALL);
headers.add("Access-Control-Allow-Methods", ALL);
headers.add("Access-Control-Allow-Headers", ALL);
headers.add("Access-Control-Max-Age", MAX_AGE);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(exchange);
}
}

View File

@@ -0,0 +1,54 @@
package cn.iocoder.yudao.gateway.filter.cors;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 解决 Spring Cloud Gateway 2.x 跨域时,出现重复 Origin 的 BUG
*
* 参考文档:<a href="https://blog.csdn.net/zimou5581/article/details/90043178" />
*
* @author 芋道源码
*/
@Component
public class CorsResponseHeaderFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
// 指定此过滤器位于 NettyWriteResponseFilter 之后
// 即待处理完响应体后接着处理响应头
return NettyWriteResponseFilter.WRITE_RESPONSE_FILTER_ORDER + 1;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.defer(() -> {
// https://gitee.com/zhijiantianya/yudao-cloud/pulls/177/
List<String> keysToModify = exchange.getResponse().getHeaders().entrySet().stream()
.filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
.filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
|| kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
keysToModify.forEach(key->{
List<String> values = exchange.getResponse().getHeaders().get(key);
if (values != null && !values.isEmpty()) {
exchange.getResponse().getHeaders().put(key, Collections.singletonList(values.get(0)));
}
});
return chain.filter(exchange);
}));
}
}

View File

@@ -0,0 +1,92 @@
package cn.iocoder.yudao.gateway.filter.logging;
import lombok.Data;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.http.HttpStatus;
import org.springframework.util.MultiValueMap;
import java.time.LocalDateTime;
/**
* 网关的访问日志
*/
@Data
public class AccessLog {
/**
* 链路追踪编号
*/
private String traceId;
/**
* 用户编号
*/
private Long userId;
/**
* 用户类型
*/
private Integer userType;
/**
* 路由
*
* 类似 ApiAccessLogCreateReqDTO 的 applicationName
*/
private Route route;
/**
* 协议
*/
private String schema;
/**
* 请求方法名
*/
private String requestMethod;
/**
* 访问地址
*/
private String requestUrl;
/**
* 查询参数
*/
private MultiValueMap<String, String> queryParams;
/**
* 请求体
*/
private String requestBody;
/**
* 请求头
*/
private MultiValueMap<String, String> requestHeaders;
/**
* 用户 IP
*/
private String userIp;
/**
* 响应体
*
* 类似 ApiAccessLogCreateReqDTO 的 resultCode + resultMsg
*/
private String responseBody;
/**
* 响应头
*/
private MultiValueMap<String, String> responseHeaders;
/**
* 响应结果
*/
private HttpStatus httpStatus;
/**
* 开始请求时间
*/
private LocalDateTime startTime;
/**
* 结束请求时间
*/
private LocalDateTime endTime;
/**
* 执行时长,单位:毫秒
*/
private Integer duration;
}

View File

@@ -0,0 +1,44 @@
package cn.iocoder.yudao.gateway.filter.security;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* 登录用户信息
*
* copy from yudao-spring-boot-starter-security 的 LoginUser 类
*
* @author 芋道源码
*/
@Data
public class LoginUser {
/**
* 用户编号
*/
private Long id;
/**
* 用户类型
*/
private Integer userType;
/**
* 额外的用户信息
*/
private Map<String, String> info;
/**
* 租户编号
*/
private Long tenantId;
/**
* 授权范围
*/
private List<String> scopes;
/**
* 过期时间
*/
private LocalDateTime expiresTime;
}

Some files were not shown because too many files have changed in this diff Show More