zuul的核心是一系列的filters, 其作用可以类比Servlet框架的Filter,或者AOP,本文我们就来具体介绍下自定义的zuul过滤器
自定义网关过滤器
1.创建项目
创建一个普通的SpringBoot项目项目
2.添加依赖
注意添加zuul的依赖
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
3.修改配置
修改application.properties文件
代码语言:javascript复制spring.application.name=zuul-gateway-filter
server.port=9020
# eureka注册中心配置
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
4.创建自定义的过滤器
创建自定义的过滤器,继承自ZuulFilter并重写相关的方法
代码语言:javascript复制import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/**
* 自定义网关过滤器
* @author dengp
*
*/
@Component
public class LogFilter extends ZuulFilter{
private Logger logger = LoggerFactory.getLogger(LogFilter.class);
/**
* 过滤方法
*/
@Override
public Object run() {
// 获取Request上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
logger.info("LogFilter .... 请求的路径是{},请求提交的方式是{}", request.getRequestURL().toString(),request.getMethod());
return null;
}
/**
* 是否开启过滤:默认false
*/
@Override
public boolean shouldFilter() {
// TODO Auto-generated method stub
return true;
}
/**
* 多个过滤器中的执行顺序,数值越小,优先级越高
*/
@Override
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
/**
* 过滤器的类型
*/
@Override
public String filterType() {
// TODO Auto-generated method stub
return "pre";
}
}
5.演示效果
启动一个provider服务后,启动我们的网关服务,然后请求访问,查询控制台输出.
注意控制台:
日志有输出,说明自定义的网关过滤器执行了。
网关过滤器类型介绍
网关过滤器的自定义方法有四个,过滤器的类型有四个,分别如下:
zuul请求的生命周期
zuul的生命周期要结合我们上面介绍的过滤器的类型来分析,具体如下图:
网关过滤器拦截请求
网关过滤器是如何拦截不合法的请求的呢?我们来看下具体的代码
代码语言:javascript复制 /**
* 过滤方法
*/
@Override
public Object run() {
// 获取Request上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
String token = request.getParameter("token");
if(token == null){
// 拦截请求
////代表请求结束。不在继续向下请求
rc.setSendZuulResponse(false);
//添加一个响应的状态码
rc.setResponseStatusCode(401);
//响应内容
rc.setResponseBody("{"result":"token is null"}");
//响应类型
rc.getResponse().setContentType("text/json;charset=utf-8");
}
// 放过请求
return null;
}
不加参数访问失败:
添加参数:
过滤器的执行顺序
过滤器类型相同的会根据filterOrder方法的返回结果的大小来排序,不同类型根据类型的特点执行。
利用网关实现异常的统一处理
1.异常过滤器
我们需要创建类型为error的网关过滤器
代码语言:javascript复制@Component
public class ErrorFilter extends ZuulFilter{
private Logger logger = LoggerFactory.getLogger(ErrorFilter.class);
/**
* 过滤方法
*/
@Override
public Object run() {
// 获取Request上下文
RequestContext rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
logger.info("LogFilter .... 请求的路径是{},请求提交的方式是{}", request.getRequestURL().toString(),request.getMethod());
return null;
}
/**
* 是否开启过滤:默认false
*/
@Override
public boolean shouldFilter() {
// TODO Auto-generated method stub
return true;
}
/**
* 多个过滤器中的执行顺序,数值越小,优先级越高
*/
@Override
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
/**
* 过滤器的类型
*/
@Override
public String filterType() {
// TODO Auto-generated method stub
return "error";
}
}
2.统一异常处理
代码语言:javascript复制/**
* 对异常响应内如处理
* @author Administrator
*
*/
@RestController
public class ExceptionHandler implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping(value="/error")
public String error(){
return "{"result":"500 error!!!!"}";
}
}