mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-20 02:08:15 +08:00
添加 网关模块
This commit is contained in:
parent
ff1c729385
commit
7da40951e7
7
pom.xml
7
pom.xml
@ -31,6 +31,7 @@
|
||||
<hutool.version>5.7.11</hutool.version>
|
||||
<guava.version>29.0-jre</guava.version>
|
||||
<feign.version>3.0.3</feign.version>
|
||||
<gateway.version>3.0.3</gateway.version>
|
||||
<feign-okhttp.version>11.6</feign-okhttp.version>
|
||||
<okhttp.version>4.9.1</okhttp.version>
|
||||
<spring-boot-admin.version>2.5.1</spring-boot-admin.version>
|
||||
@ -155,6 +156,12 @@
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
<version>${gateway.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
<modules>
|
||||
<module>ruoyi-monitor-admin</module>
|
||||
<module>ruoyi-isc-gateway</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
45
ruoyi-extend/ruoyi-isc-gateway/pom.xml
Normal file
45
ruoyi-extend/ruoyi-isc-gateway/pom.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?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>ruoyi-vue-plus</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.1.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-isc-gateway</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<!-- pool 对象池 -->
|
||||
<!--<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>-->
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,20 @@
|
||||
package com.ruoyi.gateway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-09-11
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class GatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
System.out.println("Gateway 启动成功" );
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.ruoyi.gateway.config;
|
||||
|
||||
import com.ruoyi.gateway.config.provider.ComplexRouteDefinitionRepository;
|
||||
import com.ruoyi.gateway.config.provider.RedisRouteDefinitionRepository;
|
||||
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Gateway 配置文件
|
||||
*
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-09-11
|
||||
*/
|
||||
@Configuration
|
||||
public class GatewayConfig {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, RouteDefinition> redisTemplate;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, RouteDefinition> redisTemplate(RedisConnectionFactory redisConnectionFactory)
|
||||
{
|
||||
final RedisTemplate<String, RouteDefinition> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(redisConnectionFactory);
|
||||
Jackson2JsonRedisSerializer<RouteDefinition> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(RouteDefinition.class);
|
||||
template.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
template.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
|
||||
template.setKeySerializer(stringRedisSerializer);
|
||||
template.setHashKeySerializer(stringRedisSerializer);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouteDefinitionRepository complexRouteDefinitionRepository()
|
||||
{
|
||||
return new ComplexRouteDefinitionRepository(inMemoryRouteDefinitionRepository(), redisRouteDefinitionRepository());
|
||||
}
|
||||
|
||||
/**
|
||||
* 内存 路由仓库
|
||||
*
|
||||
* @return 本地内存路由仓库
|
||||
*/
|
||||
RouteDefinitionRepository inMemoryRouteDefinitionRepository()
|
||||
{
|
||||
return new InMemoryRouteDefinitionRepository();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redis 路由仓库
|
||||
*
|
||||
* @return redis路由仓库
|
||||
*/
|
||||
RouteDefinitionRepository redisRouteDefinitionRepository()
|
||||
{
|
||||
return new RedisRouteDefinitionRepository(redisTemplate);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.ruoyi.gateway.config.provider;
|
||||
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 复合的路由存储器
|
||||
*
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-09-11
|
||||
*/
|
||||
public class ComplexRouteDefinitionRepository implements RouteDefinitionRepository {
|
||||
|
||||
private RouteDefinitionRepository localCache;
|
||||
private RouteDefinitionRepository remoteReps;
|
||||
|
||||
public ComplexRouteDefinitionRepository(RouteDefinitionRepository localCache, RouteDefinitionRepository remoteReps)
|
||||
{
|
||||
this.localCache = localCache;
|
||||
this.remoteReps = remoteReps;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Flux<RouteDefinition> getRouteDefinitions()
|
||||
{
|
||||
final Flux<RouteDefinition> routeDefinitions = localCache.getRouteDefinitions();
|
||||
return routeDefinitions.collectList().flatMapIterable(list -> {
|
||||
if(list.isEmpty()) {
|
||||
final Flux<RouteDefinition> definitions = remoteReps.getRouteDefinitions();
|
||||
definitions.collectList().flatMapIterable(routes -> {
|
||||
if(!routes.isEmpty()) {
|
||||
routes.stream().map(m -> {
|
||||
routes.add(m);
|
||||
return Mono.just(m);
|
||||
}).forEach(m -> {
|
||||
localCache.save(m);
|
||||
});
|
||||
}
|
||||
return routes;
|
||||
}).filter(l -> Objects.nonNull(l)).map(m -> list.add(m)).collectList();
|
||||
}
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> save(Mono<RouteDefinition> route)
|
||||
{
|
||||
remoteReps.save(route);
|
||||
return localCache.save(route);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> delete(Mono<String> routeId)
|
||||
{
|
||||
remoteReps.delete(routeId);
|
||||
return localCache.delete(routeId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.ruoyi.gateway.config.provider;
|
||||
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Redis 路由仓库
|
||||
*
|
||||
* @author Wenchao Gong
|
||||
* @date 2021-09-11
|
||||
*/
|
||||
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
|
||||
public static final String KEY_ROUTES = "ROUTES::";
|
||||
private final RedisTemplate<String, RouteDefinition> redisTemplate;
|
||||
|
||||
public RedisRouteDefinitionRepository(RedisTemplate<String, RouteDefinition> redisTemplate)
|
||||
{
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<RouteDefinition> getRouteDefinitions()
|
||||
{
|
||||
List<RouteDefinition> values = redisTemplate.<String,RouteDefinition>opsForHash().values(KEY_ROUTES);
|
||||
return Flux.fromIterable(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> save(Mono<RouteDefinition> route)
|
||||
{
|
||||
return route.flatMap(definition -> {
|
||||
redisTemplate.opsForHash().put(KEY_ROUTES, definition.getId(), definition);
|
||||
return Mono.empty();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> delete(Mono<String> routeId)
|
||||
{
|
||||
return routeId.flatMap(id -> {
|
||||
redisTemplate.opsForHash().delete(KEY_ROUTES, id);
|
||||
return Mono.empty();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
--- # 监控配置
|
||||
spring:
|
||||
boot:
|
||||
admin:
|
||||
# Spring Boot Admin Client 客户端的相关配置
|
||||
client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
# 设置 Spring Boot Admin Server 地址
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
prefer-ip: true # 注册实例时,优先使用 IP
|
||||
username: ruoyi
|
||||
password: 123456
|
||||
|
||||
--- # redis 配置
|
||||
spring:
|
||||
redis:
|
||||
# 地址
|
||||
host: 192.168.64.128
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码
|
||||
password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
ssl: false
|
||||
|
||||
--- # Actuator 监控端点的配置项
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||
base-path: /actuator
|
||||
exposure:
|
||||
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||
include: @endpoints.include@
|
||||
endpoint:
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
@ -0,0 +1,8 @@
|
||||
server:
|
||||
port: 8090
|
||||
# Spring配置
|
||||
spring:
|
||||
application:
|
||||
name: RuoYi-Gateway
|
||||
profiles:
|
||||
active: @profiles.active@
|
||||
114
ruoyi-extend/ruoyi-isc-gateway/src/main/resources/logback.xml
Normal file
114
ruoyi-extend/ruoyi-isc-gateway/src/main/resources/logback.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<property name="log.path" value="./logs"/>
|
||||
<property name="console.log.pattern"
|
||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %green([%thread]) %boldMagenta(%logger{36}) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-info.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 用户访问日志输出 -->
|
||||
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/sys-user.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 按天回滚 daily -->
|
||||
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.ruoyi" level="info" />
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn" />
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info" />
|
||||
<appender-ref ref="file_error" />
|
||||
<appender-ref ref="file_console" />
|
||||
</root>
|
||||
|
||||
<!--系统用户操作日志-->
|
||||
<logger name="sys-user" level="info">
|
||||
<appender-ref ref="sys-user"/>
|
||||
</logger>
|
||||
</configuration>
|
||||
Loading…
Reference in New Issue
Block a user