使用了springcloud 后,自然就会使用到 zuul网关来转发相应的请求到对应的微服务上去.

使用zuul 的过滤器可以校验一些接口的权限访问,自然有时候也需要对某些url规则的进行一些相应的转发操作,这样可以让前端不知道你后端的真实路劲,也可以适应自己的一些需求.


先贴上转发时修改url的代码.







import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;





@Component
public class UrlRedirectFilter extends ZuulFilter implements AbstractLogger{

	
    /**
     *  重定向的规则,根据key来重定向到val.
     */
    private static Map<String, String>urlMap=new HashMap<>();
    static {
 	   urlMap.put("t", "/test/");
    }
    @Override
    public Object run() {
    	RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		String url = request.getRequestURI(); // 列子 [/user/login/loginWx]
		String[] split = url.split("/", 3);	// 这里切割一下,好让下面判断是否是需要修改url的.
		if (split.length>=2) {
			String val = urlMap.get(split[1]);
			if (StringUtils.isNotEmpty(val)) {
				url=url.replaceFirst("/"+split[1]+"/", val);// 根据配置好的去将url替换掉,这里可以写自己的转换url的规则
				ctx.put(FilterConstants.REQUEST_URI_KEY, url); // 将替换掉的url set进去,在对应的转发请求的url就会使用这个url
			}
		}
    	return null;
    }
    
	@Override
	public boolean shouldFilter() {
		return true;
	}

	//filterOrder:过滤的顺序
	@Override
	public int filterOrder() {
		return 1;
	}

	/* (non-Javadoc)filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下: 
					pre:路由之前
					routing:路由之时
					post: 路由之后
					error:发送错误调用
	 */
	@Override
	public String filterType() {
		return FilterConstants.ROUTE_TYPE;
	}

}


我这里使用了zuul的过滤器来拦截 修改转发的url , 代码中是 设定了在 路由之时 过滤,这个地方特别重要,一定是路由之时,不然是没有效果的.

然后 是在路由之时 第1个 去修改这个转发的url ,并且每次都会进run方法,因为 shouldFilter() 永远给的是true.



下面来分析下zuul的源码.

首先

在 org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter 这个根据uri决定调用哪一个route 的过滤器中有

ctx.put(REQUEST_URI_KEY, route.getPath()); 这行代码,也就在这put了一次这个url对应的值, 

我们将url修改后再put 进去,zuul 将会在转发的时候 

也就是 SendForwardFilter 这个里面 (贴一段源码)

	@Override
	public Object run() {
		try {
			RequestContext ctx = RequestContext.getCurrentContext();
			String path = (String) ctx.get(FORWARD_TO_KEY);
			RequestDispatcher dispatcher = ctx.getRequest().getRequestDispatcher(path);
			if (dispatcher != null) {
				ctx.set(SEND_FORWARD_FILTER_RAN, true);
				if (!ctx.getResponse().isCommitted()) {
					dispatcher.forward(ctx.getRequest(), ctx.getResponse());
					ctx.getResponse().flushBuffer();
				}
			}
		}
		catch (Exception ex) {
			ReflectionUtils.rethrowRuntimeException(ex);
		}
		return null;
	}

这里 取的是 FORWARD_TO_KEY 这个key所存储的url .也就是最终转发的url值.


至此,url转发修改完成..



Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐