官方教程讲的都是提前在配置文件中配置网关,而在实际工作中不可能随便重启网关服务,这时动态配置就急需要解决;
动态网关配置:redis mysql gateway2.0.1;
具体代码在mall-gateway模块:https://github.com/ssy-githup/spring-cloud-mall
环境:idea jdk1.8 初始化mysql数据库:mall_sys.sql;
简介:
toBaidu:这个代表的是跳转链接
toPrduct:代表调用SERVICE-PRODUCT服务(测试此服务需要eureka和service-product服务);
核心类:
@Configuration
public class InitBean {
@Bean
public MyRouteDefinitionRepository mysqlRouteDefinitionRepository() {
return new MyRouteDefinitionRepository();
}
/**
* 配置跨域
* @return
*/
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// cookie跨域
config.setAllowCredentials(Boolean.TRUE);
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
// 配置前端js允许访问的自定义响应头
//也可以设置限制某些
config.addExposedHeader("setToken");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new HiddenHttpMethodFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
}
};
}
}
刷新路由API:http://127.0.0.1:8888/gateway/reset
@Service
public class GatewayDefineServiceImpl implements GatewayDefineService {
@Autowired
GatewayDefineMapper gatewayDefineMapper;
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
private RedisTemplate redisTemplate;
/**
* @Title reset
* @Description: 更新redis缓存,同时触发监听,更新路由缓存
* @Date: 2019/10/23 9:40
*/
public void reset() throws Exception{
List<GatewayDefine> gatewayDefineServiceAll = gatewayDefineMapper.findAll();
CacheHelper.saveCache("gateway_rotus", JSON.toJSONString(gatewayDefineServiceAll));
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
}
自定义过滤器:AuthSignatureFilter
/**
* getaway过滤率器
*/
@Component
public class AuthSignatureFilter implements GlobalFilter, Ordered {
public final static String ATTRIBUTE_IGNORE_GLOBAL_FILTER = "@ignoreGlobalFilter";
/**
* 拦截请求,获取authToken,校验
* @param exchange
* @param chain
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//从消息头中获取token,根据业务需要进行设置吧
String token = exchange.getRequest().getHeaders().getFirst("token");
Consumer<HttpHeaders> httpHeaders = httpHeader -> {
//获取ip放入请求头
//这里这样做是为了下游可以从消息头获取到对应参数
httpHeader.set("USER-AUTHENTICITY-IP", getIpAddress(exchange.getRequest()));
System.out.println("=========httpHeader="+httpHeader+"=================");
httpHeader.set("token", token);
};
//打印参数的封装map
Map data = new HashMap();
// 部分路由不进行token验证
if (exchange.getAttribute(ATTRIBUTE_IGNORE_GLOBAL_FILTER) != null) {
System.out.println("IgnoreGlobalFilter:"+exchange.getRequest().getPath().value());
ServerHttpRequest serverHttpRequest = exchange.getRequest();
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
}
//token验证
ServerHttpRequest serverHttpRequest = exchange.getRequest();
String method = serverHttpRequest.getMethodValue();
serverHttpRequest = exchange.getRequest().mutate().headers(httpHeaders).build();
String serviceMode = serverHttpRequest.getQueryParams().getFirst("mode");
data.put("token",token);
data.put("url",serverHttpRequest.getPath().value());
data.put("mode","parseToken");
if("GET".equals(method) || StringUtils.isNotBlank(serviceMode)){
data.put("serviceMode",serviceMode);
//模拟某些系连接需要被禁止:比如验证token
if("forbidn".equals(token)){
System.out.println("get:"+serverHttpRequest.getPath().value()+"--"+serviceMode);
System.out.println("==============请====================");
System.out.println("================求==================");
System.out.println("=================被=================");
System.out.println("===================禁===============");
System.out.println("=====================止=============");
System.out.println("==================================");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange.mutate().request(serverHttpRequest).build());
}else if ("POST".equals(method)) {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
//==========================================
//和get请求一样进行token验证
//这里只对get和post请求进行了处理,只是演示使用;不具备生产环境使用,
// 请慎重!!!
// 请慎重!!!
//==========================================
DataBufferUtils.release(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory()
.wrap(bytes);
return Mono.just(buffer);
});
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
mutatedRequest = mutatedRequest.mutate().headers(httpHeaders).build();
System.out.println("post:"+mutatedRequest.getPath().value()+"--"+data.get("serviceMode"));
return chain.filter(exchange.mutate().request(mutatedRequest)
.build());
});
}
return chain.filter(exchange);
}
}
测试跳转:http://127.0.0.1:8888/tobaidu
测试调用服务:http://127.0.0.1:8888/product/profile