Zuul

案例1:搭建Zuul网关服务器

》1:创建工程导入依赖
在IDEA中创建ZUUL网关工程 Zuul-Server-C9008

可以通过复制Service-A9001之后修改

添加依赖

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>

》2:编写启动类

创建启动类 C9008
@EnableZuulProxy : 通过 @EnableZuulProxy 注解开启Zuul网管功能

package com.dev1;

//省略导包
@SpringBootApplication
@EnableZuulProxy
public class C9008 {
public static void main(String[] args) {
SpringApplication.run(C9008.class,args);
}
}

》3:编写配置
创建配置文件 application.yml ,并添加相应配置

server:
port: 9008
spring:
application:
name: Zuul-Server-C9008

案例2:Zuul 中的路由转发

基础路由配置

最直观的理解:“路由”是指根据请求URL,将请求分配到对应的处理程序。在微服务体系中,Zuul负责接收所有的请求。根据不同的URL匹配规则,将不同的请求转发到不同的微服务处理。
只需要在 application.yml文件中配置路由规则即可:

server:
port: 9008
spring:
application:
name: Zuul-Server-C9008
zuul:
routes:
serivce-1:
path: /person-service/**
url: http://127.0.0.1:9001

# http://127.0.0.1:9001/person/find/2

person-service :配置路由id,可以随意取名
url :映射路径对应的实际url地址
path :配置映射路径,这里将所有请求前缀为/person-service/的请求,转发到​​​http://127.0.0.1:9001​​ 处理配置好Zuul路由之后启动服务,在浏览器中输入

http://localhost:9008/person-service/person/find/1

即可访问到微服务A。

内部过程:首先是
http://localhost:9008/person-service/person/find/1
符合符件/person-service/**则 将/person/find/1拼接到
url的后面 http://127.0.0.1:9001/person/find/2

面向服务的路由

SpringCloud案例day04.md_spring cloud

Zuul支持与Eureka整合开发,根据ServiceID自动的从注册中心中获取服务地址并转发请求

(1)添加Eureka客户端依赖

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

(2)开启Eureka客户端发现功能

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class C9008 {
public static void main(String[] args) {
SpringApplication.run(C9008.class,args);
}
}

(3)添加Eureka配置,获取服务信息

eureka:
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
client:
service-url:
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/

(4)修改映射配置,通过服务名称获取
因为已经有了Eureka客户端,我们可以从Eureka获取服务的地址信息,因此映射时无需指定IP地址,而
是通过服务名称来访问,而且Zuul已经集成了Ribbon的负载均衡功能。
serviceId: 指定需要转发的微服务实例名称

zuul:
routes:
serivce-2:
path: /person-service/**
serviceId: Service-A9001

# http://localhost:9001/person/find/2

依次启动 Eureaka-Center8000,Eureaka-Center9000,Service-A9001,Zuul-Server-C9008,在浏览器上通过访问

http://localhost:9008/person-service/person/find/1

查看最终效果

简化的路由配置

在刚才的配置中,我们的规则是这样的:

zuul.routes.<route>.path=/xxx/** : 来指定映射路径。 <route> 是自定义的路由名
zuul.routes.<route>.serviceId=/person-service :来指定服务名。

而大多数情况下,我们的 ​​<route>​​​路由名称往往和服务名会写成一样的。
因此Zuul就提供了一种简化的配置语法:

zuul.routes.<serviceId>=<path>

上面的配置可以简化为一条:

zuul:
routes:
Service-A9001: /person-service/**
# http://localhost:9001/person/find/2

默认的路由规则

在使用Zuul的过程中,上面讲述的规则已经大大的简化了配置项。
但是当服务较多时,配置也是比较繁琐的。因此Zuul就指定了默认的路由规则:
默认情况下,一切服务的映射路径就是服务名本身。
例如服务名为: Service-A ,则默认的映射路径就是: /Service-A/**

案例3:身份认证过滤器

SpringCloud案例day04.md_ide_02

自定义过滤器
接下来我们来自定义一个过滤器,模拟一个登录的校验。基本逻辑:如果请求中有access-token参数,则认为请求有效,放行。

​先验证流程通过,再编写逻辑​

package com.dev1.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;

@Component
public class LoginFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre"; //定义过滤器类型
}

@Override
public int filterOrder() {
//指定过滤器的执行顺序
//返回值越小,执行顺序越高
return 1;
}

@Override
public boolean shouldFilter() {
//当前过滤器是否生效
return true;
}

/**
* 指定过滤器中的业务逻辑
* 身份认证:
* 1.所有的请求需要携带一个参数 : access-token
* 2.获取request请求
* 3.通过request获取参数access-token
* 4.判断token是否为空
* 4.1 token==null : 身份验证失败
* 4.2 token!=null : 执行后续操作
* 在zuul网关中,通过RequestContext的上下问对象,可以获取对象request对象
*/
@Override
public Object run() throws ZuulException {
//System.out.println("执行了过滤器");
//1.获取zuul提供的上下文对象RequestContext
RequestContext ctx = RequestContext.getCurrentContext();
//2.从RequestContext中获取request
HttpServletRequest request = ctx.getRequest();
//3.获取请求参数access-token
String token = request.getParameter("access-token");
//4.判断
if (token ==null) {
//4.1 如果token==null ,拦截请求,返回认证失败
ctx.setSendZuulResponse(false); // 拦截请求
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
//4.2 如果token!=null ,继续后续操作
return null;
}
}