You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							77 lines
						
					
					
						
							3.5 KiB
						
					
					
				
			
		
		
	
	
							77 lines
						
					
					
						
							3.5 KiB
						
					
					
				# 原理分析之如何路由
 | 
						|
 | 
						|
## 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默认的路由功能,非常方便。
 | 
						|
 |