2010-09-22 44 views
38

Tôi đang cố gắng sử dụng đối tượng HttpDelete để gọi phương thức xóa của dịch vụ web. Mã của dịch vụ web phân tích JSON từ phần thân của thư. Tuy nhiên, tôi không hiểu làm thế nào để thêm một cơ thể vào một đối tượng HttpDelete. Có cách nào để làm việc này không?HttpXóa với nội dung

Với HttpPut và HttpPost, tôi gọi phương thức setEntity và chuyển vào JSON của mình. Dường như không có phương thức nào cho HttpDelete.

Nếu không có cách nào để đặt nội dung cho đối tượng HttpDelete, bạn có thể vui lòng liên kết tôi với tài nguyên sử dụng lớp siêu HttpDelete sao cho tôi có thể đặt phương thức (xóa) và đặt nội dung. Tôi biết đó không phải là lý tưởng, nhưng tại thời điểm này tôi không thể thay đổi dịch vụ web.

Trả lời

86

Các bạn đã thử trọng HttpEntityEnclosingRequestBase như sau:

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; 
import java.net.URI; 
import org.apache.http.annotation.NotThreadSafe; 

@NotThreadSafe 
class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase { 
    public static final String METHOD_NAME = "DELETE"; 
    public String getMethod() { return METHOD_NAME; } 

    public HttpDeleteWithBody(final String uri) { 
     super(); 
     setURI(URI.create(uri)); 
    } 
    public HttpDeleteWithBody(final URI uri) { 
     super(); 
     setURI(uri); 
    } 
    public HttpDeleteWithBody() { super(); } 
} 

Điều đó sẽ tạo ra một HttpDelete -lookalike rằng có một phương pháp setEntity. Tôi nghĩ rằng lớp trừu tượng làm hầu hết mọi thứ cho bạn, để có thể là tất cả những gì cần thiết.

FWIW, mã được dựa trên this source to HttpPost that Google turned up.

+4

Bạn đá dude! Cảm ơn bạn! –

+0

Ugh! Điều này dường như không hoạt động với HttpURLConnection. Tôi nhận được "java.net.ProtocolException: DELETE không hỗ trợ viết". http://stackoverflow.com/questions/10338615/sending-http-delete-request-in-android –

+0

Tôi với Scott ... làm cách nào để thực hiện việc này với HttpURLConnection? Tôi phải viết lại mã mạng của mình để sử dụng Apache HTTP? –

4

Có cách giải thích khác nhau trong câu hỏi liệu nội dung có được phép hay không trong yêu cầu HTTP DELETE. Xem ví dụ this. Trong các HTTP 1.1 specification nó không phải là nghiêm cấm. Theo ý kiến ​​của tôi, bạn không được sử dụng nội dung trong HTTP DELETE.

Nevertherless Tôi nghĩ rằng bạn nên sử dụng URL như mysite/myobject/objectId (shop.com/order/1234) nơi objectId (một phần của url) là những thông tin bổ sung. Thay vào đó, bạn có thể sử dụng các thông số URL : mysite/myobject?objectName=table&color=red để gửi thông tin bổ sung cho máy chủ trong yêu cầu HTTP DELETE. Phần bắt đầu bằng '?' là các thông số urlencoded bị lệch dy '&'.

Nếu bạn muốn gửi thông tin phức tạp hơn, bạn có thể chuyển đổi các dữ liệu để JSON đối với DataContractJsonSerializer hoặc JavaScriptSerializer với và sau đó gửi dữ liệu chuyển đổi (một chuỗi mà tôi đặt tên myJsonData sau) cũng như các thông số: mysite/myobject?objectInfo=myJsonData.

Nếu bạn cần gửi quá nhiều dữ liệu bổ sung như một phần của yêu cầu HTTP DELETE để bạn gặp sự cố với độ dài URL thì có thể bạn nên thay đổi thiết kế ứng dụng của mình tốt hơn.

CẬP NHẬT: Iy bạn muốn gửi một số cơ thể mỗi HTTP DELETE bạn có thể làm điều này ví dụ như sau

// somewhere above add: using System.Net; and using System.IO; 

WebClient myWebClient = new WebClient(); 

// 1) version: do simple request  
string t= myWebClient.UploadString ("http://www.examples.com/", "DELETE", "bla bla"); 
// will be send following: 
// 
// DELETE http://www.examples.com/ HTTP/1.1 
// Host: www.examples.com 
// Content-Length: 7 
// Expect: 100-continue 
// Connection: Keep-Alive 
// 
//bla bla 

// 2) version do complex request  
Stream stream = myWebClient.OpenWrite ("http://www.examples.com/", "DELETE"); 

string postData = "bla bla"; 
byte[] myDataAsBytes = Encoding.UTF8.GetBytes (postData); 
stream.Write (myDataAsBytes, 0, myDataAsBytes.Length); 
stream.Close(); // it send the data 
// will be send following: 
// 
// DELETE http://www.examples.com/ HTTP/1.1 
// Host: www.examples.com 
// Content-Length: 7 
// Expect: 100-continue 
// 
// bla bla 

// 3) version 
// create web request 
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create ("http://www.examples.com/"); 
webRequest.Method = "DELETE"; 
webRequest.ServicePoint.Expect100Continue = false; 

// post data 
Stream requestStream = webRequest.GetRequestStream(); 
StreamWriter requestWriter = new StreamWriter (requestStream); 
requestWriter.Write (postData); 
requestWriter.Close(); 

//wait for server response 
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); 
// send following: 
// DELETE http://www.examples.com/ HTTP/1.1 
// Host: www.examples.com 
// Content-Length: 7 
// Connection: Keep-Alive 
// 
// bla bla 

đầy đủ các mã có thể là một chút phức tạp hơn, nhưng điều này đã sẽ làm việc. Tuy nhiên tôi tiếp tục nói rằng dịch vụ Web cần thiết dữ liệu trong cơ thể của yêu cầu DELETE HTTP là xấu thiết kế.

+1

-1. Người hỏi nói khá rõ ràng rằng anh ta không thể thay đổi dịch vụ web, và anh ta có lẽ cũng không thiết kế nó. Vì mọi đề xuất trong bài đăng này liên quan đến việc thay đổi mã không thuộc quyền kiểm soát của người hỏi, điều này hoàn toàn không hữu ích trong tình huống hiện tại. –

+0

Đối với những gì nó có giá trị, tôi không đồng ý với các điểm của bạn về nguyên tắc; một dịch vụ web yêu cầu các phương thức DELETE với thân máy có lẽ được thiết kế kém. Tuy nhiên, nó là hợp pháp để hỏi làm thế nào để giao tiếp với một dịch vụ web không được thiết kế và có thể không đạt tiêu chuẩn, và đó là cách tôi giải thích câu hỏi này. –

+0

@Walter Mundt: Nếu một ** cần ** gửi nội dung trong HTTP DELETE, tôi đã thêm một ví dụ với một trong những cách có thể để thực hiện việc này. – Oleg

3

sử dụng này,

class MyDelete extends HttpPost{ 
    public MyDelete(String url){ 
     super(url); 
    } 
    @Override 
    public String getMethod() { 
     return "DELETE"; 
    } 
} 
7

Sau lời khuyên Walter Mudnt, bạn có thể sử dụng mã này. Nó hoạt động, chỉ cần thực hiện nó trong khi thử nghiệm webservice REST của tôi.

try { 
     HttpEntity entity = new StringEntity(jsonArray.toString()); 
     HttpClient httpClient = new DefaultHttpClient(); 
     HttpDeleteWithBody httpDeleteWithBody = new HttpDeleteWithBody("http://10.17.1.72:8080/contacts"); 
     httpDeleteWithBody.setEntity(entity); 

     HttpResponse response = httpClient.execute(httpDeleteWithBody); 

    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } catch (ClientProtocolException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

Để truy cập vào trả lời, bạn có thể chỉ cần làm: response.getStatusLine();

+1

Cảm ơn người đàn ông, bạn đá. :) –

0

trong retrofit

import okhttp3.Request; 

private final class ApiInterceptor implements Interceptor { 

    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Request oldRequest = chain.request(); 
     Request.Builder builder = oldRequest.newBuilder(); 
     if(condition) { 
      return chain.proceed(builder.build().newBuilder().delete(builder.build().body()).build()); 
     } 
     return chain.proceed(builder.build()); 
    } 
} 

bạn phải kích hoạt điều kiện, qua một cái gì đó và có khả năng phải làm một số bộ lọc cho các url/tiêu đề/body để xóa trình kích hoạt,

trừ khi xóa url/body/header là duy nhất đủ để không va chạm với bài đăng hoặc nhận yêu cầu.