netflix是一个影片提供商,成立了自己的开源组织,该组织提供了多个开源框架,常见的与springCloud整合的eureka、ribbon、hystrix、zuul 等 都是netflix提供的开源框架。zuul网关提供了多种类型的路由转发机制,如简单路由、ribbon路由、跳转路由等。
本文的项目module结构
1 eureka服务注册中心
2 zuul客户端的调用,包括多种转发类型说明与自定义过滤器
3 服务提供者
服务提供者提供的服务比较简单,代码如下
@RestController
public class ServiceController {
/**
* 网关服务提供者测试1
* @return
*/
@RequestMapping("/zuulServer_test1/{name}")
public String zuulServer_test1(@PathVariable String name,HttpServletRequest request)throws Exception{
String age=request.getParameter("age");
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
String time=simpleDateFormat.format(new Date());
return time+":网关服务提供者测试1:"+name+":"+age;
}
/**
* 网关服务提供者测试2
* @return
*/
@RequestMapping("/zuulServer_test2")
public String zuulServer_test2()throws Exception{
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
String time=simpleDateFormat.format(new Date());
return time+":网关服务提供者测试2";
}
}
接下来主要编写zuul客户端的代码,网关module原则上可以不编写任何业务逻辑只提供转发功能,这边做了跳转路由业务的编写和自定义过滤器的编写
yml 配置如下:
server:
port: 8090
spring:
application:
name: myzuulclient
management:
security:
enabled: false #为了端点的测试需要关闭安全认证
#zuul的全套配置begin-----------------------
zuul:
routes:
sourcezjm: # sourcezjm(可修改)的url请求都会转发至http://localhost:8081
url: http://localhost:8081 #简单路由,可以省略path配置,没有path的话sourcezjm当后缀直接访问
zuultest:
path: /zuultest/** # 所有zuultest开头的请求路径都会转发至:serviceprovider的服务id
serviceId: serviceprovider #服务提供者,ribbon路由
forwardZuul:
path: /forwardZuul/**
url: forward:/forwardZuul_test1 #跳转路由URL参数需要由forward:...构成 访问方式->http://localhost:8089/forwardZuul/**
# http://localhost:8090/routes 可进行端点访问查看映射列表
#zuul的全套配置end-----------------------
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
简单路由 使用的过滤器类 SimpleHostRoutingFilter
转发路由 使用的过滤器类 SendForwardFilter,跟struts2的Forward类似,就是一个请求跳转到其它请求
ribbon路由就是面向服务的路由,可以使用服务id代替url地址,使用的过滤器类 RibbonRoutingFilter
这些过滤器类都是继承自com.netflix.zuul包下的抽象类ZuulFilter,该抽象类封装了比较全面的过滤和判断功能,并有易于理解的英文注释,本文自定义过滤器代码如下:
/**
* Created by allen on 2019/7/9.
*/
@Component
public class DiyFilter extends ZuulFilter {
/**
* 设置过滤器类型
*
* @return String
*/
@Override
public String filterType() {
//设置为前置过滤器
return PRE_TYPE;
}
/**
* 过滤器顺序:值越小,越先执行
*
* @return int
*/
@Override
public int filterOrder() {
//不能是最先执行的
return 4;
}
/**
* 过滤是否生效
* @return true if the run() method should be invoked. false will not invoke the run() method
* 返回true就继续执行下面的run方法
* 返回false不会执行run方法,直接会和服务提供方连接
*/
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String url=request.getRequestURI();
System.out.println("url:"+url);
if (url.contains("/sourcezjm/zuulServer_test1")){
return true;
}else {
return false;
}
}
/**
*
* 为了测试的效果该业务逻辑直接返回正常并向服务提供方发送参数名称为age的参数值
* @return Object
*/
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
Map<String,List<String>> map=new HashMap<String, List<String>>();
List<String> list=new ArrayList<String>();
list.add("100");
map.put("age",list);
requestContext.setSendZuulResponse(true);
//设置ResponseStatusCode为200才能成功和服务提供方连接,否则服务终止
requestContext.setResponseStatusCode(HttpStatus.OK.value());
//设置请求的额外参数值
requestContext.setRequestQueryParams(map);
return null;
}
}
过滤器中 shouldFilter()方法主要校验对某些请求进行过滤,当返回true时才会真正执行run()方法进行业务上的过滤操作。否则会跳过直接请求到目标函数。
请求路径中包含 "/sourcezjm/zuulServer_test1"才会进行过滤
为了更直观查看过滤结果,只对符合过滤条件的请求添加age这个请求参数,值为100.如下代码段
zuul客户端的控制器代码,注:里面代码除了一个跳转路由有实际跳转到该控制器外,其它都是各种转发类型的说明
@RestController
public class MyZuulController {
/**
简单路由的测试
简单路由可以省略path配置,没有path的话sourcezjm当后缀直接访问
http://localhost:8090/sourcezjm/zuulServer_test1/张三
该路径根据yml配置会转发的路径为
http://localhost:8081/zuulServer_test1/张三
请求路径要跟网关服务提供者的目标项目请求路径搭配
*/
public void test1(){
}
/**
ribbon路由的测试
URl 如果不是简单路由的格式也不是跳转路由的格式,
zuul就会看成一个serviceid了,
url 格式是HTTP或HTTPS开头的就会看作是简单路由,
格式是forward: 开头就是跳转路由了
http://localhost:8090/zuultest/zuulServer_test2
该路径根据yml配置都会转发的路径为
http://localhost:8081/zuulServer_test2
*/
public void test2(){
}
/**
*
跳转路由URL参数需要由forward:...构成
http://localhost:8090/forwardZuul/123
该路径根据yml配置会转发到本控制器的forwardZuul_test1/**请求路径,也就是下面的forwardZuul_test1方法了
*/
public void test3(){
}
@RequestMapping(value = "/forwardZuul_test1/{name}", method = RequestMethod.GET)
public String forwardZuul_test1(@PathVariable("name") String name){
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
String time=simpleDateFormat.format(new Date());
return time+":跳转路由测试:"+name;
}
}
如下是各种路由类型都输出结果
有时候路由类型可能配置比较多了,为了方便查看配对情况,可以采用actuator routes端口进行查看映射列表,如下图
为了开启端口查看功能有两个注意点:
1 在yml主配置文件,添加关闭安全认证的配置
management:
security:
enabled: false #为了端点的测试需要关闭安全认证
2 新增端口开启依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
GitHub 源码下载地址:https://github.com/higherzjm/springCloud_zuul.git