springcloud<zuul动态路由重写>
配置类: package com.wangbiao.config.dynamic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description TODO * @date 2021/4/11 18:35 */ @Configuration public class DynamicRouteConfiguration { @Autowired private ZuulProperties zuulProperties; @Autowired private ServerProperties server; @Autowired private JdbcTemplate jdbcTemplate; @Bean public DynamicRouteLocator routeLocator() { DynamicRouteLocator routeLocator = new DynamicRouteLocator(this.server.getServlet().getContextPath(), this.zuulProperties,this.jdbcTemplate); return routeLocator; } }
package com.wangbiao.config.dynamic; import com.google.common.base.Strings; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; 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.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.util.StringUtils; import java.util.*; import java.util.stream.Collectors; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description 重写refresh locateRoutes()两个方法进行动态路由加载 * @date 2021/4/11 16:43 */ @Slf4j public class DynamicRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator { private ZuulProperties properties; private JdbcTemplate jdbcTemplate; public DynamicRouteLocator(String servletPath, ZuulProperties properties, JdbcTemplate jdbcTemplate) { super(servletPath, properties); this.properties = properties; this.jdbcTemplate = jdbcTemplate; log.info("servletPath:{}",servletPath); } @Override public void refresh() { doRefresh(); } @Override protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() { LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<String, ZuulProperties.ZuulRoute>(); //从配置文件中加载路由信息 routesMap.putAll(super.locateRoutes()); //自定义加载路由信息 routesMap.putAll(getRouteList()); //优化一下配置 LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>(); for (Map.Entry<String, ZuulProperties.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; } /** * 从数据库读取zuul路由规则 * @return */ private LinkedHashMap<String, ZuulProperties.ZuulRoute> getRouteList() { LinkedHashMap<String, ZuulProperties.ZuulRoute> zuulRoutes = new LinkedHashMap<>(); List<ZuulProperties.ZuulRoute> sysZuulRoutes = jdbcTemplate.query("select * from sys_zuul_route where del_flag = 0", new BeanPropertyRowMapper<>(ZuulProperties.ZuulRoute.class)); for (ZuulProperties.ZuulRoute route: sysZuulRoutes) { // 为空跳过 if (Strings.isNullOrEmpty(route.getPath()) && Strings.isNullOrEmpty(route.getUrl())) { continue; } ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute(); try { zuulRoute.setId(route.getServiceId()); zuulRoute.setPath(route.getPath()); zuulRoute.setServiceId(route.getServiceId()); zuulRoute.setRetryable(Objects.equals("0", route.getRetryable()) ? Boolean.FALSE : Boolean.TRUE); zuulRoute.setStripPrefix(Objects.equals("0", route.isStripPrefix()) ? Boolean.FALSE : Boolean.TRUE); zuulRoute.setUrl(route.getUrl()); List<String> sensitiveHeadersList = Arrays.asList(route.getSensitiveHeaders().stream().collect(Collectors.joining()).split(",")); if (sensitiveHeadersList != null) { Set<String> sensitiveHeaderSet = Sets.newHashSet(); sensitiveHeadersList.forEach(sensitiveHeader -> sensitiveHeaderSet.add(sensitiveHeader)); zuulRoute.setSensitiveHeaders(sensitiveHeaderSet); zuulRoute.setCustomSensitiveHeaders(true); } } catch (Exception e) { log.error("数据库加载配置异常", e); } log.info("自定义的路由配置,path:{},serviceId:{}", zuulRoute.getPath(), zuulRoute.getServiceId()); zuulRoutes.put(zuulRoute.getPath(), zuulRoute); } return zuulRoutes; } }
如有需要控制层手动刷新 package com.wangbiao.config.dynamic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description TODO * @date 2021/4/11 17:32 */ @RestController public class RefreshController { @Autowired private RefreshRouteService refreshRouteService; @GetMapping("/refresh") public String refresh() { refreshRouteService.refreshRoute(); return "refresh"; } }
路由刷新事件发布,与事件监听者 package com.wangbiao.config.dynamic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; import org.springframework.cloud.netflix.zuul.RoutesRefreshedEvent; import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Service; /** * TODO * * @author wangbiao * @Title TODO * @module TODO * @description 路由刷新事件发布,与事件监听者 * @date 2021/4/11 17:22 */ @Service public class RefreshRouteService implements ApplicationListener<ApplicationEvent> { @Autowired private ZuulHandlerMapping zuulHandlerMapping; private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); @Autowired private ApplicationEventPublisher publisher; @Autowired private DynamicRouteLocator dynamicRouteLocator; /** * 动态路由实现 调用refreshRoute() 发布刷新路由事件 */ public void refreshRoute() { RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(dynamicRouteLocator); publisher.publishEvent(routesRefreshedEvent); } /** * 事件监听者。监控检测事件刷新 * @param event */ @Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof RoutesRefreshedEvent){ //主动手动刷新。上下文刷新,配置属性刷新 zuulHandlerMapping.setDirty(true); }else if(event instanceof HeartbeatEvent){ //心跳触发,将本地映射关系。关联到远程服务上 HeartbeatEvent heartbeatEvent = (HeartbeatEvent)event; if(heartbeatMonitor.update(heartbeatEvent.getValue())){ zuulHandlerMapping.setDirty(true); } } } }
sql: /* Navicat Premium Data Transfer Source Server : root Source Server Type : MySQL Source Server Version : 80016 Source Host : localhost:3306 Source Schema : zuul Target Server Type : MySQL Target Server Version : 80016 File Encoding : 65001 Date: 08/04/2022 22:47:52 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for sys_zuul_route -- ---------------------------- DROP TABLE IF EXISTS `sys_zuul_route`; CREATE TABLE `sys_zuul_route` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'router Id', `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '路由路径', `service_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '服务名称', `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'url代理', `strip_prefix` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '转发去掉前缀', `retryable` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '是否重试', `enabled` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '1' COMMENT '是否启用', `sensitiveHeaders_list` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '敏感请求头', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '0' COMMENT '删除标识(0-正常,1-删除)', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '动态路由配置表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of sys_zuul_route -- ---------------------------- INSERT INTO `sys_zuul_route` VALUES (9, '/wangbiao/**', 'cloud-pay-server', NULL, '1', '1', '1', NULL, '2021-04-11 17:44:29', NULL, '0'); INSERT INTO `sys_zuul_route` VALUES (10, '/user/**', 'cloud-user-server', NULL, '1', '1', '1', NULL, '2021-04-11 17:46:09', NULL, '0'); SET FOREIGN_KEY_CHECKS = 1;
一点点学习,一丝丝进步。不懈怠,才不会被时代淘汰