spring-cloud-zuul
开发环境
开发工具:Intellij IDEA 2018.2.6
springboot: 2.0.6.RELEASE
jdk:1.8.0_192
maven: 3.6.0
Zuul:2.0.2.RELEASE
spring-boot-zuul
zuul简介
API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由、 负载均衡、 校验过滤等功能之外,还需要更多能力,比如与服务治理框架的结合、请求转发时的熔断机制、服务的聚合等一系列高级功能。在SpringCloud中了提供了基于NetflixZuul实现的API网关组件Spring Cloud Zuul。
项目搭建
- pom.xml
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-zuul</artifactId>
<groupId>com.andy</groupId>
<version>1.0.6.RELEASE</version>
<packaging>jar</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Cairo-SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<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.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<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>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.3.RELEASE</version>
<configuration>
<!--<mainClass>${start-class}</mainClass>-->
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
/**
* <p>
*
* @author Leone
* @since 2018-02-10
**/
@EnableZuulProxy
@SpringCloudApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
- application.yml
server:
port: 10000
spring:
application:
name: mc-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
appname: zuul-service
instance-id: ${spring.application.name}:${server.port}
ip-address: 127.0.0.1
zuul:
ignored-patterns:
- /**/page/**
# 访问 zuul 的前缀
prefix: /api
# 去掉前缀为 false 默认 true
strip-prefix: true
# 忽略那些服务
ignored-services: mc-user
routes:
user:
path: /api-user/**
url: http://127.0.0.1:9001
sensitiveHeaders: Cookie,Set-Cookie,Authorization
mc-order:
path: /api-order/**
serviceId: mc-order
goods:
path: /api-goods/**
serviceId: mc-goods
ribbon:
eureka:
enabled: true
- RoutingZuulFilter.java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* <p>
*
* @author leone
* @since 2019-01-23
**/
@Component
public class RoutingZuulFilter extends ZuulFilter {
private static final Logger log = LoggerFactory.getLogger(PostZuulFilter.class);
/**
* 是否执行该过滤器,true 代表需要执行
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* filter 执行的优先级,数字越大,优先级越低
*
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.RIBBON_ROUTING_FILTER_ORDER;
}
/**
* 主要的处理逻辑的地方,我们做权限控制、日志等都是在这里
*
* @return
*/
@Override
public Object run() throws ZuulException {
log.info("routing filter run...");
return null;
}
/**
* filter 的类型
*
* @return
*/
@Override
public String filterType() {
return FilterConstants.ROUTE_TYPE;
}
}
- PreZuulFilter.java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
/**
* @author Leone
* @since 2018-02-07
**/
@Component
public class PreZuulFilter extends ZuulFilter {
private static final Logger log = LoggerFactory.getLogger(PostZuulFilter.class);
/**
* filter 的类型 前置过滤器
*
* @return
*/
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* filter 执行的优先级,数字越大,优先级越低
*
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER;
}
/**
* 是否执行该过滤器,true 代表需要执行
*
* @return
*/
@Override
public boolean shouldFilter() {
return false;
}
/**
* 主要的处理逻辑的地方,我们做权限控制、日志等都是在这里
*
* @return
*/
@Override
public Object run() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
String token = request.getParameter("token");
String host = request.getRemoteHost();
log.info("pre filter run... token: {} host: {}", token, host);
if (StringUtils.isEmpty(token)) {
// 不响应 request
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
- PostZuulFilter.java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* <p>
*
* @author Leone
* @since 2018-02-09
**/
@Component
public class PostZuulFilter extends ZuulFilter {
private static final Logger log = LoggerFactory.getLogger(PostZuulFilter.class);
/**
* 后置过滤器
*
* @return
*/
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
/**
* filter 执行的优先级,数字越大,优先级越低
*
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 2;
}
/**
* 是否执行该过滤器,true代表需要过滤
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 主要的处理逻辑的地方,我们做权限控制、日志等都是在这里
*
* @return
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
log.info("post filter run... response: {}", ctx.getResponseBody());
return null;
}
}
- ErrorZuulFilter.java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* <p>
*
* @author Leone
* @since 2018-02-09
**/
@Component
public class ErrorZuulFilter extends ZuulFilter {
private static final Logger log = LoggerFactory.getLogger(PostZuulFilter.class);
/**
* 异常过滤器
* @return
*/
@Override
public String filterType() {
return FilterConstants.ERROR_TYPE;
}
@Override
public int filterOrder() {
// 优先级,数字越大,优先级越低
return FilterConstants.SEND_ERROR_FILTER_ORDER;
}
/**
* 是否执行该过滤器,true 代表需要执行
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 主要的处理逻辑的地方,我们做权限控制、日志等都是在这里
*
* @return
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setResponseBody("出现异常");
log.info("error filter run:{}", ctx.getResponseBody());
return null;
}
}