gateway动态路由

实体类:

@Data
public class AppRoute implements Serializable {
    private Integer id;
    private String routeId;
    private Integer exeseq;
    private String uri;
    private String predicates;
    private String filters;
    private Date createTime;
    private Date updateTime;
    private Integer state;
}

监听:

@Service
public class RouteHandler implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    /**
     * 刷新路由方法
     * RefreshRouteLocator 会监听该事件,在收到 RefreshRoutesEvent 事件后, 会清空缓存信息,待下次请求时重新加载路由信息并缓存
     */
    public void refreshRoutes() {
        publisher.publishEvent(new RefreshRoutesEvent(this));
    }

}

初始化路由

@Component
public class RouteStartListener {
    private static final Logger logger = LoggerFactory.getLogger(RouteStartListener.class);

    @Autowired
    RouteDefinitionRepository repository;

    @Autowired
    AppRouteService routeService;

    @Autowired
    RefreshRouteLocator refreshRouteLocator;

    /**
     * 类加载时读取数据到缓存
     */
    @PostConstruct
    public void init() {
        logger.info("..................................初始化路由数据................................................");
        List<AppRoute> routeList = routeService.findAll();
        if (routeList != null && routeList.size() > 0) {
            routeList.forEach(e ->{
                Mono<RouteDefinition> routeDefinitionMono = Mono.just(new RouteDefinition(e.toString()));
                logger.info("..................................写路由信息到缓存................................................");
                repository.save(routeDefinitionMono);
            });
        }
    }

    @Bean
    public void routes() {
        refreshRouteLocator.buildRoutes();
    }
}

刷新路由

/**
 * 刷新路由服务
 */
@Component
public class RefreshRouteLocator implements RouteLocator  {

    private static Logger log = LoggerFactory.getLogger(RefreshRouteLocator.class);

    private Flux<Route> route;
    private RouteLocatorBuilder builder;
    private RouteLocatorBuilder.Builder routesBuilder;

    @Autowired
    AppRouteServiceImpl appRouteService;

    @Autowired
    private RouteHandler routeHandler;

    @Autowired
    RouteDefinitionRepository repository;

    public RefreshRouteLocator(RouteLocatorBuilder builder) {
        this.builder = builder;
        clearRoutes();
    }

    public void clearRoutes() {
        routesBuilder = builder.routes();
    }


    /**
     * 配置完成后,调用本方法全量构建路由和刷新路由表
     */
    public void buildRoutes() {
        log.info("---------清空路由------------");
        clearRoutes();
        if (routesBuilder != null) {
            log.info("---------从数据库读取新数据,全量刷新路由------------");
            appRouteService.findAll().forEach(serviceDefinition ->{
                String serviceId = serviceDefinition.getRouteId();
                // 拼成 uri + path 请求路径
                String url = serviceDefinition.getUri();
                String predicates = serviceDefinition.getPredicates();
                String[] filterNames = serviceDefinition.getFilters().split(",");
                URI uri = UriComponentsBuilder.fromHttpUrl(url + predicates).build().toUri();
                List<GatewayFilter> filters = buildFilters(filterNames);
                routesBuilder.route(serviceId, r -> r.path(predicates).filters(e ->e.filters(filters)).uri(uri));
            });
           route = routesBuilder.build().getRoutes();
        }
        routeHandler.refreshRoutes();
    }

    /**
     * 反射生成GatewayFilter
     * @param filterNames
     * @return
     */
    private List<GatewayFilter> buildFilters(String[] filterNames) {
        List<GatewayFilter> filters = new ArrayList<>();
        for (String filterName : filterNames){
            //反射生成
            Class aClass = null;
            try {
                aClass = Class.forName(filterName);
                System.out.println(aClass.getName());
                filters.add((GatewayFilter)aClass.newInstance());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        };
        return filters;
    }


    @Override
    public Flux<Route> getRoutes() {
        return route;
    }
}

测试Contro

@RestController
@RequestMapping(value = "/app/route")
public class AppRouteAction {

    private AppRouteService appRouteService;


    @Autowired
    public void setAppRouteService(AppRouteService appRouteService) {
        this.appRouteService = appRouteService;
    }

    @GetMapping(value = "/list")
    public JsonResult list() {
        List<AppRoute> all = appRouteService.findAll();
        return new JsonResult(true,all);
    }


    @PostMapping(value = "/save")
    public JsonResult save(@RequestBody AppRoute route) {
        System.out.println("-------------route----------route----------route-----------"+route);
        if (route == null || StringUtils.isBlank(route.getRouteId())) {
            return new JsonResult(false,null, "id不能为空");
        } else if (StringUtils.isBlank(route.getUri())) {
            return new JsonResult(false, null,"uri不能为空");
        }else if (StringUtils.isBlank(route.getPredicates())) {
            return new JsonResult(false, null,"Predicates不能为空");
        }

        AppRoute sameRouteIdObj = appRouteService.findByRouteId(route.getRouteId());
        if (sameRouteIdObj != null) {
                return new JsonResult(false,null, "已存在相同 RouteId 的配置");
        }
        route.setPredicates(route.getPredicates() != null ? route.getPredicates().trim() : null);
        route.setFilters(route.getFilters() != null ? route.getFilters().trim() : null);

        boolean res = appRouteService.saveOrUpdate(route);
        return new JsonResult(res, res ? "操作成功" : "操作失败");
    }

    @DeleteMapping(value = "{routeId}")
    public JsonResult delete(@PathVariable("routeId") String routeId) {
        AppRoute route = appRouteService.findByRouteId(routeId);
        if (route == null || StringUtils.isBlank(route.getRouteId())) {
            return new JsonResult(false,null, "路由不存在或已删除");
        }
        boolean res = appRouteService.deleteRoute(route);
        return new JsonResult(res, res ? "操作成功" : "操作失败");
    }

    @GetMapping(value="/clearCache")
    public void clearCache(){
        appRouteService.resetRoute();
    }

}

 

访问服务接口

public interface AppRouteService {

     List<AppRoute> findAll();

     boolean saveOrUpdate(AppRoute route);

     boolean deleteRoute(AppRoute routeId);

     AppRoute findByRouteId(String routeId);

     void resetRoute();


}

通过接口访问,对数据进行增删

/**
 * 刷新路由保存数据库
 */
@Service
public class AppRouteServiceImpl implements AppRouteService {

    private static final Logger logger = LoggerFactory.getLogger(AppRouteService.class);

    @Autowired
    AppRouteMapper appRouteMapper;

    @Autowired
    RouteDefinitionRepository routeDefinitionRepository;

    @Autowired
    RouteHandler routeHandler;

    @Autowired
    RefreshRouteLocator refreshRouteLocator;

    /**
     * 查询所有路由信息
     *
     * @return
     */
    @Override
    public List<AppRoute> findAll() {
        return appRouteMapper.findAll();
    }

    /**
     * 保存、更新 路由
     *
     * @param route
     * @return
     */
    @Override
    public boolean saveOrUpdate(AppRoute route) {
        route.setUpdateTime(new Date());
        AppRoute oldRoute = appRouteMapper.findById(route.getId());
        boolean res = false;
        if (oldRoute != null && oldRoute.getId() != null) {
            res = appRouteMapper.updateRoute(route);
        } else {
            res = appRouteMapper.insertRoute(route);
        }

        if (res) {
            logger.info("更新缓存,通知网关重新加载路由信息...");
            routeDefinitionRepository.save(Mono.just(new RouteDefinition(route.toString())));
            resetRoute();
        }

        return res;
    }

    /**
     * 删除路由
     *
     * @param route
     * @return
     */
    public boolean deleteRoute(AppRoute route) {
        route.setUpdateTime(new Date());
        boolean res = appRouteMapper.deleteRoute(route);
        if (res) {
            logger.info("更新缓存,通知网关重新加载路由信息...");
            routeDefinitionRepository.delete(Mono.just(route.getRouteId()));
            resetRoute();
        }
        return res;
    }

    /**
     * 通过routeId查找路由
     *
     * @param routeId
     * @return
     */
    @Override
    public AppRoute findByRouteId(String routeId) {
        return appRouteMapper.findByRouteId(routeId);
    }

    @Override
    public void resetRoute() {
                    refreshRouteLocator.buildRoutes();
    }
}

Dao接口

@Repository
public interface AppRouteMapper {
    List<AppRoute> findAll();

    AppRoute findByRouteId(String routeId);

    AppRoute findById(Integer id);

    boolean updateRoute(AppRoute route);

    boolean insertRoute(AppRoute route);

    boolean deleteRoute(@Param("route") AppRoute route);

    AppRoute findByPath(String path);
}

执行sql

 <select id="findAll" resultType="com.zqs.domain.dto.route.AppRoute">
        select * from tbl_app_route where state = 0
    </select>

    <select id="findByRouteId" parameterType="string" resultType="com.zqs.domain.dto.route.AppRoute">
        select * from tbl_app_route where route_Id = #{routeId} and state = 0 LIMIT 1
    </select>

    <select id="findById" parameterType="integer" resultType="com.zqs.domain.dto.route.AppRoute">
        select * from tbl_app_route where id = #{id}
    </select>

    <select id="findByPath" parameterType="String" resultType="com.zqs.domain.dto.route.AppRoute">
        select * from tbl_app_route where predicates = #{path} AND state = 0
    </select>

    <update id="updateRoute">
        update tbl_app_route
            set
                route_id = #{routeId},
                exeseq = #{exeseq},
                uri = #{uri},
                predicates = #{predicates},
                filters = #{filters},
                state = 0
            where id = #{id}
    </update>

    <insert id="insertRoute" parameterType="com.zqs.domain.dto.route.AppRoute">
        insert into tbl_app_route(
            id,
            route_id,
            exeseq,
            uri,
            predicates,
            filters)
            values(
            #{id},
            #{routeId},
            #{exeseq},
            #{uri},
            #{predicates},
            #{filters}
            );
    </insert>

    <update id="deleteRoute" parameterType="com.zqs.domain.dto.route.AppRoute">
        update  tbl_app_route set state = 1 where id = #{route.id}
    </update>

 主要依赖

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 

posted @ 2022-08-12 18:22  0卜卜口0  阅读(200)  评论(0)    收藏  举报