Files
SOP/doc/docs/files/90012_原理分析之如何路由.md
2019-03-26 11:30:45 +08:00

78 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 原理分析之如何路由
## 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默认的路由功能非常方便。