我目前正在尝试按照HATEOAS原则模块实现一个RESTful Client,以便在我的Android App中使用。在我的方法中我使用了Google的Volley。 我已经扩展了Volley的Request类来提供自定义的Response对象。 以下是两个类:
自定义请求类:
public class RestRequest extends Request<RestResponse>
{
private final Map<String, String> headers;
private final Response.Listener<RestResponse> listener;
public RestRequest(int requestType, String url, Map<String, String> headers,
Response.Listener<RestResponse> listener,
Response.ErrorListener error)
{
super(requestType, url, error);
this.listener = listener;
this.headers = headers;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError
{
return this.headers != null ? this.headers : super.getHeaders();
}
@Override
protected Response<RestResponse> parseNetworkResponse(NetworkResponse response)
{
String responseBody = null;
try
{
responseBody = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
}
catch (UnsupportedEncodingException e)
{
responseBody = new String(response.data);
}
for (Map.Entry<String, String> entry : response.headers.entrySet())
{
System.out.println(entry.getKey() + " " + entry.getValue());
}
return Response.success(new RestResponse(response.headers,
responseBody), HttpHeaderParser.parseCacheHeaders(response));
}
@Override
protected void deliverResponse(RestResponse response)
{
listener.onResponse(response);
}
}
自定义响应类:
public class RestResponse
{
private Map<String, String> responseHeaders;
private String responseBody;
public RestResponse(Map<String, String> responseHeaders, String responseBody)
{
this.responseHeaders = responseHeaders;
this.responseBody = responseBody;
}
public Map<String, String> getResponseHeaders()
{
return responseHeaders;
}
public String getResponseBody() {
return responseBody;
}
}
正如您所看到的,我尝试保存在RestResponse类中保存ResponseHeaders和ResponseBody。使用我的RestRequest类,我的请求都得到了正确处理而没有错误。
我面临的唯一问题是ResponseHeaders没有正确保存,或者至少是我在做错事的地方。但正如你在
中看到的那样 protected Response<RestResponse> parseNetworkResponse(NetworkResponse response)
我正在为我创建的RestResponse对象提供来自response.headers
的ResponseHeaders。
查看包含标题的检索到的地图会显示以下内容:
I/System.out: Content-Length 0
I/System.out: Date Wed, 29 Jun 2016 17:27:59 GMT
I/System.out: link <https://LINK_1>;rel="link-1"
I/System.out: Server Apache-Coyote/1.1
I/System.out: X-Android-Received-Millis 1467221322063
I/System.out: X-Android-Response-Source NETWORK 200
I/System.out: X-Android-Selected-Protocol http/1.1
I/System.out: X-Android-Sent-Millis 1467221322031
但它应该在链接标题中返回更多链接,就像通过Postman发出请求一样:
Content-Length →0
Date →Wed, 29 Jun 2016 17:33:22 GMT
Server →Apache-Coyote/1.1
link →<LINK_1>;rel="link-1", <LINK_2>;rel="link-2", <LINK_3>;rel="link-3"
我显然用占位符替换了实际的链接,但其他一切都来自真正的调用。 Volley总是给我一个链接而且我不知道为什么。在Volley内部执行是错误的还是我在这里做错了什么? 提前谢谢!
编辑: 添加了根据日志放置的System.out.print。
答案 0 :(得分:0)
我认为这个问题确实存在于Volley。我查看了Volley的源代码,其中创建了NetworkResponse对象,并发现来自HttpResponse对象的Header []正在转换为Map。由于Maps只能使用唯一键,因此会导致错误行为,因为Link标头可以是多值的。 想象一下,将以下标题放入地图中,其中headername是键,标题值是值。
link: <http://example.com>; rel="example"
link: <http://example1.com>; rel="example1"
link: <http://example2.com>; rel="example2"
由于默认的Map行为,显然只剩下一个链接头。