使用了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.
首先
在 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轉發修改完成..