文小库公文写作网站,软件开发模型有几种并简述其特点,内容营销的价值是什么,用花瓣网站上的图片做游戏行吗在这篇文章中#xff0c;我们将研究在Spring WebFlux中为不同的逻辑域定义多个路由器功能。 如果您正在创建“微服务”#xff0c;则可能不会出现问题#xff0c;因为您很可能仅在每个服务的单个域中工作#xff0c;但是如果不是这样#xff0c;则可能需要在应用程序中包含… 在这篇文章中我们将研究在Spring WebFlux中为不同的逻辑域定义多个路由器功能。 如果您正在创建“微服务”则可能不会出现问题因为您很可能仅在每个服务的单个域中工作但是如果不是这样则可能需要在应用程序中包含多个域用户或您自己的服务可以进行交互。 做到这一点的代码就像我希望的那样简单可以用几句话来解释。 为了使本文更加有趣我们将看一些使这一切成为可能的Spring代码。 如果您不熟悉WebFlux建议您阅读我以前的文章[使用Spring WebFlux做事] https://lankydanblog.com/2018/03/15/doing-stuff-with-spring-webflux/ 在这里我写了一些有关该主题的详尽示例和解释。 因此让我们先设置场景。 您的应用程序内有两个不同的域例如人和地点。 您可能希望不仅在逻辑上而且在代码内使它们彼此分开。 为此您需要一种独立于彼此域定义路由的方法。 这就是我们将在这篇文章中看到的内容。 如果您认为您已经知道该问题的答案那么您可能是对的。 真的就是这么简单。 让我们继续努力吧。 要仅为人员域创建路由请创建一个RouterFunction bean该bean映射到相关的处理程序函数如下所示。 Configuration
public class MyRouter {// works for a single beanBeanpublic RouterFunctionServerResponse routes(PersonHandler personHandler) {return RouterFunctions.route(GET(/people/{id}).and(accept(APPLICATION_JSON)), personHandler::get).andRoute(GET(/people).and(accept(APPLICATION_JSON)), personHandler::all).andRoute(POST(/people).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::post).andRoute(PUT(/people/{id}).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::put).andRoute(DELETE(/people/{id}), personHandler::delete).andRoute(GET(/people/country/{country}).and(accept(APPLICATION_JSON)), personHandler::getByCountry);}
} 这将创建到PersonHandler各种处理程序函数的PersonHandler 。 因此现在我们要为位置逻辑添加路由。 我们可以简单地将路由添加到该bean如下所示。 Configuration
public class MyRouter {// not ideal!Beanpublic RouterFunctionServerResponse routes(PersonHandler personHandler, LocationHandler locationHandler) {return RouterFunctions.route(GET(/people/{id}).and(accept(APPLICATION_JSON)), personHandler::get).andRoute(GET(/people).and(accept(APPLICATION_JSON)), personHandler::all).andRoute(POST(/people).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::post).andRoute(PUT(/people/{id}).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::put).andRoute(DELETE(/people/{id}), personHandler::delete).andRoute(GET(/people/country/{country}).and(accept(APPLICATION_JSON)), personHandler::getByCountry).andRoute(GET(/locations/{id}).and(accept(APPLICATION_JSON)), locationHandler::get);}
} Bean现在包含对LocationHandler的引用因此可以设置位置路由。 该解决方案的问题在于它需要将代码耦合在一起。 此外如果您需要添加更多的处理程序很快就会被注入到此bean中的依赖项数量所淹没。 解决此问题的方法是创建多个RouterFunction bean。 而已。 因此如果我们在人员域中创建一个例如PersonRouter然后在位置域中创建一个名为LocationRouter域则每个域都可以定义所需的路由其余的将由Spring完成。 之所以可行是因为Spring会遍历应用程序上下文并查找或创建任何RouterFunction bean并将它们合并为一个函数供以后使用。 使用此信息我们可以编写以下代码。 Configuration
public class PersonRouter {// solutionBeanpublic RouterFunctionServerResponse peopleRoutes(PersonHandler personHandler) {return RouterFunctions.route(GET(/people/{id}).and(accept(APPLICATION_JSON)), personHandler::get).andRoute(GET(/people).and(accept(APPLICATION_JSON)), personHandler::all).andRoute(POST(/people).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::post).andRoute(PUT(/people/{id}).and(accept(APPLICATION_JSON)).and(contentType(APPLICATION_JSON)), personHandler::put).andRoute(DELETE(/people/{id}), personHandler::delete).andRoute(GET(/people/country/{country}).and(accept(APPLICATION_JSON)), personHandler::getByCountry);}
} 和 Configuration
public class LocationRouter {// solutionBeanpublic RouterFunctionServerResponse locationRoutes(LocationHandler locationHandler) {return RouterFunctions.route(GET(/locations/{id}).and(accept(APPLICATION_JSON)), locationHandler::get);}
} PersonRouter可以与其他人/人相关的代码保持在一起而LocationRouter可以做到相同。 为了使它变得更有趣为什么要这样做 RouterFunctionMapping是检索在应用程序上下文内创建的所有RouterFunction Bean的类。 RouterFunctionMapping bean是在WebFluxConfigurationSupport中创建的 WebFluxConfigurationSupport是Spring WebFlux配置的中心。 通过在配置类中包含EnableWebFlux批注或依靠自动配置将启动一系列事件收集我们所有的RouterFunction就是其中之一。 下面是RouterFunctionMapping类。 我删除了它的构造函数和一些方法以使此处的代码片段更容易理解。 public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean {Nullableprivate RouterFunction? routerFunction;private ListHttpMessageReader? messageReaders Collections.emptyList();// constructors// getRouterFunction// setMessageReadersOverridepublic void afterPropertiesSet() throws Exception {if (CollectionUtils.isEmpty(this.messageReaders)) {ServerCodecConfigurer codecConfigurer ServerCodecConfigurer.create();this.messageReaders codecConfigurer.getReaders();}if (this.routerFunction null) {initRouterFunctions();}}/*** Initialized the router functions by detecting them in the application context.*/protected void initRouterFunctions() {if (logger.isDebugEnabled()) {logger.debug(Looking for router functions in application context: getApplicationContext());}ListRouterFunction? routerFunctions routerFunctions();if (!CollectionUtils.isEmpty(routerFunctions) logger.isInfoEnabled()) {routerFunctions.forEach(routerFunction - logger.info(Mapped routerFunction));}this.routerFunction routerFunctions.stream().reduce(RouterFunction::andOther).orElse(null);}private ListRouterFunction? routerFunctions() {SortedRouterFunctionsContainer container new SortedRouterFunctionsContainer();obtainApplicationContext().getAutowireCapableBeanFactory().autowireBean(container);return CollectionUtils.isEmpty(container.routerFunctions) ? Collections.emptyList() :container.routerFunctions;}// getHandlerInternalprivate static class SortedRouterFunctionsContainer {Nullableprivate ListRouterFunction? routerFunctions;Autowired(required false)public void setRouterFunctions(ListRouterFunction? routerFunctions) {this.routerFunctions routerFunctions;}}} 检索所有路由的路径始于afterPropertiesSet 该RouterFunctionMapping在创建RouterFunctionMapping bean之后调用。 由于内部的RouterFunction为null因此它会调用initRouterFunctions触发一系列导致routerFunctions执行的routerFunctions 。 通过从应用程序上下文注入所有RouterFunction构造一个新的SortedRouterFunctionsContainer 私有静态类将其设置为routerFunctions字段。 这是可行的因为在注入ListT时Spring会注入所有T类型的bean。 现在检索到的RouterFunction组合在一起形成一个RouterFunction 从现在开始将其用于将所有传入请求路由到适当的处理程序。 这里的所有都是它的。 总之为不同的业务域定义多个RouterFunction非常简单因为您只需在它们最有意义的任何区域中创建它们Spring就会开始获取它们。 为了使某些魔术变得神秘我们研究了RouterFunctionMapping以了解如何收集和组合我们创建的RouterFunction 以便可以将它们用于将请求路由到处理程序。 作为结束语我确实了解到这篇文章在某些方面是微不足道的但有时看似明显的信息可能会很有帮助。 如果您还没有这样做我建议您看一下我以前的文章《使用Spring WebFlux做事》 https://lankydanblog.com/2018/03/15/doing-stuff-with-spring-webflux/ 。 最后如果您发现这篇文章很有帮助并且希望在我撰写新文章时保持关注那么可以在Twitter上通过LankyDanDev关注我。 翻译自: https://www.javacodegeeks.com/2018/03/creating-multiple-routerfunctions-in-spring-webflux.html