mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-03 20:35:29 +08:00
3.2.0-beta,重构很大:升级springboot2.6.6、spring-cloud-alibaba 2021.1、mybatisplus3.5.1、代码规范部分重构
This commit is contained in:
@ -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;
|
||||
|
||||
@ -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
|
||||
* 路由配置方式:database,yml,nacos
|
||||
*/
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@ -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("访问超时,请稍后再试!");
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -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("访问超时,请稍后再试"));
|
||||
// }
|
||||
//}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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("访问超时,请稍后再试"));
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 {
|
||||
// 获取所有可用的host:serviceId
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
@ -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));
|
||||
|
||||
@ -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";
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jeecg.loader;
|
||||
package org.jeecg.loader.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package org.jeecg.loader;
|
||||
package org.jeecg.loader.vo;
|
||||
|
||||
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||
|
||||
@ -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/**
|
||||
Reference in New Issue
Block a user