Volley 使用PATCH的记录

来源:互联网 发布:金税盘开票数据导出 编辑:程序博客网 时间:2024/06/10 13:57

由于项目需要,使用了Volley框架,其中有一个通信接口的Method是用PATCH的,之前没接触过,所以在实现中遇到了一些问题。经过一番查找,终于实现了。

  • 问题一:java.net.ProtocolException: Unknown method ‘PATCH’; must be one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE]

首先遇到这个问题,以为是volley版本没有提供PATCH,后来发现是没有实现(大概这么理解),经过查询得知以下处理方法:
首先导入以下jar包:
okhttp-2.2.0.jar
okhttp-urlconnection-2.2.0.jar
okio-1.2.0.jar
然后编写如下类:

import java.io.IOException;import java.net.HttpURLConnection;import java.net.URL;import com.android.volley.toolbox.HurlStack;import com.squareup.okhttp.OkHttpClient;import com.squareup.okhttp.OkUrlFactory;public class OkHttpStack extends HurlStack {    private final OkUrlFactory mFactory;    public OkHttpStack() {        this(new OkHttpClient());    }    public OkHttpStack(OkHttpClient client) {        if (client == null) {            throw new NullPointerException("Client must not be null.");        }        mFactory = new OkUrlFactory(client);    }    @Override protected HttpURLConnection createConnection(URL url) throws IOException {        return mFactory.open(url);    }}

使用方法如下:

Volley.newRequestQueue(getApplicationContext(),new OkHttpStack()).add(jsonRequest);

以为得救了,马上测试了下,结果出现了问题二,可能使用的Volley版本太低或者它本身的原因吧(用的不是最新版,最后会给相关包的下载路径)。

  • 问题二:java.lang.IllegalArgumentException: method PATCH must have a request body.

遇到这个问题,我能确定的是,肯定有request body,只是在哪里丢掉了,最后没有传上去,问题可能出现在新加的那个类里。不过对这个不熟悉,只能继续查资料。
最后查到了如下类替换掉上面那个类,就可以了:

import java.io.IOException;import java.util.Map;import java.util.concurrent.TimeUnit;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.ProtocolVersion;import org.apache.http.StatusLine;import org.apache.http.entity.BasicHttpEntity;import org.apache.http.message.BasicHeader;import org.apache.http.message.BasicHttpResponse;import org.apache.http.message.BasicStatusLine;import com.android.volley.AuthFailureError;import com.android.volley.Request;import com.android.volley.toolbox.HttpStack;import com.squareup.okhttp.Call;import com.squareup.okhttp.Headers;import com.squareup.okhttp.MediaType;import com.squareup.okhttp.OkHttpClient;import com.squareup.okhttp.Protocol;import com.squareup.okhttp.RequestBody;import com.squareup.okhttp.Response;import com.squareup.okhttp.ResponseBody;public class OkHttpStack implements HttpStack{    private final OkHttpClient mClient;    public OkHttpStack(OkHttpClient client)    {        this.mClient = client;    }    @Override    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)            throws IOException, AuthFailureError    {        OkHttpClient client = mClient.clone();        int timeoutMs = request.getTimeoutMs();        client.setConnectTimeout(timeoutMs, TimeUnit.MILLISECONDS);        client.setReadTimeout(timeoutMs, TimeUnit.MILLISECONDS);        client.setWriteTimeout(timeoutMs, TimeUnit.MILLISECONDS);        com.squareup.okhttp.Request.Builder okHttpRequestBuilder =                new com.squareup.okhttp.Request.Builder();        okHttpRequestBuilder.url(request.getUrl());        Map<String, String> headers = request.getHeaders();        for (final String name : headers.keySet())        {            okHttpRequestBuilder.addHeader(name, headers.get(name));        }        for (final String name : additionalHeaders.keySet())        {            okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));        }        setConnectionParametersForRequest(okHttpRequestBuilder, request);        com.squareup.okhttp.Request okHttpRequest = okHttpRequestBuilder.build();        Call okHttpCall = client.newCall(okHttpRequest);        Response okHttpResponse = okHttpCall.execute();        StatusLine responseStatus = new BasicStatusLine                (                        parseProtocol(okHttpResponse.protocol()),                        okHttpResponse.code(),                        okHttpResponse.message()                );        BasicHttpResponse response = new BasicHttpResponse(responseStatus);        response.setEntity(entityFromOkHttpResponse(okHttpResponse));        Headers responseHeaders = okHttpResponse.headers();        for (int i = 0, len = responseHeaders.size(); i < len; i++)        {            final String name = responseHeaders.name(i), value = responseHeaders.value(i);            if (name != null)            {                response.addHeader(new BasicHeader(name, value));            }        }        return response;    }    private static HttpEntity entityFromOkHttpResponse(Response r) throws IOException    {        BasicHttpEntity entity = new BasicHttpEntity();        ResponseBody body = r.body();        entity.setContent(body.byteStream());        entity.setContentLength(body.contentLength());        entity.setContentEncoding(r.header("Content-Encoding"));        if (body.contentType() != null)        {            entity.setContentType(body.contentType().type());        }        return entity;    }    @SuppressWarnings("deprecation")    private static void setConnectionParametersForRequest            (com.squareup.okhttp.Request.Builder builder, Request<?> request)            throws IOException, AuthFailureError    {        switch (request.getMethod())        {            case Request.Method.DEPRECATED_GET_OR_POST:                // Ensure backwards compatibility.                // Volley assumes a request with a null body is a GET.                byte[] postBody = request.getPostBody();                if (postBody != null)                {                    builder.post(RequestBody.create                            (MediaType.parse(request.getPostBodyContentType()), postBody));                }                break;            case Request.Method.GET:                builder.get();                break;            case Request.Method.DELETE:                builder.delete();                break;            case Request.Method.POST:                builder.post(createRequestBody(request));                break;            case Request.Method.PUT:                builder.put(createRequestBody(request));                break;            case Request.Method.HEAD:                builder.head();                break;            case Request.Method.OPTIONS:                builder.method("OPTIONS", null);                break;            case Request.Method.TRACE:                builder.method("TRACE", null);                break;            case Request.Method.PATCH:                builder.patch(createRequestBody(request));                break;            default:                throw new IllegalStateException("Unknown method type.");        }    }    private static ProtocolVersion parseProtocol(final Protocol p)    {        switch (p)        {            case HTTP_1_0:                return new ProtocolVersion("HTTP", 1, 0);            case HTTP_1_1:                return new ProtocolVersion("HTTP", 1, 1);            case SPDY_3:                return new ProtocolVersion("SPDY", 3, 1);            case HTTP_2:                return new ProtocolVersion("HTTP", 2, 0);        }        throw new IllegalAccessError("Unkwown protocol");    }    private static RequestBody createRequestBody(Request r) throws AuthFailureError    {        final byte[] body = r.getBody();        if (body == null) return null;        return RequestBody.create(MediaType.parse(r.getBodyContentType()), body);    }}

调用方法如下:

Volley.newRequestQueue(getActivity(),new OkHttpStack(new OkHttpClient())).add(jsonRequest);

具体为什么要这样改,稍后再研究,赶任务中先记录一下。

用到的包下载地址:
volley和okhttp
参考连接:
问题一参考
问题二参考

0 1
原创粉丝点击