一.
今天说下Zuul 如何实现一个自定义的过滤器。实现过滤器很简单,只需要继承 ZuulFilter 类,并实现 ZuulFilter 中的抽象方法。
项目用eureka-zuul-client,参考文章
需要实现的抽象方法有:
- filterType(拦截器的类型):pre,routing,post,error
- filterOrder(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行。
- shouldFilter:表示该过滤器是否过滤逻辑,为true则执行run(),为false,则不执行。
- run: 过滤器实际上执行的内容(即具体的过滤逻辑)
过滤器一些简单概念:
- PRE过滤器: 它是在请求路由到具体的服务之前执行的,可以做安全验证,例如:身份验证、参数验证等。
- ROUTING过滤器: 将请求转发到具体的微服务实例进行逻辑处理。在默认情况下,它使用Http Client 进行网络请求。
- POST过滤器: 它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计信息、指标,以及将相应传输回客户端。
- ERROR 过滤器:: 它是在其他过滤器发生错误时执行。
二. 写一个 检查请求的参数中是否传了token这个参数,如果没有传,则直接返回响应,状态码为401
代码如下:
package com.example.eurekazuulclient.filter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 自定义 Zuul 的过滤器
* 写一个 检查请求的参数中是否传了token这个参数,如果没有传,则直接返回响应,状态码为401
*/
@Component
public class MyFilter extends ZuulFilter {
private static Logger logger = LoggerFactory.getLogger(MyFilter.class);
/**
* filterType(拦截器的类型):pre,routing,post,error
* filterOrder(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行。
* shouldFilter:表示该过滤器是否过滤逻辑,为true则执行run(),为false,则不执行。
* run: 过滤器实际上执行的内容(即具体的过滤逻辑)
*/
/**
* PRE过滤器: 它是在请求路由到具体的服务之前执行的,可以做安全验证,例如:身份验证、参数验证等。
* ROUTING过滤器: 将请求转发到具体的微服务实例进行逻辑处理。在默认情况下,它使用Http Client 进行网络请求。
* POST过滤器: 它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计信息、指标,以及将相应传输回客户端。
* ERROR 过滤器:: 它是在其他过滤器发生错误时执行。
*/
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
/**
* RequestContext是ConcurrentMap的一个子类,这个类可以拿到HttpServletRequest与HttpServletResponse,同时这个类当中的数据可以被多个zuulFilter共享,其中有几个方法值得我们注意以下:
* getCurrentContext() 获取ThreadLocal中的RequestContext对象
* setSendZuulResponse() 如果设置为false那么将终止对原始地址的路由
* setResponseStatusCode() 设置http的状态响应码
* addZuulResponseHeader() 设置响应头,通过这个方法我们能解决响应时中文乱码问题
* setResponseBody() 设置响应体
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
Object accessToken = request.getParameter("token");
if (accessToken == null) {
logger.info("token is empty!");
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(401);
//Gson gson = new GsonBuilder().create();
requestContext.addZuulResponseHeader("content-type", "application/json;charset=utf-8");
try {
//requestContext.setResponseBody(gson.toJson(new ResponseEntity("token is empty!", HttpStatus.UNAUTHORIZED)));
//requestContext.setResponseBody("token is empty!");
requestContext.getResponse().getWriter().write("token is empty!");
} catch (Exception e) {
return null;
}
}
logger.info("ok");
return null;
}
}
启动 eureka-serve,eureka-zuul-client,eureka-client (8762,8763两个端口) 服务,访问地址: http://localhost:8768/v1/hiApi/HiController/hi/java
从上图可以看到请求被拦截了。
接着我们带 token 去请求。http://localhost:8768/v1/hiApi/HiController/hi/java?token=1
到此,Zuul 中使用过滤器 学习结束