美文网首页
springcloud2020版本使用zuul和nacos服务发

springcloud2020版本使用zuul和nacos服务发

作者: 夜辰啊 | 来源:发表于2021-10-11 13:05 被阅读0次

    spirngcloud版本 2020.0.3
    springcloud.alibaba 2021.1

    ZuulHandlerBeanPostProcessor

    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.boot.web.servlet.error.ErrorController;
    import org.springframework.cglib.proxy.*;
    import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
    import org.springframework.cloud.netflix.zuul.web.ZuulController;
    import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Objects;
    
    
    @Component
    @Slf4j
    public class ZuulHandlerBeanPostProcessor {
    
        /**
         * 自定义拦截器
         */
        @Resource
        private TokenHandlerInterceptor tokenHandlerInterceptor;
    
        /**
         * The path returned by ErrorContoller.getErrorPath() with Spring Boot < 2.5 (and no longer available on Spring Boot >= 2.5).
         */
        private static final String ERROR_PATH = "/error";
    
        /**
         * Constructs a new bean post-processor for Zuul.
         *
         * @param routeLocator    the route locator.
         * @param zuulController  the Zuul controller.
         * @param errorController the error controller.
         * @return the new bean post-processor.
         */
        @Bean
        public ZuulPostProcessor zuulPostProcessor(@Autowired RouteLocator routeLocator, @Autowired ZuulController zuulController,
                                                   @Autowired(required = false) ErrorController errorController) {
            return new ZuulPostProcessor(routeLocator, zuulController, errorController, tokenHandlerInterceptor);
        }
    
        private static final class ZuulPostProcessor implements BeanPostProcessor {
    
            private final RouteLocator routeLocator;
    
            private final ZuulController zuulController;
    
            private final boolean hasErrorController;
    
            private TokenHandlerInterceptor tokenHandlerInterceptor;
    
            ZuulPostProcessor(RouteLocator routeLocator, ZuulController zuulController, ErrorController errorController, TokenHandlerInterceptor tokenHandlerInterceptor) {
                this.routeLocator = routeLocator;
                this.zuulController = zuulController;
                this.hasErrorController = (errorController != null);
                this.tokenHandlerInterceptor = tokenHandlerInterceptor;
            }
    
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (hasErrorController && (bean instanceof ZuulHandlerMapping)) {
                    Enhancer enhancer = new Enhancer();
                    enhancer.setSuperclass(ZuulHandlerMapping.class);
                    enhancer.setCallbackFilter(LookupHandlerCallbackFilter.INSTANCE); // only for lookupHandler
                    enhancer.setCallbacks(new Callback[]{LookupHandlerMethodInterceptor.INSTANCE, NoOp.INSTANCE});
                    Constructor<?> ctor = ZuulHandlerMapping.class.getConstructors()[0];
                    ZuulHandlerMapping zuulHandlerMapping = (ZuulHandlerMapping) enhancer.create(ctor.getParameterTypes(), new Object[]{routeLocator, zuulController});
                    zuulHandlerMapping.setInterceptors(tokenHandlerInterceptor);
    //   生成ZuulHandlerMapping代理类后需要执行initInterceptors (如果需要使用拦截器的话)
                    try {
                        Method method = null;
                        for (Class<?> clazz = bean.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
                            try {
                                method = clazz.getDeclaredMethod("initInterceptors");
                                if (Objects.nonNull(method)){
                                    break;
                                }
                            } catch (Exception e) {
                            }
                        }
                        method.setAccessible(true);
                        method.invoke(zuulHandlerMapping);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                       log.error("invoke zuulHandlerMapping initInterceptors() error ",e);
                    }
                    return zuulHandlerMapping;
                }
                return bean;
            }
    
        }
    
        private enum LookupHandlerCallbackFilter implements CallbackFilter {
    
            INSTANCE;
    
            @Override
            public int accept(Method method) {
                if ("lookupHandler".equals(method.getName())) {
                    return 0;
                }
                return 1;
            }
    
        }
    
        private enum LookupHandlerMethodInterceptor implements MethodInterceptor {
    
            INSTANCE;
    
            @Override
            public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if (ERROR_PATH.equals(args[0])) {
    
                    /* by entering this branch we avoid the ZuulHandlerMapping.lookupHandler method to trigger the NoSuchMethodError */
                    return null;
                }
                return methodProxy.invokeSuper(target, args);
            }
    
        }
    
    
    }
    
    

    RibbonCusClientConfig

    @Configuration(proxyBeanMethods = false)
    @Lazy
    public class RibbonCusClientConfig  {
    
        @Autowired
        private PropertiesFactory propertiesFactory;
    
        @Autowired
        private NacosDiscoveryClient discoveryClient;
    
        @Value("${ribbon.client.name:client}")
        private String name = "client";
    
        @Autowired
        private Environment environment;
    
    
        public static final int DEFAULT_CONNECT_TIMEOUT = 1000;
    
        /**
         * Ribbon client default read timeout.
         */
        public static final int DEFAULT_READ_TIMEOUT = 1000;
    
        /**
         * Ribbon client default Gzip Payload flag.
         */
        public static final boolean DEFAULT_GZIP_PAYLOAD = true;
    
        @Bean
        @ConditionalOnMissingBean
        public IClientConfig ribbonClientConfig() {
            DefaultClientConfigImpl config = new DefaultClientConfigImpl();
    
            config.loadProperties(this.name);
    
            config.set(CommonClientConfigKey.ConnectTimeout, getProperty(
                    CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT));
    
            config.set(CommonClientConfigKey.ReadTimeout,
                    getProperty(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT));
    
            config.set(CommonClientConfigKey.GZipPayload, DEFAULT_GZIP_PAYLOAD);
            return config;
        }
    
        private Integer getProperty(IClientConfigKey<Integer> connectTimeout,
                                    int defaultConnectTimeout) {
            return environment.getProperty("ribbon." + connectTimeout, Integer.class,
                    defaultConnectTimeout);
        }
    
    
        @Bean
        @ConditionalOnMissingBean
        @SuppressWarnings("unchecked")
        public ServerList<Server> ribbonServerList(IClientConfig config) {
    //        IClientConfig config=new DefaultClientConfigImpl();
            RequestContext context = RequestContext.getCurrentContext();
            String serviceId = (String) context.get(SERVICE_ID_KEY);
            if (this.propertiesFactory.isSet(ServerList.class, serviceId)) {
                return this.propertiesFactory.get(ServerList.class, config, serviceId);
            }
            NacosServerList serverList = new NacosServerList(discoveryClient, serviceId);
            serverList.initWithNiwsConfig(config);
            return serverList;
        }
    
    
    }
    
    

    NacosServerList

    public class NacosServerList extends AbstractServerList {
    
        private IClientConfig clientConfig;
    
        private DiscoveryClient discoveryClient;
    
        public String name;
    
        public NacosServerList(DiscoveryClient discoveryClient,String name) {
            this.discoveryClient = discoveryClient;
            this.name = name;
        }
    
        @Override
        public List<Server> getInitialListOfServers() {
            return getUpdatedListOfServers();
        }
    
        @Override
        public List<Server> getUpdatedListOfServers() {
            List<Server> list = Lists.newArrayList();
            List<ServiceInstance> instances = discoveryClient.getInstances(name);
            for (ServiceInstance instance : instances) {
                list.add(new Server(instance.getScheme(), instance.getHost(), instance.getPort()));
            }
            return list;
        }
    
        @Override
        public void initWithNiwsConfig(IClientConfig clientConfig) {
            this.clientConfig = clientConfig;
        }
    
    }
    
    
    <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
                <version>2.2.9.RELEASE</version>
    <!--            <exclusions>-->
    <!--                <exclusion>-->
    <!--                    <groupId>com.netflix.servo</groupId>-->
    <!--                    <artifactId>servo-core</artifactId>-->
    <!--                </exclusion>-->
    <!--            </exclusions>-->
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.netflix.servo/servo-core -->
            <dependency>
                <groupId>com.netflix.servo</groupId>
                <artifactId>servo-core</artifactId>
                <version>0.13.2</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
    

    相关文章

      网友评论

          本文标题:springcloud2020版本使用zuul和nacos服务发

          本文链接:https://www.haomeiwen.com/subject/rculoltx.html