背景:項目重構,生產線上url需要按照需要通過網關轉發給不同的service,之前用過自定義路由,在yml文件配置route的方式去做轉發,遇到一個問題那就是 zuul.route.<自定義一個serviceid>.path = /account/** zuul.route.<自定義一個serviceid>.serviceId=account,但是不能保證請求的url,在/account/后面的url路徑跟 account服務里面的路徑一致,所以這樣會有問題。這樣的話,只能用另外一種方式了,那就是通過filter轉發
1.網關代碼
@Component public class CommonServicePathFilter extends ZuulFilter { private final static String GETWAY_FOWARD_PREFIX="getway_forward_"; private final static String GETWAY_COMPAY_CONFIG_KEY = "getway_company"; @Autowired private RedisTemplate redisTemplate; @Override public String filterType() { //這里很重要,必須是route return "route"; } @Override public int filterOrder() { return 1; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); String url = ctx.getRequest().getRequestURI(); Map<String,String> forwardMap = getForwardMap(url); if(forwardMap != null){ String fowardUrl = forwardMap.get(url); String serviceId = getServiceId(fowardUrl); String requestUrl = getRequestUrl(fowardUrl,serviceId); //1.設置目標service的Controller的路徑 ctx.put(FilterConstants.REQUEST_URI_KEY,requestUrl); //2.設置目標service的serviceId ctx.put(FilterConstants.SERVICE_ID_KEY,serviceId); } return null; } private String getServiceId(String url){ if(url.startsWith("/")){ String temp = url.substring(1); return temp.split("/")[0]; }else{ return null; } } private String getRequestUrl(String url,String serviceId){ return url.substring(serviceId.length() +1); } @Override public boolean shouldFilter() { return true; } private Map<String,String> getForwardMap(String originalUrl){ //todo:這里是返回一個map,傳入一個originUrl,返回一個要轉發的url } }
2.坑
很多網上的資料講需要做到
ctx.put(FilterConstants.REQUEST_URI_KEY,requestUrl);
但是我使用的時候,一直報404,后來跟蹤服務之后,發現其實ctx里面還有一個serviceId的屬性,它是跟當前請求的這個原始url映射的serviceId保持一致的,但是如果你要轉發的serviceId並不是這個的話,那就會報404,所以必須要在這里重新定義serviceId,
ctx.put(FilterConstants.SERVICE_ID_KEY,serviceId);