Retrofit 2.0 删除、放置不起作用

Retrofit 2.0 delete, put are not working

我正在尝试用Retrofit 2.0实现一个图书馆系统。 其中可以添加图书,列出所有图书信息,列出一本书信息,删除一本书,删除所有图书,更新一本书信息。

我的 baseURL 的末尾有一个“/”:

http://www.example.com/webservice/

前三个功能非常有效:

@GET("books")
Call<ArrayList<Book>> listBooks();

@POST("books")
Call<Book> addBook(@Body Book book);

@GET("books/{id}")
Call<Book> getBookInfo(@Path("id") int bookId);

然而,这三个根本不起作用:

@DELETE("books/{id}")
Call<Void> deleteBook(@Path("id") int bookId);

@PUT("books/{id}")
Call<Book> updateBook(@Path("id") int bookId , @Body Book book);

@DELETE("clean")
Call<Void> deleteAll();

例如,这是我的 deleteBook 功能:

        Gson gson = new GsonBuilder()
        .setDateFormat(Constant.DATE_FORMAT)
        .create();

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(Constant.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

LibraryService libraryServiceAPI = retrofit.create(LibraryService.class);
Call<Void> deleteBookCall = libraryServiceAPI.deleteBook(bookId);
deleteBookCall.enqueue(new Callback<Void>() {
    @Override
    public void onResponse(Call<Void> call, Response<Void> response) {
        if (response.isSuccessful()) {
            if (response.code() == 204) { // I get 200 here, not 204
                // but this is what I find:
                // response-->rawResponse-->request-->method == "GET"
                // This should be DELETE, am I right?
            }
        } else {
            Log.d(DELETE_BOOK_ERROR, String.valueOf(response.code()));
        }
    }

    @Override
    public void onFailure(Call<Void> call, Throwable t) {
        Log.d(DELETE_BOOK_ERROR, RESPONSE_FAILURE);
    }
});

调试数据时:发现response-->rawResponse-->request-->method == "GET",本例中应该是"DELETE"。在我实现 updateBook 和 deleteAll 功能后,我发现它们有同样的问题,这里的方法都等于 "GET" 而不是 "PUT" 和 "DELETE".

有人可以帮我理解为什么会这样吗?非常感谢。

更新一:增加调试信息截图。

您将在响应中看到,检查请求信息,方法是 "GET",但标记显示方法 = "DELETE"。

更新2:根据Dexter的建议,我添加了HttpLoggingInterceptor用于调试,

            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.interceptors().add(logging);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(httpClient.build()).build();

这里有两条日志:

  1. @GET("books/{id}") Call<Book> getBookInfo(@Path("id") int bookId); 这是正确的。

03-28 00:26:00.842 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> GET http://www.example.com/56eb7034cada930009ab0998/books/2 http/1.1 03-28 00:26:00.842 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> END GET 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- 200 OK http://www.example.com/56eb7034cada930009ab0998/books/2/ (191ms) 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Connection: keep-alive 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Server: gunicorn/18.0 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Date: Mon, 28 Mar 2016 06:03:30 GMT 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Type: application/json 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Length: 153 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Via: 1.1 vegur 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Sent-Millis: 1459139160940 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Received-Millis: 1459139161040 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: {"author": "123", "categories": "123", "id": 2, "lastCheckedOut": null, "lastCheckedOutBy": null, "publisher": "123", "title": "123", "url": "/books/2/"} 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- END HTTP (153-byte body) 03-28 00:26:01.038 3171-3171/com.xiaoyaoworm.prolificlibrary D/book info response code: Response status code: 200

  1. @DELETE("books/{id}") Call<Void> deleteBook(@Path("id") int bookId); 这是不正确的。

03-28 00:26:35.602 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> DELETE http://www.example.com/56eb7034cada930009ab0998/books/2 http/1.1 03-28 00:26:35.602 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> END DELETE 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- 200 OK http://www.example.com/56eb7034cada930009ab0998/books/2/ (481ms) 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Connection: keep-alive 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Server: gunicorn/18.0 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Date: Mon, 28 Mar 2016 06:04:05 GMT 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Type: application/json 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Length: 153 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Via: 1.1 vegur 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Sent-Millis: 1459139195900 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Received-Millis: 1459139196088 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: {"author": "123", "categories": "123", "id": 2, "lastCheckedOut": null, "lastCheckedOutBy": null, "publisher": "123", "title": "123", "url": "/books/2/"} 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- END HTTP (153-byte body)

我自己找到答案。这是一个愚蠢的错误......当我调试我的响应消息时,我发现在我的删除和放置方法中,reponse--> rawResponse--> priorResponse: Response{protocol=http/1 .1,代码=301,消息=永久移动,url=http://www.example.com/56eb7034cada930009ab0998/clean}

在我的正确获取函数中,priorResponse 为空。我在那里阅读 HTTP basic 信息,发现

If a client issues a GET request to "/testdir/" (i.e., at the directory).......It is interesting to take note that if a client issue a GET request to "/testdir" (without specifying the directory path "/"), the server returns a "301 Move Permanently" with a new "Location" of "/testdir/", as follows.

在我的 DELETE、PUT 界面中添加此“/”作为结尾后 url,现在所有功能都可以使用了!!!有趣的是,在 chrome 插件--> Advanced Rest Client 中,我最后不需要这个“/”来让它工作。

我现在更新的界面代码为:

@GET("books")
Call<ArrayList<Book>> listBooks();

@POST("books")
Call<Book> addBook(@Body Book book);

@GET("books/{id}/")
Call<Book> getBookInfo(@Path("id") int bookId);

@DELETE("books/{id}/")
Call<Void> deleteBook(@Path("id") int bookId);

@PUT("books/{id}/")
Call<Book> updateBook(@Path("id") int bookId, @Body Book book);

@DELETE("clean/")
Call<Void> deleteAll();