微服务架构讲究系统的高内聚性,即只做该系统该做的事情,而其他的事情可以通过网关去做。spring cloud的zuul可以快速的搭建一个网关系统,其主要功能如下:
当加入了spring cloud的zuul后,架构图大致如下:
下面我们使用zuul来快速搭建一个官网系统
1.添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>
<!-- 导入Spring Cloud的依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
2.编写启动类
@EnableZuulProxy
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
3.编写yml配置文件
server:
port: 6677 #服务端口
spring:
application:
name: spring-cloud-gateway #指定服务名
zuul:
routes:
caclulate: #caclulate这个名字是任意写的
path: /caclulate/** #配置请求URL的请求规则
serviceId: com-spring-caclu #指定Eureka注册中心中的服务id
eureka:
client:
registerWithEureka: true #是否将自己注册到Eureka服务中,默认为true
fetchRegistry: true #是否从Eureka中获取注册信息,默认为true
serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址
defaultZone: http://cloud:cloud@127.0.0.1:6868/eureka/
instance:
prefer-ip-address: true #将自己的ip地址注册到Eureka服务中
前往eureka的注册中心,我们发现该服务已经注册到该服务中心了。
此时,我们只需要访问/caclulate/**,该网关服务执行玩自己该做的事情之后,就会转发到对应的服务(com-spring-caclu)下面去执行目标代码。
上面配置文件中,转发路由的配置是比较常用的一种写法,也是比较好用的,它不会破坏Hystrix、Ribbon特性,下面还有几种配置路由的方式可以参考一下:
3.1 指定服务id
3.2 忽略指定服务
3.3 忽略所有服务,只是有路由指定
3.4 同时配置path和url
3.5 使用正则表达式指定路由规则
3.6 路由前缀
3.7 忽略某些路径
下面我们通过一个示例来演示一下zuul如何来使用
我们只需要创建一个类来继承ZuulFilter这个抽象类,并实现其4个抽象方法即可:
1、shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
2、run:过滤器的具体业务逻辑。
3、filterType:返回字符串代表过滤器的类型
a)pre:请求在被路由之前执行
b)routing:在路由请求时调用
c)post:在routing和errror过滤器之后调用
d)error:处理请求时发生错误调用
filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
下面是一个实例代码:
@Component //加入到Spring容器
public class UserLoginZuulFilter extends ZuulFilter{
@Override
public boolean shouldFilter() {
return true; // 该过滤器需要执行
}
@Override
public Object run() { //编写业务逻辑
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getParameter("token");
if(StringUtils.isEmpty(token)){
requestContext.setSendZuulResponse(false); // 过滤该请求,不对其进行路由
requestContext.setResponseStatusCode(401); // 设置响应状态码
return null;
}
return null;
}
@Override
public String filterType() {
return "pre"; // 设置过滤器类型为:pre
}
@Override
public int filterOrder() {
return 0;// 设置执行顺序
}
}
这个时候,当我们再次访问的时候,如果没有token这个参数,那么就会直接返回,并抛出401状态码。