翻看了gateway中的控制RouteDefinition的累如下:
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository { private final Map<String, RouteDefinition> routes = synchronizedMap( new LinkedHashMap<String, RouteDefinition>()); @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.flatMap(r -> { if (StringUtils.isEmpty(r.getId())) { return Mono.error(new IllegalArgumentException("id may not be empty")); } routes.put(r.getId(), r); return Mono.empty(); }); } @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.flatMap(id -> { if (routes.containsKey(id)) { routes.remove(id); return Mono.empty(); } return Mono.defer(() -> Mono.error( new NotFoundException("RouteDefinition not found: " + routeId))); }); } @Override public Flux<RouteDefinition> getRouteDefinitions() { return Flux.fromIterable(routes.values()); } }
而且该类添加了条件判断了,如果有实现RouteDefinitionRepository接口的bean则不会初始化InMemoryRouteDefinitionRepository
@Bean @ConditionalOnMissingBean(RouteDefinitionRepository.class) public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() { return new InMemoryRouteDefinitionRepository(); } //这是在GatewayAutoConfiguration中的代码
所以我照猫画虎的搞了一个灵活的,这样就可以自由控制gateway中的route了。
package com.jd.ads.gateway.main; import com.alibaba.fastjson.JSON; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; 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.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.UriComponentsBuilder; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import javax.annotation.PostConstruct; import java.net.URI; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Created by zzq on 2020/5/28. */ @RestController @RequestMapping("/route-definition") public class AdsRouteDefinitionManager implements RouteDefinitionRepository, ApplicationEventPublisherAware { Map<String, RouteDefinition> routesMap = new ConcurrentHashMap<>(); @Autowired private RouteDefinitionWriter routeDefinitionWriter; private ApplicationEventPublisher publisher; @Override public Flux<RouteDefinition> getRouteDefinitions() { return Flux.fromIterable(routesMap.values()); } @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.flatMap(r -> { if (StringUtils.isEmpty(r.getId())) { return Mono.error(new IllegalArgumentException("id may not be empty")); } routesMap.put(r.getId(), r); return Mono.empty(); }); } @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.flatMap(id -> { if (routesMap.containsKey(id)) { routesMap.remove(id); return Mono.empty(); } return Mono.defer(() -> Mono.error( new NotFoundException("RouteDefinition not found: " + routeId))); }); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; } private void notifyChanged() { this.publisher.publishEvent(new RefreshRoutesEvent(this)); } /** * 增加路由 */ @PostMapping("/add") public String add(@RequestBody RouteDefinition definition) { String id = definition.getId(); if (routesMap.containsKey(id)) { return "already exists"; } routesMap.put(id, definition); notifyChanged(); return "success"; } /** * 更新路由 */ @PostMapping("/update") public String update(@RequestBody RouteDefinition definition) { try { String id = definition.getId(); if (routesMap.containsKey(id)) { routesMap.put(id, definition); return "success"; } return "not exists RouteDefinition"; } catch (Exception e) { return "update fail,not find route routeId: " + definition.getId(); } } /** * 删除路由 */ @GetMapping("/delete") public String delete(String id) { try { if (routesMap.containsKey(id)) { routesMap.remove(id); notifyChanged(); return "delete success"; } return "delete fail,id not exists"; } catch (Exception e) { e.printStackTrace(); return "delete fail"; } } @PostConstruct public void init() { RouteDefinition addMethod = getAddMethod(); routesMap.put(addMethod.getId(), addMethod); RouteDefinition deleteMethod = getDeleteMethod(); routesMap.put(deleteMethod.getId(), deleteMethod); RouteDefinition updateMethod = getUpdateMethod(); routesMap.put(updateMethod.getId(), updateMethod); } public RouteDefinition getAddMethod() { RouteDefinition definition = new RouteDefinition(); definition.setId("local-add"); URI uri = UriComponentsBuilder.fromUriString("forward:///route-definition/add").build().toUri(); definition.setUri(uri); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName("Path"); Map<String, String> predicateParams = new HashMap<>(8); predicateParams.put("pattern", "/route-definition/add"); predicate.setArgs(predicateParams); definition.setPredicates(new ArrayList<PredicateDefinition>() {{ add(predicate); }}); System.out.println("definition:" + JSON.toJSONString(definition)); return definition; } public RouteDefinition getUpdateMethod() { RouteDefinition definition = new RouteDefinition(); definition.setId("local-update"); URI uri = UriComponentsBuilder.fromUriString("forward:///route-definition/update").build().toUri(); definition.setUri(uri); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName("Path"); Map<String, String> predicateParams = new HashMap<>(8); predicateParams.put("pattern", "/route-definition/update"); predicate.setArgs(predicateParams); definition.setPredicates(new ArrayList<PredicateDefinition>() {{ add(predicate); }}); System.out.println("definition:" + JSON.toJSONString(definition)); return definition; } public RouteDefinition getDeleteMethod() { RouteDefinition definition = new RouteDefinition(); definition.setId("local-delete"); URI uri = UriComponentsBuilder.fromUriString("forward:///route-definition/delete").build().toUri(); definition.setUri(uri); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName("Path"); Map<String, String> predicateParams = new HashMap<>(8); predicateParams.put("pattern", "/route-definition/delete"); predicate.setArgs(predicateParams); definition.setPredicates(new ArrayList<PredicateDefinition>() {{ add(predicate); }}); System.out.println("definition:" + JSON.toJSONString(definition)); return definition; } } /* RouteDefinition definition = new RouteDefinition(); definition.setId("id1"); URI uri = UriComponentsBuilder.fromHttpUrl("http://127.0.0.1:8001/").build().toUri(); // URI uri = UriComponentsBuilder.fromHttpUrl("http://baidu.com").build().toUri(); definition.setUri(uri); //定义第一个断言 PredicateDefinition predicate = new PredicateDefinition(); predicate.setName("Path"); Map<String, String> predicateParams = new HashMap<>(8); predicateParams.put("pattern", "/post1"); predicate.setArgs(predicateParams); definition.setPredicates(new ArrayList<PredicateDefinition>() {{ add(predicate); }}); routesMap.put(definition.getId(), definition); System.out.println("definition:" + JSON.toJSONString(definition)); //定义Filter FilterDefinition filter = new FilterDefinition(); filter.setName("AddRequestHeader"); Map<String, String> filterParams = new HashMap<>(8); //该_genkey_前缀是固定的,见org.springframework.cloud.gateway.support.NameUtils类 filterParams.put("_genkey_0", "header"); filterParams.put("_genkey_1", "addHeader"); filter.setArgs(filterParams); FilterDefinition filter1 = new FilterDefinition(); filter1.setName("AddRequestParameter"); Map<String, String> filter1Params = new HashMap<>(8); filter1Params.put("_genkey_0", "param"); filter1Params.put("_genkey_1", "addParam"); filter1.setArgs(filter1Params); definition.setFilters(Arrays.asList(filter, filter1)); definition.setPredicates(Arrays.asList(predicate)); //*/ // System.out.println("definition:" + JSON.toJSONString(definition)