• SpringCloud-Zuul搭建


    一、创建工程,在pom中引入Zuul

    二、重写路由加载类,实在路由的动态注册和路由转发

    package com.genius.gateway.zuul;
    
    import com.genius.gateway.helper.DbHelper;
    import com.genius.gateway.model.ZuulRouteKV;
    import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator;
    import org.springframework.cloud.netflix.zuul.filters.Route;
    import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
    import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
    
    
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    
    import  org.slf4j.Logger ;
    import  org.slf4j.LoggerFactory ;
    import org.springframework.jdbc.core.BeanPropertyRowMapper;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.util.StringUtils;
    
    
    public class CustomRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
    
        public final static Logger logger=LoggerFactory.getLogger(CustomRouteLocator.class);
    
        private JdbcTemplate jdbcTemplate;
        private DbHelper dbHelper;
        public void setDbHelper(DbHelper dbHelper){
            this.dbHelper=dbHelper;
        }
    
    
        private ZuulProperties properties;
    
        //设置数据库连接
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
            this.jdbcTemplate=jdbcTemplate;
        }
    
        public CustomRouteLocator(String servletPah,ZuulProperties properties){
            super(servletPah,properties);
            this.properties=properties;
            logger.info("servletPath:{}",servletPah);
        }
    
    
        @Override
        public void refresh() {
            doRefresh();
        }
    
        /**
         *加载路由规则
         */
        @Override
        protected Map<String,ZuulProperties.ZuulRoute> locateRoutes(){
            LinkedHashMap<String,ZuulProperties.ZuulRoute> routesMap=new LinkedHashMap<String,ZuulProperties.ZuulRoute>();
            //从application.properties中加载路由信息
            routesMap.putAll(super.locateRoutes());
            //从db中加载路由信息
            routesMap.putAll(locateRoutesFromDB());
            //优化一下配置
            LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
            for (Map.Entry<String, ZuulProperties.ZuulRoute> entry : routesMap.entrySet()) {
                String path = entry.getKey();
                // 如果还没有出现,就用斜杠准备。
                if (!path.startsWith("/")) {
                    path = "/" + path;
                }
                if (StringUtils.hasText(this.properties.getPrefix())) {
                    path = this.properties.getPrefix() + path;
                    if (!path.startsWith("/")) {
                        path = "/" + path;
                    }
                }
                values.put(path, entry.getValue());
            }
            return values;
        }
    
        /*
        * 加载路由数据
        * */
        private Map<String,ZuulProperties.ZuulRoute> locateRoutesFromDB(){
            Map<String,ZuulProperties.ZuulRoute> routes=new LinkedHashMap<>();
            System.out.println("=============load zuul route info from db ==============");
            //从数据库中加载数据
            String sql="select t.*, t.rowid from PIPECLOUD.ZUULROUTE t where t.enabled=1";
            sql="select * from zuulroute where enabled=true";
            List<ZuulRouteKV> result=jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(ZuulRouteKV.class));
            //List<ZuulRouteKV> result= dbHelper.GetRoutesData();
            //遍历数据
            for(ZuulRouteKV item:result){
                if(org.apache.commons.lang3.StringUtils.isBlank(item.getPath()) || org.apache.commons.lang3.StringUtils.isBlank(item.getUrl()) ){
                    continue;
                }
                ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
                try {
                    //org.springframework.beans.BeanUtils.copyProperties(result,zuulRoute);
                    zuulRoute.setId(item.getId());
                    zuulRoute.setPath(item.getPath());
                    zuulRoute.setServiceId(item.getServiceId());
                    zuulRoute.setStripPrefix(item.isStripPrefix());
                    zuulRoute.setUrl(item.getUrl());
                } catch (Exception e) {
                    logger.error("=============load zuul route info from db with error==============",e);
                }
                routes.put(zuulRoute.getPath(),zuulRoute);
            }
            return routes;
        }
    
        /**
         * 获取路由
         */
        @Override
        protected Route getRoute(ZuulProperties.ZuulRoute route, String path) {
            if (route == null) {
                return null;
            } else {
                String targetPath = path;
                String prefix = this.properties.getPrefix();
                if (prefix.endsWith("/")) {
                    prefix = prefix.substring(0, prefix.length() - 1);
                }
    
                if (path.startsWith(prefix + "/") && this.properties.isStripPrefix()) {
                    targetPath = path.substring(prefix.length());
                }
    
                if (route.isStripPrefix()) {
    
                    //源码
    //                int index = route.getPath().indexOf("*") - 1;
    //                if (index > 0) {
    //                    String routePrefix = route.getPath().substring(0, index);
    //                    targetPath = targetPath.replaceFirst(routePrefix, "");
    //                    prefix = prefix + routePrefix;
    //                }
    
                    //重构方法
                    int spliccount=route.getPath().split("/").length-1;
                    if(spliccount>0){
                        String[] paths=targetPath.split("/");
                        String indexStr=paths[spliccount]+"/";
                        int index1=targetPath.indexOf(indexStr)-1;
                        if(index1>0){
                            prefix=targetPath.substring(0,index1);
                            targetPath=targetPath.substring(index1);
                        }
                    }
    
                }
    
                Boolean retryable = this.properties.getRetryable();
                if (route.getRetryable() != null) {
                    retryable = route.getRetryable();
                }
    
                //负载均衡
                String hostStr=route.getUrl();
                String Location=hostStr;
                String[] hosts=hostStr.split(";");
                if(hosts.length>1){
                    Random random=new Random();
                    int index=random.nextInt(hosts.length);
                    Location=hosts[index];
                }
    
                return new Route(route.getId(), targetPath, Location, prefix, retryable, route.isCustomSensitiveHeaders() ? route.getSensitiveHeaders() : null, route.isStripPrefix());
            }
        }
    }
    View Code
    @Configuration
    public class CustomZuulConfig {
    
        @Autowired
        ZuulProperties zuulProperties;
        @Autowired
        ServerProperties server;
        @Autowired
        JdbcTemplate jdbcTemplate;
    
        //@Autowired
        //DbHelper dbHelper;
    
        @Bean
        public CustomRouteLocator routeLocator(){
            String path=this.server.getServlet().getServletPrefix();
            CustomRouteLocator reouteLocator=new CustomRouteLocator(path, this.zuulProperties);
            reouteLocator.setJdbcTemplate(jdbcTemplate);
            //reouteLocator.setDbHelper(dbHelper);
            return reouteLocator;
        }
    }
    View Code
    @Service
    public class RefreshRouteService {
    
        @Autowired
        ApplicationEventPublisher publisher;
    
        @Autowired
        RouteLocator routeLocator;
    
        //刷新路由配置信息
        public void refreshRoute() {
            RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator);
            publisher.publishEvent(routesRefreshedEvent);
        }
    }
    View Code
    @RestController
    @RequestMapping("/admin")
    public class AdminController {
    
        @RequestMapping("/index")
        public  String index(){
            return "index";
        }
    
        @Autowired
        RefreshRouteService server;
    
        @RequestMapping("/refreshRoute")
        public String refreshRoute(){
            server.refreshRoute();
            return "路由重置成功!";
        }
    }
    View Code

    三、跨域请求过滤器

    /**
     * 实现跨域请求
     * #防止header重复写入
     * zuul.sensitive-headers=Access-Control-Allow-Origin,Access-Control-Allow-Method
     */
    @Configuration
    public class GateWayCorsConfig {
        @Bean
        public FilterRegistrationBean corsFilter() {
            final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            final CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.addAllowedOrigin("*");
            config.addAllowedHeader("*");
            config.addAllowedMethod("*");
            //这个请求头在https中会出现,但是有点问题,下面我会说
            //config.addExposedHeader("X-forwared-port, X-forwarded-host");
            source.registerCorsConfiguration("/**", config);
            FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
            bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return bean;
        }
    }
    View Code

    https://blog.csdn.net/tianyaleixiaowu/article/details/77933295?locationNum=5&fps=1

    https://www.cnblogs.com/sam-uncle/p/9011400.html

  • 相关阅读:
    subplots
    异步方法:用async关键字修饰的方法
    async、await原理揭秘
    TCP/IP概述
    EFCore中的IEnumerable和IQueryable的不同之处
    IQueryable底层是如何读取数据的?
    二叉树性质
    几种查找算法
    EFCore中所谓IQueryable
    常用位运算
  • 原文地址:https://www.cnblogs.com/raorao1994/p/9546496.html
Copyright © 2020-2023  润新知