spring cloud gateway实现动态配置(持久化到mysql)网关-附源码

官方教程讲的都是提前在配置文件中配置网关,而在实际工作中不可能随便重启网关服务,这时动态配置就急需要解决;
动态网关配置: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

你可能感兴趣的:(积累)