赞
踩
Zuul 中的过滤器跟我们之前使用的 javax.servlet.Filter 不一样,javax.servlet.Filter 只有一种类型,可以通过配置 urlPatterns 来拦截对应的请求。
而 Zuul 中的过滤器总共有 4 种类型,且每种类型都有对应的使用场景。
1)pre
可以在请求被路由之前调用。适用于身份认证的场景,认证通过后再继续执行下面的流程。
2)route
在路由请求时被调用。适用于灰度发布场景,在将要路由的时候可以做一些自定义的逻辑。
3)post
在 route 和 error 过滤器之后被调用。这种过滤器将请求路由到达具体的服务之后执行。适用于需要添加响应头,记录响应日志等应用场景。
4)error
处理请求时发生错误时被调用。在执行过程中发送错误时会进入 error 过滤器,可以用来统一记录错误信息。
通过上面的图可以清楚地知道整个执行的顺序,请求发过来首先到 pre 过滤器,再到 routing 过滤器,最后到 post 过滤器,任何一个过滤器有异常都会进入 error 过滤器。
通过 com.netflix.zuul.http.ZuulServlet 也可以看出完整执行顺序,ZuulServlet 类似 Spring-Mvc 的 DispatcherServlet,所有的 Request 都要经过 ZuulServlet 的处理。
1)shouldFilter
是否执行该过滤器,true 为执行,false 为不执行,这个也可以利用配置中心来实现,达到动态的开启和关闭过滤器。
2)filterType
过滤器类型,可选值有 pre、route、post、error。
3)filterOrder
过滤器的执行顺序,数值越小,优先级越高。
4)run
执行自己的业务逻辑,本段代码中是通过判断请求中是否有token,决定是否进行拦截。当token为空时,通过设置 requestContext.setSendZuulResponse(false),告诉 Zuul 不需要将当前请求转发到后端的服务了。通过 setResponseBody 返回数据给客户端。
- import com.netflix.zuul.ZuulFilter;
- import com.netflix.zuul.context.RequestContext;
- import com.netflix.zuul.exception.ZuulException;
- import org.apache.commons.lang.StringUtils;
- import org.springframework.http.HttpStatus;
- import org.springframework.stereotype.Component;
- import javax.servlet.http.HttpServletRequest;
- import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
-
- /**
- * 登录过滤器
- */
- //这个注解不要忘了,加入spring容器中
- @Component
- public class LoginFilter extends ZuulFilter {
-
- /**
- * 过滤器类型
- * org.springframework.cloud.netflix.zuul.filters.support.FilterConstants 这个类
- * pre:在请求被路由(转发)之前调用
- * route:在路由(请求)转发时被调用
- * error:服务网关发生异常时被调用
- * post:在路由(转发)请求后调用
- * @return
- */
- @Override
- public String filterType() {
- //前置过滤器
- return PRE_TYPE;
- }
-
- /**
- * 过滤器顺序,越小越先执行
- * @return
- */
- @Override
- public int filterOrder() {
-
- return 4;
- }
-
-
- /**
- * 过滤器是否生效
- * @return
- */
- @Override
- public boolean shouldFilter() {
-
- RequestContext requestContext = RequestContext.getCurrentContext();
- HttpServletRequest request = requestContext.getRequest();
-
- System.out.println(request.getRequestURI()); ///apigateway/product/api/v1/product/list
- System.out.println(request.getRequestURL()); //http://localhost:9000/apigateway/product/api/v1/product/list
-
- //ACL
- //进行拦截,就会进入下面的 run方法中
- if (request.getRequestURI().contains("/apigateway/orderapi/ordermapping/savedingdan")){
- return true;
- }
-
- //不拦截,放行
- return false;
- }
-
- /**
- * 业务逻辑
- * @return
- * @throws ZuulException
- */
- @Override
- public Object run() throws ZuulException {
-
- //获取上下文
- RequestContext requestContext = RequestContext.getCurrentContext();
- //获取request对象
- HttpServletRequest request = requestContext.getRequest();
-
- //token对象
- String token = request.getHeader("token");
-
- if(StringUtils.isBlank((token))){
- token = request.getParameter("token");
- }
-
- //登录校验逻辑 根据公司情况自定义 JWT
- //token为空,就不能访问
- if (StringUtils.isBlank(token)) {
- //停止访问,并返回出错的消息
- requestContext.setSendZuulResponse(false);
-
- //防止中文乱码
- requestContext.getResponse().setContentType("text/html;charset=UTF-8");
- //设置返回的状态码和正文
- requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
- requestContext.setResponseBody("userToken is null");
- }
- //正常的话,继续向下走
- return null;
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。