feat:first commit gateway
This commit is contained in:
84
pom.xml
84
pom.xml
@@ -21,9 +21,87 @@
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>17</java.version>
|
||||
<spring.boot.version>2.7.18</spring.boot.version>
|
||||
<spring.cloud.version>2021.0.8</spring.cloud.version>
|
||||
<spring.cloud.alibaba.version>2021.1</spring.cloud.alibaba.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Cloud Gateway(核心) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
<version>3.1.8</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot WebFlux(必须,Netty 容器) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Nacos 服务发现 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>${spring.cloud.alibaba.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Actuator(可选:健康检查 & 调试路由) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok(可选,简化开发) -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Spring Boot 打包插件 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- 编译器插件 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -17,4 +17,12 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xiang</groupId>
|
||||
<artifactId>xs-service</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -2,12 +2,14 @@ package com.xiang;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
|
||||
/**
|
||||
* @Author: xiang
|
||||
* @Date: 2025-08-12 17:26
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
|
||||
public class XsGatewayApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XsGatewayApplication.class, args);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.xiang.xservice.gateway.server.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class ServiceDiscoveryController {
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
/**
|
||||
* 查看所有注册到 Nacos 的服务
|
||||
*/
|
||||
@GetMapping("/services")
|
||||
public List<String> getServices() {
|
||||
return discoveryClient.getServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看某个服务的实例信息
|
||||
*/
|
||||
@GetMapping("/services/instances")
|
||||
public Object getServiceInstances(String serviceName) {
|
||||
return discoveryClient.getInstances(serviceName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
server:
|
||||
port: 38010
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: xservice-gateway
|
||||
main:
|
||||
web-application-type: reactive # 强制使用 WebFlux
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: general.xiangtech.xyz:8848
|
||||
namespace: 00131110-3ecb-4a35-8bbb-624edde1d937
|
||||
group: DEFAULT_GROUP
|
||||
username: nacos
|
||||
password: nacos
|
||||
gateway:
|
||||
discovery:
|
||||
locator:
|
||||
enabled: true # 开启 nacos 自动路由
|
||||
routes:
|
||||
- id: xservice-auth-center
|
||||
uri: lb://xservice-auth-center
|
||||
predicates:
|
||||
- Path=/api-auth/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
redis:
|
||||
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
||||
port: 6379
|
||||
password: Xiang0000 # 如果无密码可以省略
|
||||
database: 0
|
||||
timeout: 5000
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8
|
||||
max-idle: 8
|
||||
min-idle: 0
|
||||
max-wait: 1000
|
||||
@@ -4,3 +4,5 @@ server:
|
||||
spring:
|
||||
profiles:
|
||||
active: local
|
||||
main:
|
||||
web-application-type: reactive
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.xiang.xservice.gateway.service.core;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
String path = request.getURI().getPath();
|
||||
// 放行 /public/** 和 /login
|
||||
if (path.contains("/public/") || path.contains("/login")) {
|
||||
log.debug("跳过 Token 校验: {}", path);
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
// 获取 Header 中的 Authorization
|
||||
String token = request.getHeaders().getFirst("Authorization");
|
||||
|
||||
if (!StringUtils.hasText(token)) {
|
||||
log.warn("❌ 缺少 Token: {}", path);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: 这里换成你自己的 JwtUtil.verify(token)
|
||||
// boolean valid = JwtUtil.verify(token);
|
||||
if (false) {
|
||||
log.warn("❌ Token 校验失败: {}", token);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("❌ Token 校验异常", e);
|
||||
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
return exchange.getResponse().setComplete();
|
||||
}
|
||||
|
||||
log.info("✅ Token 校验通过: {}", token);
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.xiang.xservice.gateway.service.core;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.route.Route;
|
||||
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LoggerGlobalFilter implements GlobalFilter, Ordered {
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
log.info("🌐 Gateway 请求进入, 原始请求路径:{}", exchange.getRequest().getURI().getPath());
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
InetSocketAddress remoteAddress = request.getRemoteAddress();
|
||||
log.info("请求路径: {} | 方法: {} | 来源: {} | 匹配到路由:{}, 转发目标地址:{}",
|
||||
request.getURI(),
|
||||
request.getMethod(),
|
||||
remoteAddress != null ? remoteAddress.getHostString() : "unknown",
|
||||
exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR),
|
||||
exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR));
|
||||
|
||||
// 继续执行过滤链
|
||||
return chain.filter(exchange)
|
||||
.then(Mono.fromRunnable(() -> {
|
||||
log.info("响应状态: {}", exchange.getResponse().getStatusCode());
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user