pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
在启动类上面加入注解
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ExampleZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleZuulApplication.class, args);
}
}
我们需要将zuul也加入到eureka的注册列表中(配置上zuul可能有办法不需要注册成为eureka的客户端,通过url进行转发,zuul的功能和nginx差不多)
zuul拦截器
public class QueryParamPreFilter extends ZuulFilter {
/**
* pre:路由之前
* routing:路由之时
* post: 路由之后
* error:发送错误调用
* @return
*/
@Override
public String filterType() {
// 路由之前
return "pre";
}
@Override
public int filterOrder() {
// 过滤的顺序
return 0;
}
@Override
public boolean shouldFilter() {
// 这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
return true;
}
@Override
public Object run() throws ZuulException {
// 过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问
return null;
}
}
创建一个类继承ZuulFilter,同时run里面就是执行的逻辑,filterType指的处理的行为,注释已经列出了返回值对应的行为,问题来了,如果都需要处理怎么办? 如果是路由前中后都需要处理, 那么理论上你需要创建三个类,都继承ZuulFilter,同时三个类的filterType返回为对应的行为。run中执行改行为需要做的操作。
zuul 配置文件
server:
port: 8751
eureka:
instance:
hostname: localhost
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
example:
path: /**
serviceId: example-feign
## 当给定路径无法访问时,跳转到默认的路由
error: /error/**
演示模板,zuul.routes.example.path 将所有解析的路径都映射到实例id为 example-feign的实例上(实例id通过eureka可以获得,打debug可以看到猫腻),example-feign是下一章要讲的负载均衡,这里不做太多的介绍。
error这个配置意为当给定路径无法访问时会跳转到默认的路由,同时需要新增一个类
public class MyFallbackProvider implements FallbackProvider {
// 下一级路由无法访问时的跳转处理
// 要为所有路由提供默认回退则可以设置为 * 或者 null
@Override
public String getRoute() {
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return 200;
}
@Override
public String getStatusText() throws IOException {
return "SUCCESS";
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("Service-Timeout".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
类似重定向到一个统一的错误页面上,和nginx访问不到重定向到500页面一样。当然你可以配置为不跳转,就默认原路径返回。
最后
在一些简单的应用上可以直接使用nginx代替zuul,不用做太多的复杂的路由跳转,但是在复杂的应用上,例如security或者要验证token,cookies等,zuul的拦截器可以帮我们很好的处理,虽然zuul的功能和nginx有点类似,但是仍然有他的使用场景,nginx我们还是尽量保持整洁,不做太多业务层上的操作。