feat:first commit gateway
This commit is contained in:
84
pom.xml
84
pom.xml
@@ -21,9 +21,87 @@
|
|||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<java.version>17</java.version>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<spring.boot.version>2.7.18</spring.boot.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<spring.cloud.version>2021.0.8</spring.cloud.version>
|
||||||
|
<spring.cloud.alibaba.version>2021.1</spring.cloud.alibaba.version>
|
||||||
</properties>
|
</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>
|
</project>
|
||||||
@@ -17,4 +17,12 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.xiang</groupId>
|
||||||
|
<artifactId>xs-service</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -2,12 +2,14 @@ package com.xiang;
|
|||||||
|
|
||||||
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.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: xiang
|
* @Author: xiang
|
||||||
* @Date: 2025-08-12 17:26
|
* @Date: 2025-08-12 17:26
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
|
||||||
public class XsGatewayApplication {
|
public class XsGatewayApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(XsGatewayApplication.class, 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
|
||||||
@@ -3,4 +3,6 @@ server:
|
|||||||
|
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: local
|
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