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

原文地址:https://www.cnblogs.com/raorao1994/p/9546496.html