提交 6c472893 编写于 作者: zlt2000's avatar zlt2000

zuul增加动态路由

上级 bd764da8
......@@ -100,6 +100,11 @@
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
......
package com.central.gateway.config;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.central.gateway.route.nacos.NacosDynRouteLocator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 动态路由配置
*
* @author zlt
* @date 2019/8/21
*/
@Configuration
@ConditionalOnProperty(prefix = "zlt.gateway.dynamicRoute", name = "enabled", havingValue = "true")
public class DynamicZuulRouteConfig {
@Autowired
private ZuulProperties zuulProperties;
@Autowired
private DispatcherServletPath dispatcherServletPath;
/**
* Nacos实现方式
*/
@Configuration
@ConditionalOnProperty(prefix = "zlt.gateway.dynamicRoute", name = "dataType", havingValue = "nacos", matchIfMissing = true)
public class NacosZuulRoute {
@Autowired
private NacosConfigProperties nacosConfigProperties;
@Autowired
private ApplicationEventPublisher publisher;
@Bean
public NacosDynRouteLocator nacosDynRouteLocator() {
return new NacosDynRouteLocator(nacosConfigProperties, publisher, dispatcherServletPath.getPrefix(), zuulProperties);
}
}
}
package com.central.gateway.config;
import lombok.Getter;
import lombok.Setter;
/**
* zuul路由实体
*
* @author zlt
* @date 2019/8/21
*/
@Setter
@Getter
public class ZuulRouteEntity {
/**
* The ID of the route (the same as its map key by default).
*/
private String id;
/**
* The path (pattern) for the route, e.g. /foo/**.
*/
private String path;
/**
* The service ID (if any) to map to this route. You can specify a
* physical URL or a service, but not both.
*/
private String serviceId;
/**
* A full physical URL to map to the route. An alternative is to use a
* service ID and service discovery to find the physical address.
*/
private String url;
/**
* Flag to determine whether the prefix for this route (the path, minus
* pattern patcher) should be stripped before forwarding.
*/
private boolean stripPrefix = true;
/**
* Flag to indicate that this route should be retryable (if supported).
* Generally retry requires a service ID and ribbon.
*/
private Boolean retryable;
private String apiName;
private boolean enabled = true;
private boolean customSensitiveHeaders = true;
}
package com.central.gateway.route;
import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 扩展 {@link SimpleRouteLocator} 实现动态路由
*
* @author zlt
* @date 2019/8/21
*/
public abstract class AbstractDynRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
private ZuulProperties properties;
public AbstractDynRouteLocator(String servletPath, ZuulProperties properties) {
super(servletPath, properties);
this.properties = properties;
}
/**
* 刷新路由
*/
@Override
public void refresh() {
doRefresh();
}
@Override
protected Map<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();
// 从application.properties中加载静态路由信息
routesMap.putAll(super.locateRoutes());
// 从数据源中加载动态路由信息
routesMap.putAll(loadDynamicRoute());
// 优化一下配置
LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
for (Map.Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
String path = entry.getKey();
// Prepend with slash if not already present.
if (!path.startsWith("/")) {
path = "/" + path;
}
if (StringUtils.hasText(this.properties.getPrefix())) {
path = this.properties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
}
values.put(path, entry.getValue());
}
return values;
}
/**
* 加载路由配置,由子类去实现
*/
public abstract Map<String, ZuulRoute> loadDynamicRoute();
}
package com.central.gateway.route.nacos;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.central.gateway.config.ZuulRouteEntity;
import com.central.gateway.route.AbstractDynRouteLocator;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties.ZuulRoute;
import org.springframework.context.ApplicationEventPublisher;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
/**
* Nacos动态路由实现类
*
* @author zlt
* @date 2019/8/22
*/
@Slf4j
public class NacosDynRouteLocator extends AbstractDynRouteLocator {
private static final String ZUUL_DATA_ID = "zuul-routes";
private static final String ZUUL_GROUP_ID = "ZUUL_GATEWAY";
private NacosConfigProperties nacosConfigProperties;
private ApplicationEventPublisher publisher;
private NacosDynRouteLocator locator;
@Setter
private List<ZuulRouteEntity> zuulRouteEntities;
public NacosDynRouteLocator(NacosConfigProperties nacosConfigProperties, ApplicationEventPublisher publisher,
String servletPath, ZuulProperties properties) {
super(servletPath, properties);
this.nacosConfigProperties = nacosConfigProperties;
this.publisher = publisher;
this.locator = this;
addListener();
}
/**
* 添加Nacos监听
*/
private void addListener() {
try {
nacosConfigProperties.configServiceInstance().addListener(ZUUL_DATA_ID, ZUUL_GROUP_ID, new Listener() {
@Override
public Executor getExecutor() {
return null;
}
@Override
public void receiveConfigInfo(String configInfo) {
//赋值路由信息
locator.setZuulRouteEntities(getListByStr(configInfo));
RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(locator);
publisher.publishEvent(routesRefreshedEvent);
}
});
} catch (NacosException e) {
log.error("nacos-addListener-error", e);
}
}
@Override
public Map<String, ZuulProperties.ZuulRoute> loadDynamicRoute() {
Map<String, ZuulRoute> routes = new LinkedHashMap<>();
if (zuulRouteEntities == null) {
zuulRouteEntities = getNacosConfig();
}
for (ZuulRouteEntity result : zuulRouteEntities) {
if (StrUtil.isBlank(result.getPath()) || !result.isEnabled()) {
continue;
}
ZuulRoute zuulRoute = new ZuulRoute();
BeanUtil.copyProperties(result, zuulRoute);
routes.put(zuulRoute.getPath(), zuulRoute);
}
return routes;
}
/**
* 查询zuul的路由配置
*/
private List<ZuulRouteEntity> getNacosConfig() {
try {
String content = nacosConfigProperties.configServiceInstance().getConfig(ZUUL_DATA_ID, ZUUL_GROUP_ID,5000);
return getListByStr(content);
} catch (NacosException e) {
log.error("listenerNacos-error", e);
}
return new ArrayList<>(0);
}
public List<ZuulRouteEntity> getListByStr(String content) {
if (StrUtil.isNotEmpty(content)) {
return JSONObject.parseArray(content, ZuulRouteEntity.class);
}
return new ArrayList<>(0);
}
}
{
"properties": [
{
"name": "zlt.gateway.dynamicRoute.enabled",
"description": "是否开启动态路由.",
"type": "java.lang.Boolean",
"defaultValue": false
},
{
"name": "zlt.gateway.dynamicRoute.dataType",
"description": "动态路由的数据类型.",
"type": "java.lang.String",
"defaultValue": "nacos"
}
]
}
\ No newline at end of file
......@@ -26,10 +26,6 @@ spring:
groupId: DEFAULT_GROUP
rule-type: gw-api-group
security:
sessions: ALWAYS
zlt:
oauth2:
token:
......@@ -39,7 +35,6 @@ zlt:
ignore:
# 忽略认证的地址
httpUrls: >
/api-user/test,
/api-uaa/oauth/**,
/api-uaa/validata/**,
/api-uaa/css/**,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册