今天,来记录Zuul ,spring cloud 的网关组件的使用方法
Zuul 的使用场景,就是api的一个入口,当某些权限验证,以及过滤器 等 ,都在此处做处理;
1, 先创建 Zuul 的项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hero</groupId>
<artifactId>hero-gateway-zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hero-gateway-zuul</name>
<description>Demo project for Spring Cloud</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.SR4</spring-cloud.version>
</properties>
<dependencies>
<!-- Zuul 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Zuul 依赖-->
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml 配置
server:
port: 8902
spring:
application:
name: hero-gateway-zuul
eureka: ## zuul 组件,也是需要注册到注册中心
client:
service-url:
defaultZone: http://root:123456@localhost:7776/eureka/
zuul: ## Zuul 的配置,需要路由的配置,针对consumer 看住consumer 的入口
routes:
hero-eureka-consumer: /user/** ## consumer注册的名字:拦截的方式,拦截/xx/xx 下的请求
hero-index-consumer: /index/**
hero-order-consumer: /order/**
测试:http://localhost:8902/user/userLogin
在测试中,consumer的地址也是可以访问的 :http://localhost:8900/userLogin
所以需要注意的:
- 提供前端服务地址,不要提供consumer的地址
- 提供前端服务地址,只能给Zuul网关的地址
- 要想办法把consumer的地址给屏蔽掉
Zuul 过滤器分类
1. PRE
4. ROUTE
5. POST
6. ERROR
Zuul 过滤器的时间线流程
用户发出请求–> 网关拦截—> PRE 过滤器处理—> ROUTE 过滤器处理—>
在发出给consumer 处理——> consumer返回给ROUTE过滤器——> 如果中途ROUTE过滤器处理异常
也会发生异常下游到ERROR过滤器——> 如果consumer 处理完毕下游ROUTE 过滤器都没任何异常时则直接——> POST 过滤器做处理——> 响应回去到用户
Zuul网关实现过滤器
- 创建PreFilter 过滤器来实现策略,继承ZuulFilter ,且实先方法
- 实现过滤器的方法解析
package com.hero.gateway.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.Response;
@Component // 该组件需要注册到spring中
public class PreFilter extends ZuulFilter {
@Override
public String filterType() { // 过滤器的类型: pre,route,post,error
return FilterConstants.PRE_TYPE; // FilterConstants 有提供常量值
}
@Override
public int filterOrder() {// 同类型的过滤器类型执行优先级设置,跨越不了其他类型过滤器
return 0; // 同级过滤器类型中,值越小,优先级越大,可为负数
}
@Override
public boolean shouldFilter() {// 是否启用当前过滤器
return true;// true,启动,false, 不启动
}
@Override
public Object run() { // 需要拦截的逻辑核心
// 当前方法的object spring cloud 只是做了一个可扩展而已,可返回,可不返回
// 对当前的请求进行了包装,类似springboot中的request
RequestContext cxt = RequestContext.getCurrentContext();
HttpServletRequest request = cxt.getRequest();
String token = request.getHeader("token");
if(StringUtils.isEmpty(token)){
cxt.setSendZuulResponse(false); // 在这里已经异常了,告诉后面的过滤器,不用执行了
cxt.setResponseStatusCode(401);// 放回请求状态
BaseRespose<String> msg = new BaseRespose<>(401, "access without permission,please login !");
cxt.setResponseBody(msg.toString()); // 返回异常提示信息
return "";
}else{
return "";
}
}
}
没token令牌的测试:
有token令牌的测试:
上下级过滤器的链接:打头的过滤器直接设为true,后面的,则需要上一级逻辑设置这个开关
@Override
public boolean shouldFilter() {// 是否启用当前过滤器
// true,启动,false, 不启动;
// 这里的状态,需要上一级过滤器给出状态,如果上一级给出cxt.setSendZuulResponse(false); 则不执行
// cxt.setSendZuulResponse(true); 则执行
/*RequestContext cxt = RequestContext.getCurrentContext();
cxt.sendZuulResponse();
上下文传递参数:可以使用:cxt.set("code","value");
*/
return true;
}
过滤器还可以在配置文件种设置过滤器失效的办法:在官网Zuul 下的routes同级 配置过滤器类的名字以及过滤器级别,设置disable 是否启用
zuul:
routes:
hero-eureka-consumer: /user/**
SecondFilter:
pre:
disable: true