RequestContext context = RequestContext.getCurrentContext();
this.helper.addIgnoredHeaders();
try {
//构建一个Ribbon的命令上下文
RibbonCommandContext commandContext = buildCommandContext(context);
//执行Ribbon,发送请求
ClientHttpResponse response = forward(commandContext);
//设置结果
setResponse(response);
return response;
}
catch (ZuulException ex) {
throw new ZuulRuntimeException(ex);
}
catch (Exception ex) {
throw new ZuulRuntimeException(ex);
}
}
//把响应结果设置到RequestContext上下文对象中
protected void setResponse(ClientHttpResponse resp)
throws ClientException, IOException {
//把响应结果设置到RequestContext上下文对象中
RequestContext.getCurrentContext().set(“zuulResponse”, resp);
this.helper.setResponse(resp.getRawStatusCode(),
resp.getBody() == null ? null : resp.getBody(), resp.getHeaders());
}
RibbonCommandContext
在run方法中构建了一个 RibbonCommandContext
Ribbon的上下文对象,然后调用 forward
方法转发请求 ,通过 setResponse
方法设置结果
先看一下buildCommandContext
方法是如何构建RibbonCommandContext
的
protected RibbonCommandContext buildCommandContext(RequestContext context) {
HttpServletRequest request = context.getRequest();
//获取请求头
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
//获取参数
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
//获取请求的方式
String verb = getVerb(request);
//获取请求体中的内容
InputStream requestEntity = getRequestBody(request);
if (request.getContentLength() < 0 && !verb.equalsIgnoreCase(“GET”)) {
context.setChunkedRequestBody();
}
//调用的服务ID
String serviceId = (String) context.get(SERVICE_ID_KEY);
//是否重试
Boolean retryable = (Boolean) context.get(RETRYABLE_KEY);
Object loadBalancerKey = context.get(LOAD_BALANCER_KEY);
//请求的资源路径
String uri = this.helper.buildZuulRequestURI(request);
// remove double slashes
uri = uri.replace(“//”, “/”);
//getContentLength 内容长度
long contentLength = useServlet31 ? request.getContentLengthLong(): request.getContentLength();
//创建一个 RibbonCommandContext
return new RibbonCommandContext(serviceId, verb, uri, retryable, headers, params,
requestEntity, this.requestCustomizers, contentLength, loadBalancerKey);
}
这里从请求中获取了请求头,请求参数,请求体内容,以及服务ID,请求的资源URL等信息封装分 RibbonCommandContext
,那RibbonCommandContext 其实就是对下游微服务的请求的上下文数据的封装,下面是 RibbonCommandContext
的源码