spring-cloud-zuul Mysql 实现动态路由以及手动刷新

     本文建立在spring-cloud-zuul环境搭建的基础上进行扩展介绍。

介绍

     实现zuul的动态路由可通过两种方式

           1. 基于配置中心实现配置文件动态刷新

           2.基于数据库存储配置文件,发布 RoutesRefreshedEvent 事件,触发 SimpleRouteLocator 重新加载配置

实现步骤

1.数据库初始化

CREATE TABLE `zuul_route` (
  `id` varchar(50) NOT NULL,
  `path` varchar(255) NOT NULL,
  `service_id` varchar(50) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `strip_prefix` tinyint(1) DEFAULT '1',
  `retryable` tinyint(1) DEFAULT '0',
  `enabled` tinyint(1) NOT NULL DEFAULT '1',
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert  into `zuul_route`(`id`,`path`,`service_id`,`url`,`strip_prefix`,`retryable`,`enabled`,`description`) values ('pppp','/client/**',NULL,'http://localhost:7070',1,0,1,'url');

2.配置文件

server:
  port: 8080
eureka:
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:8000/eureka/   #注册中心地址
    registry-fetch-interval-seconds: 15    #客户端拉取服务端的频率
spring:
  application:
    name: zuul
  datasource:
    url: jdbc:mysql://rm-bp1e5s5co.mysql.rds.aliyuncs.com:3306/zuul?useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    username: rook
    password: Hou5
ribbon:
  eureka:
    enabled: true

3.数据库访问 

public class ZuulRouteEntity {
	
	private String id;

	private String path;
	
	private String serviceId;

	private String url;

	private boolean stripPrefix = true;

	private Boolean retryable;

	private Boolean enabled;
	
	private String description;
}

@Component
public class PropertiesDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	private final static String SQL = "SELECT * FROM zuul_route WHERE enabled = TRUE";
	
	public Map<String, ZuulRoute> getProperties() {
		Map<String, ZuulRoute> routes = new LinkedHashMap<>();
		List<ZuulRouteEntity> list = jdbcTemplate.query(SQL, new BeanPropertyRowMapper<>(ZuulRouteEntity.class));
		list.forEach(entity -> {
			if (StringUtils.isEmpty(entity.getPath())) {
				return;
			}
			ZuulRoute zuulRoute = new ZuulRoute();
			BeanUtils.copyProperties(entity, zuulRoute);
			routes.put(zuulRoute.getPath(), zuulRoute);
		});
		return routes;
	}
}

4.重写理由配置加载方法

import org.springframework.beans.factory.annotation.Autowired;
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;

/**
 * @author houkai
 */
public class DynamicZuulRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {

	@Autowired
	private ZuulProperties properties;

	@Autowired
	private PropertiesDao propertiesDao;

	public DynamicZuulRouteLocator(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<>();
		routesMap.putAll(super.locateRoutes());
		routesMap.putAll(propertiesDao.getProperties());
		LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
		routesMap.forEach((key, value) -> {
			String path = key;
			if (!path.startsWith("/")) {
				path = "/" + path;
			}
			if (StringUtils.hasText(this.properties.getPrefix())) {
				path = this.properties.getPrefix() + path;
				if (!path.startsWith("/")) {
					path = "/" + path;
				}
			}
			values.put(path, value);
		});
		return values;
	}
}

@Configuration
public class DynamicZuulConfig {

	@Autowired
	private ZuulProperties zuulProperties;
	
	@Autowired
	private ServerProperties serverProperties;
	
	@Bean
	public DynamicZuulRouteLocator routeLocator() {
		DynamicZuulRouteLocator routeLocator = new DynamicZuulRouteLocator(
				serverProperties.getServlet().getContextPath(), zuulProperties);
		return routeLocator;
	}
}

5.刷新接口

@RestController
public class RefreshController {
    @Autowired
    private ApplicationEventPublisher publisher;
    @Autowired
    private RouteLocator routeLocator;
    @Autowired
    private ZuulHandlerMapping zuulHandlerMapping;

    @GetMapping("refreshRoute")
    public String refreshRoute() {
        RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator);
        publisher.publishEvent(routesRefreshedEvent);
        return "refresh success";
    }

    @GetMapping("watchRoute")
    public Object watchNowRoute() {
        //可以用debug模式看里面具体是什么
        return zuulHandlerMapping.getHandlerMap();
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值