springcloud的网关(三)gateway之动态过滤器
程序员文章站
2024-02-15 19:04:35
...
一:关于动态过滤器
在整个网关系统中,我们看到无论在yml中还是java中配置过滤器,过滤器都是配置死了的。换而言之,当我们需要配置新的过滤规则就要需要重新配置,重启网关服务,这明显是不科学的。我们可以这样考虑如果我们可以动态配置且不需要重启项目就能新增路由规则。
二:动态路由的管理
动态路由的配置是配置在jvm的内存中。我们可以将每次的对外配置暴露并持久化保持,并定时加载持久化中配置的。
三:动态路由的代码管理
动态路由id,跳转url,一组断言和一组过滤器组成。这样上述可以组成一个或者多个实体类。
1.实体配置
package com.zypcy.springcloud.gateway.enetity;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 断言
* zhuyu 2019-01-17
*/
public class GatewayPredicateDefinition {
//断言对应的Name
private String name;
//配置的断言规则
private Map<String, String> args = new LinkedHashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getArgs() {
return args;
}
public void setArgs(Map<String, String> args) {
this.args = args;
}
}
package com.zypcy.springcloud.gateway.enetity;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 过滤器模型
* zhuyu 2019-01-17
*/
public class GatewayFilterDefinition {
//Filter Name
private String name;
//对应的路由规则
private Map<String, String> args = new LinkedHashMap<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<String, String> getArgs() {
return args;
}
public void setArgs(Map<String, String> args) {
this.args = args;
}
}
package com.zypcy.springcloud.gateway.enetity;
import java.util.ArrayList;
import java.util.List;
/**
* 路由模型
* zhuyu 2019-01-17
*/
public class GatewayRouteDefinition {
//路由的Id
private String id;
//路由断言集合配置
private List<GatewayPredicateDefinition> predicates = new ArrayList<>();
//路由过滤器集合配置
private List<GatewayFilterDefinition> filters = new ArrayList<>();
//路由规则转发的目标uri
private String uri;
//路由执行的顺序
private int order = 0;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<GatewayPredicateDefinition> getPredicates() {
return predicates;
}
public void setPredicates(List<GatewayPredicateDefinition> predicates) {
this.predicates = predicates;
}
public List<GatewayFilterDefinition> getFilters() {
return filters;
}
public void setFilters(List<GatewayFilterDefinition> filters) {
this.filters = filters;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
2.业务层配置(主要实现内部的路由机制的增删改查)
package com.zypcy.springcloud.gateway.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
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;
/**
* 业务层,实现路由的增删改查
*
*
* @author monxz
*
* @date 2019年6月6日
*/
@Service
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware{
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
//增加路由
public String add(RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
}
//更新路由
public String update(RouteDefinition definition) {
try {
delete(definition.getId());
} catch (Exception e) {
return "update fail,not find route routeId: "+definition.getId();
}
try {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
this.publisher.publishEvent(new RefreshRoutesEvent(this));
return "success";
} catch (Exception e) {
return "update route fail";
}
}
//删除路由
public Mono<ResponseEntity<Object>> delete(String id) {
return this.routeDefinitionWriter.delete(Mono.just(id)).then(Mono.defer(() -> {
return Mono.just(ResponseEntity.ok().build());
})).onErrorResume((t) -> {
return t instanceof NotFoundException;
}, (t) -> {
return Mono.just(ResponseEntity.notFound().build());
});
}
}
3.controller的配置对外暴露的方法
package com.zypcy.springcloud.gateway.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import com.zypcy.springcloud.gateway.enetity.GatewayFilterDefinition;
import com.zypcy.springcloud.gateway.enetity.GatewayPredicateDefinition;
import com.zypcy.springcloud.gateway.enetity.GatewayRouteDefinition;
import com.zypcy.springcloud.gateway.service.DynamicRouteServiceImpl;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
/**
* 路由的方法
*
*
* @author monxz
*
* @date 2019年6月6日
*/
@RestController
@RequestMapping("/route")
public class RouteController {
@Autowired
private DynamicRouteServiceImpl dynamicRouteService;
//增加路由
@PostMapping("/add")
public String add(@RequestBody GatewayRouteDefinition gwdefinition) {
String flag = "fail";
try {
RouteDefinition definition = assembleRouteDefinition(gwdefinition);
flag = this.dynamicRouteService.add(definition);
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
//删除路由
@GetMapping("/del/{id}")
public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
try {
return this.dynamicRouteService.delete(id);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
//更新路由
@PostMapping("/update")
public String update(@RequestBody GatewayRouteDefinition gwdefinition) {
RouteDefinition definition = assembleRouteDefinition(gwdefinition);
return this.dynamicRouteService.update(definition);
}
//把前端传递的参数转换成路由对象
private RouteDefinition assembleRouteDefinition(GatewayRouteDefinition gwdefinition) {
RouteDefinition definition = new RouteDefinition();
definition.setId(gwdefinition.getId());
definition.setOrder(gwdefinition.getOrder());
//设置断言
List<PredicateDefinition> pdList=new ArrayList<>();
List<GatewayPredicateDefinition> gatewayPredicateDefinitionList=gwdefinition.getPredicates();
for (GatewayPredicateDefinition gpDefinition: gatewayPredicateDefinitionList) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setArgs(gpDefinition.getArgs());
predicate.setName(gpDefinition.getName());
pdList.add(predicate);
}
definition.setPredicates(pdList);
//设置过滤器
List<FilterDefinition> filters = new ArrayList();
List<GatewayFilterDefinition> gatewayFilters = gwdefinition.getFilters();
for(GatewayFilterDefinition filterDefinition : gatewayFilters){
FilterDefinition filter = new FilterDefinition();
filter.setName(filterDefinition.getName());
filter.setArgs(filterDefinition.getArgs());
filters.add(filter);
}
definition.setFilters(filters);
URI uri = null;
if(gwdefinition.getUri().startsWith("http")){
uri = UriComponentsBuilder.fromHttpUrl(gwdefinition.getUri()).build().toUri();
}else{
uri = URI.create(gwdefinition.getUri());
}
definition.setUri(uri);
return definition;
}
}
4.yml中配置内部的路由暴露
# 暴露端点
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
上一篇: vue项目笔记(23)-动态路由传值及iconfont更新使用
下一篇: OSPF的触发更新过程: