3.2.0-beta,重构很大:升级springboot2.6.6、spring-cloud-alibaba 2021.1、mybatisplus3.5.1、代码规范部分重构

This commit is contained in:
zhangdaiscott
2022-04-18 09:37:28 +08:00
parent d0b68919b3
commit 69ecb39c9e
487 changed files with 9754 additions and 2928 deletions

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-gateway
EXPOSE 9999
ADD ./target/jeecg-cloud-gateway-3.1.0.jar ./
ADD ./target/jeecg-cloud-gateway-3.2.0.jar ./
CMD sleep 50;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.1.0.jar
CMD sleep 50;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.2.0.jar

View File

@ -5,11 +5,11 @@
<parent>
<artifactId>jeecg-cloud-module</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-gateway</artifactId>
<dependencies>
<!-- jeecg 微服务基础依赖-->
<dependency>
@ -22,12 +22,22 @@
</exclusion>
</exclusions>
</dependency>
<!-- spring-cloud网关-->
<!-- Gateway网关依赖,内置webflux-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--sentinel断路器依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- redis方式限流 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!--sentinel 限流熔点降级-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
@ -36,46 +46,24 @@
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- sentinel集成nacos作为数据源 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--- sentinel流控链路不生效 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>
<!--Spring Webflux-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 熔断、降级 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--健康监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 限流Redis实现 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!--springboot2.X默认使用lettuce连接池需要引入commons-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--server-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- Swagger API文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>

View File

@ -1,7 +1,6 @@
package org.jeecg;
import org.jeecg.loader.DynamicRouteLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -1,19 +1,13 @@
package org.jeecg.config;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.handler.HystrixFallbackHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import javax.annotation.Resource;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
@ -26,25 +20,17 @@ import static org.springframework.web.reactive.function.server.ServerResponse.ok
@Slf4j
@Configuration
public class GatewayRoutersConfiguration {
public static final long DEFAULT_TIMEOUT = 30000;
public static String SERVER_ADDR;
public static String NAMESPACE;
public static String DATA_ID;
public static String ROUTE_GROUP;
public static String USERNAME;
public static String PASSWORD;
/**
* 路由配置文件数据获取方式yml,nacos,database
* 路由配置方式databaseymlnacos
*/
public static String DATA_TYPE;
public static final long DEFAULT_TIMEOUT = 30000;
public static String SERVER_ADDR;
public static String NAMESPACE;
public static String DATA_ID;
public static String ROUTE_GROUP;
public static String USERNAME;
public static String PASSWORD;
@Value("${spring.cloud.nacos.discovery.server-addr}")
public void setServerAddr(String serverAddr) {
@ -66,13 +52,16 @@ public class GatewayRoutersConfiguration {
ROUTE_GROUP = routeGroup;
}
@Value("${jeecg.route.config.data-type}")
public void setDataType(String dataType) { DATA_TYPE = dataType; }
@Value("${jeecg.route.config.data-type:#{null}}")
public void setDataType(String dataType) {
DATA_TYPE = dataType;
}
@Value("${spring.cloud.nacos.config.username}")
public void setUsername(String username) {
USERNAME = username;
}
@Value("${spring.cloud.nacos.config.password}")
public void setPassword(String password) {
PASSWORD = password;
@ -80,18 +69,8 @@ public class GatewayRoutersConfiguration {
/**
* 路由断言
* @return
*/
@Bean
public RouterFunction routerFunction() {
return RouterFunctions.route(
RequestPredicates.path("/globalFallback").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler);
}
/**
* 映射接口文档默认地址通过9999端口直接访问
* 接口地址通过9999端口直接访问
*
* @param indexHtml
* @return
*/
@ -100,7 +79,4 @@ public class GatewayRoutersConfiguration {
return route(GET("/"), request -> ok().contentType(MediaType.TEXT_HTML).syncBody(indexHtml));
}
@Resource
private HystrixFallbackHandler hystrixFallbackHandler;
}

View File

@ -1,32 +1,32 @@
package org.jeecg.fallback;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
/**
* 响应超时熔断处理器
*
* @author zyf
*/
@RestController
public class FallbackController {
/**
* 全局熔断处理
* @return
*/
@RequestMapping("/fallback")
public Mono<String> fallback() {
return Mono.just("访问超时,请稍后再试!");
}
/**
* demo熔断处理
* @return
*/
@RequestMapping("/demo/fallback")
public Mono<String> fallback2() {
return Mono.just("访问超时,请稍后再试!");
}
}
//package org.jeecg.fallback;
//
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//import reactor.core.publisher.Mono;
//
///**
// * 响应超时熔断处理器【升级springboot2.6.6后,此类作废】
// *
// * @author zyf
// */
//@RestController
//public class FallbackController {
//
// /**
// * 全局熔断处理
// * @return
// */
// @RequestMapping("/fallback")
// public Mono<String> fallback() {
// return Mono.just("访问超时,请稍后再试!");
// }
//
// /**
// * demo熔断处理
// * @return
// */
// @RequestMapping("/demo/fallback")
// public Mono<String> fallback2() {
// return Mono.just("访问超时,请稍后再试!");
// }
//}

View File

@ -0,0 +1,33 @@
//package org.jeecg.fallback;
//
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.http.HttpStatus;
//import org.springframework.stereotype.Component;
//import org.springframework.web.reactive.function.BodyInserters;
//import org.springframework.web.reactive.function.server.HandlerFunction;
//import org.springframework.web.reactive.function.server.ServerRequest;
//import org.springframework.web.reactive.function.server.ServerResponse;
//import reactor.core.publisher.Mono;
//
//import java.util.Optional;
//
//import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
//
///**
// * @author scott
// * @date 2020/05/26
// * Hystrix 降级处理
// */
//@Slf4j
//@Component
//public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
// @Override
// public Mono<ServerResponse> handle(ServerRequest serverRequest) {
// Optional<Object> originalUris = serverRequest.attribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
//
// originalUris.ifPresent(originalUri -> log.error("网关执行请求:{}失败,hystrix服务降级处理", originalUri));
//
// return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
// .header("Content-Type","text/plain; charset=utf-8").body(BodyInserters.fromObject("访问超时,请稍后再试"));
// }
//}

View File

@ -0,0 +1,45 @@
package org.jeecg.fallback.sentinel;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import org.jeecg.common.enums.SentinelErrorInfoEnum;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import javax.annotation.PostConstruct;
import java.util.HashMap;
/**
* @Description: 自定义Sentinel全局异常(需要启动Sentinel客户端)
* @author: zyf
* @date: 2022/02/18
* @version: V1.0
*/
@Configuration
public class GatewaySentinelExceptionConfig {
@PostConstruct
public void init() {
BlockRequestHandler blockRequestHandler = (serverWebExchange, ex) -> {
String msg;
SentinelErrorInfoEnum errorInfoEnum = SentinelErrorInfoEnum.getErrorByException(ex);
if (ObjectUtil.isNotEmpty(errorInfoEnum)) {
msg = errorInfoEnum.getError();
} else {
msg = "未知限流降级";
}
HashMap<String, String> map = new HashMap();
map.put("code", HttpStatus.TOO_MANY_REQUESTS.toString());
map.put("message", msg);
//自定义异常处理
return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}

View File

@ -0,0 +1,39 @@
//package org.jeecg.fallback.sentinel;
//import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
//import com.alibaba.csp.sentinel.transport.config.TransportConfig;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.commons.util.InetUtils;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
//import org.springframework.stereotype.Component;
//import org.springframework.web.reactive.function.BodyInserters;
//import org.springframework.web.reactive.function.server.ServerResponse;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Mono;
//
//import javax.annotation.PostConstruct;
//
///**
// * 自定义限流返回信息
// * @author scott
// */
//@Slf4j
//@Component
//public class SentinelBlockRequestHandler implements BlockRequestHandler {
// @Autowired
// private InetUtils inetUtils;
//
// @PostConstruct
// public void doInit() {
// System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
// }
//
// @Override
// public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
// String resultString = "{\"code\":403,\"message\":\"服务开启限流保护,请稍后再试!\"}";
// return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(resultString));
// }
//
//
//}

View File

@ -15,8 +15,13 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
/**
*
*/
* 全局拦截器,作用所有的微服务
*
* 1.重写StripPrefix(获取真实的URL)
* 2.将现在的request添加当前身份
* @author: scott
* @date: 2022/4/8 10:55
*/
@Slf4j
@Component
public class GlobalAccessTokenFilter implements GlobalFilter, Ordered {
@ -41,7 +46,7 @@ public class GlobalAccessTokenFilter implements GlobalFilter, Ordered {
ServerHttpRequest newRequest = exchange.getRequest().mutate().path(newPath).build();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
//将现在的request添加当前身份
//2.将现在的request添加当前身份
ServerHttpRequest mutableReq = exchange.getRequest().mutate().header("Authorization-UserName", "").header(X_GATEWAY_BASE_PATH,basePath).build();
ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
return chain.filter(mutableExchange);

View File

@ -6,7 +6,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Administrator
* @author: zyf
* @date: 20210715
*/
@Configuration
public class SentinelFilterContextConfig {

View File

@ -1,34 +0,0 @@
package org.jeecg.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.Optional;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
/**
* @author scott
* @date 2020/05/26
* Hystrix 降级处理
*/
@Slf4j
@Component
public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
@Override
public Mono<ServerResponse> handle(ServerRequest serverRequest) {
Optional<Object> originalUris = serverRequest.attribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
originalUris.ifPresent(originalUri -> log.error("网关执行请求:{}失败,hystrix服务降级处理", originalUri));
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.header("Content-Type","text/plain; charset=utf-8").body(BodyInserters.fromObject("访问超时,请稍后再试"));
}
}

View File

@ -2,18 +2,19 @@ package org.jeecg.handler;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.modules.redis.listener.JeecgRedisListerer;
import org.jeecg.common.constant.GlobalConstants;
import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
import org.jeecg.loader.DynamicRouteLoader;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 路由刷新监听
* 路由刷新监听实现方式redis监听handler
*/
@Slf4j
@Component
public class LoderRouderHandler implements JeecgRedisListerer {
@Component(GlobalConstants.LODER_ROUDER_HANDLER)
public class LoderRouderHandler implements JeecgRedisListener {
@Resource
private DynamicRouteLoader dynamicRouteLoader;

View File

@ -1,38 +0,0 @@
package org.jeecg.handler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
/**
* 自定义限流返回信息
* @author Administrator
*/
@Slf4j
@Component
public class SentinelBlockRequestHandler implements BlockRequestHandler {
@Autowired
private InetUtils inetUtils;
@PostConstruct
public void doInit() {
System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, inetUtils.findFirstNonLoopbackAddress().getHostAddress());
}
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
String resultString = "{\"code\":403,\"message\":\"服务开启限流保护,请稍后再试!\"}";
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON_UTF8).body(BodyInserters.fromObject(resultString));
}
}

View File

@ -1,20 +1,24 @@
package org.jeecg.handler;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
package org.jeecg.handler.swagger;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 聚合各个服务的swagger接口
*/
@ -32,6 +36,13 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
*/
private final RouteLocator routeLocator;
/**
* nacos服务地址
*/
@Value("${spring.cloud.nacos.discovery.server-addr}")
private String serverAddr;
/**
* 网关应用名称
*/
@ -50,7 +61,14 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
// 获取所有可用的hostserviceId
routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
.filter(route -> !self.equals(route.getUri().getHost()))
.subscribe(route -> routeHosts.add(route.getUri().getHost()));
.subscribe(route ->{
//update-begin---author:zyf ---date:20220413 for过滤掉无效路由,避免接口文档报错无法打开
boolean hasRoute=checkRoute(route.getId());
if(hasRoute){
routeHosts.add(route.getUri().getHost());
}
//update-end---author:zyf ---date:20220413 for过滤掉无效路由,避免接口文档报错无法打开
});
// 记录已经添加过的server存在同一个应用注册了多个服务在nacos上
Set<String> dealed = new HashSet<>();
@ -72,4 +90,23 @@ public class MySwaggerResourceProvider implements SwaggerResourcesProvider {
});
return resources;
}
/**
* 检测nacos中是否有健康实例
* @param routeId
* @return
*/
private Boolean checkRoute(String routeId) {
Boolean hasRoute = false;
try {
NamingService naming = NamingFactory.createNamingService(serverAddr);
List<Instance> list = naming.selectInstances(routeId, true);
if (ObjectUtil.isNotEmpty(list)) {
hasRoute = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return hasRoute;
}
}

View File

@ -1,4 +1,4 @@
package org.jeecg.handler;
package org.jeecg.handler.swagger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

View File

@ -10,17 +10,19 @@ import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.GatewayRoutersConfiguration;
import org.jeecg.config.RouterDataType;
import org.jeecg.loader.repository.DynamicRouteService;
import org.jeecg.loader.repository.MyInMemoryRouteDefinitionRepository;
import org.jeecg.loader.vo.MyRouteDefinition;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
@ -48,28 +50,26 @@ import java.util.concurrent.Executor;
public class DynamicRouteLoader implements ApplicationEventPublisherAware {
private MyInMemoryRouteDefinitionRepository repository;
private ApplicationEventPublisher publisher;
private InMemoryRouteDefinitionRepository repository;
private DynamicRouteService dynamicRouteService;
private ConfigService configService;
private RedisUtil redisUtil;
public DynamicRouteLoader(InMemoryRouteDefinitionRepository repository, DynamicRouteService dynamicRouteService, RedisUtil redisUtil) {
public DynamicRouteLoader(MyInMemoryRouteDefinitionRepository repository, DynamicRouteService dynamicRouteService, RedisUtil redisUtil) {
this.repository = repository;
this.dynamicRouteService = dynamicRouteService;
this.redisUtil = redisUtil;
}
@PostConstruct
public void init() {
init(null);
}
// @PostConstruct
// public void init() {
// init(null);
// }
public void init(BaseMap baseMap) {
String dataType = GatewayRoutersConfiguration.DATA_TYPE;
log.info("初始化路由dataType"+ dataType);
@ -138,7 +138,7 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
}
Object configInfo = redisUtil.get(CacheConstant.GATEWAY_ROUTES);
if (ObjectUtil.isNotEmpty(configInfo)) {
log.info("获取网关当前配置:\r\n{}", configInfo);
log.debug("获取网关当前配置:\r\n{}", configInfo);
JSONArray array = JSON.parseArray(configInfo.toString());
try {
routes = getRoutesByJson(array);
@ -147,7 +147,7 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
}
}
for (MyRouteDefinition definition : routes) {
log.info("update route : {}", definition.toString());
log.debug("update route : {}", definition.toString());
Integer status=definition.getStatus();
if(status.equals(0)){
dynamicRouteService.delete(definition.getId());
@ -156,9 +156,9 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
}
}
if(ObjectUtils.isNotEmpty(baseMap)){
String routerId=baseMap.get("routerId");
if(ObjectUtils.isNotEmpty(routerId)) {
dynamicRouteService.delete(routerId);
String delRouterId = baseMap.get("delRouterId");
if (ObjectUtils.isNotEmpty(delRouterId)) {
dynamicRouteService.delete(delRouterId);
}
}
this.publisher.publishEvent(new RefreshRoutesEvent(this));

View File

@ -1,15 +1,12 @@
package org.jeecg.loader;
package org.jeecg.loader.repository;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.loader.repository.MyInMemoryRouteDefinitionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@ -25,10 +22,7 @@ import reactor.core.publisher.Mono;
public class DynamicRouteService implements ApplicationEventPublisherAware {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private InMemoryRouteDefinitionRepository repository;
private MyInMemoryRouteDefinitionRepository repository;
/**
* 发布事件
@ -52,7 +46,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
repository.delete(Mono.just(id)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}catch (Exception e){
//e.printStackTrace();
log.warn(e.getMessage(),e);
}
}
@ -89,7 +83,7 @@ public class DynamicRouteService implements ApplicationEventPublisherAware {
try {
repository.save(Mono.just(definition)).subscribe();
} catch (Exception e) {
log.warn(e.getMessage(),e);
}
return "success";
}

View File

@ -0,0 +1,68 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.jeecg.loader.repository;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import ch.qos.logback.classic.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* @author qinfeng
*/
@Slf4j
@Component
public class MyInMemoryRouteDefinitionRepository implements RouteDefinitionRepository {
private final Map<String, RouteDefinition> routes = Collections.synchronizedMap(new LinkedHashMap());
public MyInMemoryRouteDefinitionRepository() {
}
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap((r) -> {
if (ObjectUtils.isEmpty(r.getId())) {
return Mono.error(new IllegalArgumentException("id may not be empty"));
} else {
this.routes.put(r.getId(), r);
return Mono.empty();
}
});
}
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap((id) -> {
if (this.routes.containsKey(id)) {
this.routes.remove(id);
return Mono.empty();
} else {
log.warn("RouteDefinition not found: " + routeId);
return Mono.empty();
// return Mono.defer(() -> {
// return Mono.error(new NotFoundException("RouteDefinition not found: " + routeId));
// });
}
});
}
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
Map<String, RouteDefinition> routesSafeCopy = new LinkedHashMap(this.routes);
return Flux.fromIterable(routesSafeCopy.values());
}
}

View File

@ -1,4 +1,4 @@
package org.jeecg.loader;
package org.jeecg.loader.vo;
import org.springframework.cloud.gateway.route.RouteDefinition;

View File

@ -3,14 +3,83 @@ server:
spring:
application:
name: jeecg-gateway
main:
#循环依赖默认情况下已经被禁止了
allow-circular-references: true
allow-bean-definition-overriding: true
cloud:
#Sentinel配置
sentinel:
web-context-unify: false
transport:
dashboard: localhost:8087
# 懒加载Sentinel Dashboard菜单
dashboard: jeecg-boot-sentinel:9000
# 支持链路限流
web-context-unify: false
filter:
enabled: false
# 取消Sentinel控制台懒加载
eager: false
datasource:
#流控规则
flow: # 指定数据源名称
# 指定nacos数据源
nacos:
server-addr: @config.server-addr@
# 指定配置文件
dataId: ${spring.application.name}-flow-rules
# 指定分组
groupId: SENTINEL_GROUP
# 指定配置文件规则类型
rule-type: flow
# 指定配置文件数据格式
data-type: json
#降级规则
degrade:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
rule-type: degrade
data-type: json
#系统规则
system:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-system-rules
groupId: SENTINEL_GROUP
rule-type: system
data-type: json
#授权规则
authority:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-authority-rules
groupId: SENTINEL_GROUP
rule-type: authority
data-type: json
#热点参数
param-flow:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-param-rules
groupId: SENTINEL_GROUP
rule-type: param-flow
data-type: json
#网关流控规则
gw-flow:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: gw-flow
data-type: json
#API流控规则
gw-api-group:
nacos:
server-addr: @config.server-addr@
dataId: ${spring.application.name}-api-rules
groupId: SENTINEL_GROUP
rule-type: gw-api-group
data-type: json
gateway:
discovery:
locator:
@ -19,11 +88,14 @@ spring:
cors-configurations:
'[/**]':
allowCredentials: true
allowedOrigins: "*"
#springboot2.4后需用allowedOriginPatterns
allowedOriginPatterns: "*"
allowedMethods: "*"
allowedHeaders: "*"
# #如果启用nacos或者数据库配置请删除一下配置
# routes:
# httpclient:
# connect-timeout: 1000
# response-timeout: 5s
# # Nacos的yml方式路由配置(默认注释掉,采用数据库加载)
# - id: jeecg-demo
# uri: lb://jeecg-demo
# predicates:
@ -39,30 +111,4 @@ spring:
# - id: jeecg-demo-websocket
# uri: lb:ws://jeecg-demo
# predicates:
# - Path=/vxeSocket/**
# 全局熔断降级配置
default-filters:
- name: Hystrix
args:
name: default
#转发地址
fallbackUri: 'forward:/fallback'
- name: Retry
args:
#重试次数,默认值是 3 次
retries: 3
#HTTP 的状态返回码
statuses: BAD_GATEWAY,BAD_REQUEST
#指定哪些方法的请求需要进行重试逻辑,默认值是 GET 方法
methods: GET,POST
# hystrix 信号量隔离3秒后自动超时
hystrix:
enabled: true
shareSecurityContext: true
command:
default:
execution:
isolation:
strategy: SEMAPHORE
thread:
timeoutInMilliseconds: 9000
# - Path=/vxeSocket/**