1、zuul的大部分功能都是通过过滤器进行。zuul定义四种标准的过滤器类型,这四种过滤器应用在请求生命周期的不同时期。
pre过滤器,它在请求被zuul路由之前调用。一般用来实现身份验证、在集群中的选择请求的微服务、记录调试信息等
routing过滤器,它将请求路由到微服务。一般用于构建发送请求到微服务,并使用apache的httpclient或者ribbon进行请求微服务。
post过滤器,这种过滤器是路由到微服务之后执行,相当于后置过滤器。这种过滤器可为请求响应的时候添加标准的http header,收集统计信息、将响应从微服务发给客户端等,简单地说,就是请求处理后,响应给客户端的时候,会调用这个过滤器。
error过滤器,在其他过滤器阶段,发生错误的时候,会执行该过滤器,相当于在执行其他过滤器的时候,出现error会被error过滤器捕获。
当然也可以自定义过滤器,后续再写个自定义过滤器进行学习。
查看源码,zuul过滤器定义在org.springframework.cloud.netflix.zuul.filters包下,这些过滤器默认包含了三种不同的生命周期,pre、routing、post。
自定义过滤器,需要继承ZuulFilter,重写filterType、filterOrder、shouldFilter、run方法
filterType:代表自定义过滤器的类型,值有pre、route、post、error
pre:可以在请求被路由之前调用
route:在路由请求时候被调用
post:在route和error过滤器之后被调用
error:处理请求时发生错误时被调用
filterOrder:用来代表过滤器的执行顺序,越小越先被执行,int值
shouldFilter:返回boolean值来判断该过滤器是否被执行,true表示该过滤器生效,false反之
run:过滤器的具体处理逻辑,根据shouldFilter的返回值判断是否执行,true则会执行run方法,false则不会
这里自定义RouteFilter
package com.etc.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;
/**
* 过滤器
*/
@Component
public class RouteFilter extends ZuulFilter {
/**
* 设置过滤器类型为前置过滤器
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 设置过滤器顺序,越小越先执行
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 设置过滤器是否生效,返回true则需要权限校验,
* 返回false则不需要权限校验
* @return
*/
@Override
public boolean shouldFilter() {
//获取上下文对象
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
Map<String, String[]> map = request.getParameterMap();
String contentType = request.getContentType();
int contentLength = request.getContentLength();
//获取请求uri,对uri进行访问判断
String uri = request.getRequestURI();
if("/webreq/error/htp".equalsIgnoreCase(uri)){
return true;
}
return false;
}
/**
* 业务逻辑,只有shouldFilter返回true,
* 才会进入该方法
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
//jwt的token,可以用请求头传过来,也可以用参数传过来,一般是用请求头传递
String token = request.getHeader("token");
System.out.println("=================请求头信息=================");
//请求头信息
Enumeration<String> headersMap = request.getHeaderNames();
while (headersMap.hasMoreElements()){
String headerName = (String)headersMap.nextElement();
String headerVal =request.getHeader(headerName);
System.out.println(headerName+":"+headerVal);
}
if(StringUtils.isEmpty(token)){
//过滤掉该路由,不对它进行路由
requestContext.setSendZuulResponse(false);
//返回错误代码
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}