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; } }