diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 2eefab8c..2ee5f754 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,13 +1,14 @@ -* [首页](/?t=1553568114881) +* [首页](/?t=1553571028492) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1553568114881) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1553568114907) - * [新增接口](files/10020_新增接口.md?t=1553568114907) - * [业务参数校验](files/10030_业务参数校验.md?t=1553568114907) - * [错误处理](files/10040_错误处理.md?t=1553568114908) - * [接口交互详解](files/10050_接口交互详解.md?t=1553568114908) - * [使用SpringCloudGateway](files/10060_使用SpringCloudGateway.md?t=1553568114908) - * [easyopen支持](files/10070_easyopen支持.md?t=1553568114908) + * [快速体验](files/10010_快速体验.md?t=1553571028492) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1553571028520) + * [新增接口](files/10020_新增接口.md?t=1553571028521) + * [业务参数校验](files/10030_业务参数校验.md?t=1553571028521) + * [错误处理](files/10040_错误处理.md?t=1553571028521) + * [接口交互详解](files/10050_接口交互详解.md?t=1553571028521) + * [使用SpringCloudGateway](files/10060_使用SpringCloudGateway.md?t=1553571028521) + * [easyopen支持](files/10070_easyopen支持.md?t=1553571028521) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1553568114909) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1553568114909) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1553571028521) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1553571028521) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1553571028521) diff --git a/doc/docs/files/90012_原理分析之如何路由.md b/doc/docs/files/90012_原理分析之如何路由.md new file mode 100644 index 00000000..cc14416e --- /dev/null +++ b/doc/docs/files/90012_原理分析之如何路由.md @@ -0,0 +1,77 @@ +# 原理分析之如何路由 + +## zuul如何路由 + +SOP网关默认使用zuul,当然也默认使用了zuul提供的路由功能。zuul默认使用过滤器来实现路由转发, +我们看下zuul中自带的过滤器: + +| 类型 | 顺序 | 过滤器 | 功能 | +| ----- | ---- | ----------------------- | ---------------------------- | +| pre | -3 | ServletDetectionFilter | 标记处理 Servlet 的类型 | +| pre | -2 | Servlet30WrapperFilter | 包装 HttpServletRequest 请求 | +| pre | -1 | FormBodyWrapperFilter | 包装请求体 | +| pre | 1 | DebugFilter | 标记调试标志 | +| pre | 5 | PreDecorationFilter | 决定路由转发过滤器 | +| route | 10 | RibbonRoutingFilter | serviceId 请求转发 | +| route | 100 | SimpleHostRoutingFilter | url 请求转发 | +| route | 500 | SendForwardFilter | forward 请求转发 | +| post | 0 | SendErrorFilter | 处理有错误的请求响应 | +| post | 1000 | SendResponseFilter | 处理正常的请求响应 | + +上图就是zuul提供的默认过滤器,可在org.springframework.cloud.netflix.zuul.filters下查看。 + +zuul的过滤器顺序值小的优先执行,其中的`PreDecorationFilter`是我们重点关注的类,由它来决定路由转发去向。 + +打开PreDecorationFilter类,看到类注释有一句话:`that determines where and how to route based on the supplied` + +翻译过来就是说,决定从哪里获取路由,然后怎样去路由。 + +PreDecorationFilter类的核心方法是run()方法。找到run方法中这一句代码: + +`Route route = this.routeLocator.getMatchingRoute(requestURI);` + +这句代码很重要,表示路由从哪里获取,如果我们能够重写getMatchingRoute方法那就可以返回自己定义的路由了。 + +接下来找到RouteLocator类的定义,发现是通过构造方法传进来的,那么我们就去找使用构造方法的类。(IDEA下右键构造方法--Find Usage) + +在org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration类中找到了定义 + +```java +// pre filters +@Bean +@ConditionalOnMissingBean(PreDecorationFilter.class) +public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) { + return new PreDecorationFilter(routeLocator, this.server.getServlet().getContextPath(), this.zuulProperties, + proxyRequestHelper); +} +``` + +方法默认注入了RouteLocator类,默认注入的实现是CompositeRouteLocator类(通过打断点可以查看)。 + +同时方法上用了`@ConditionalOnMissingBean`注解,表示如果其它地方没有声明,则默认使用这个。 + +因此我们可以自己声明一个PreDecorationFilter,然后注入自定义的RouteLocator就行了。 + +SOP自定义的RouteLocator为:`com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator`,可自行前往查看。 + +然后再我们的Config中定义: + +```java +/** + * 选取路由 + * @param zuulRouteRepository + * @param proxyRequestHelper + * @return + */ +@Bean +public PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) { + // 自定义路由 + RouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository); + return new PreDecorationFilter(routeLocator, + this.server.getServlet().getContextPath(), + this.zuulProperties, + proxyRequestHelper); +} +``` + +到此,我们只需要实现RouteLocator接口,就能使用zuul默认的路由功能,非常方便。 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java index 13e912cf..9ea8f829 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java @@ -12,6 +12,7 @@ import com.gitee.sop.gatewaycommon.zuul.route.ZuulZookeeperRouteManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; +import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter; import org.springframework.context.annotation.Bean; @@ -39,16 +40,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return zuulRouteRepository; } - /** - * 路由获取 - * @param zuulRouteRepository - * @return - */ - @Bean - SopRouteLocator sopRouteLocator(ZuulRouteRepository zuulRouteRepository) { - return new SopRouteLocator(zuulRouteRepository); - } - /** * 选取路由 * @param zuulRouteRepository @@ -57,7 +48,8 @@ public class BaseZuulConfiguration extends AbstractConfiguration { */ @Bean public PreDecorationFilter preDecorationFilter(ZuulRouteRepository zuulRouteRepository, ProxyRequestHelper proxyRequestHelper) { - SopRouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository); + // 自定义路由 + RouteLocator routeLocator = new SopRouteLocator(zuulRouteRepository); return new PreDecorationFilter(routeLocator, this.server.getServlet().getContextPath(), this.zuulProperties,