2016-05-25 40 views
0

所以我只花了6個小時的工作,弄清楚這個'小'的事實: 沒有調用client.getResponseCode()POST請求不通過。POST請求(HttpURLConnection)有趣的問題 - 但爲什麼會發生?

我希望有人能解釋爲什麼! 具體來說,對於這個簡約的Android客戶端獨立代碼,沒有線條int status = client.getResponseCode(); 字面上沒有任何事情發生,但與它,一切工作就像魔術。 我沒有找到關於這方面的任何官方文檔,所以我想知道這是什麼,或者我不明白(執行Java的人通常做出傑出的工作,所以它可能是我沒有得到的東西:))。

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     final String theUrl = "http://xx.yyy.zz.aa:bb/securitiesFollowServer/users"; 
     final String TAG = getClass().getSimpleName(); 

     AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 
      @Override 
      protected Void doInBackground(Void... params) { 
       String body = "BODY OF MESSAGE"; 

       HttpURLConnection client = null; 
       BufferedWriter outputPost = null; 

       try { 
        URL url = new URL(theUrl); 

        // open the connection 
        client = (HttpURLConnection) url.openConnection(); 
        client.setRequestProperty("content-type", "text/plain"); 
        //client.setRequestMethod("POST"); Someone claimed that setDoOutput(true) works so I will try that instead (I tried both,mutually and exclusively so all 3 options). 
        client.setDoOutput(true); 

        outputPost = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); 
        outputPost.write(body); 
        outputPost.flush(); 
        outputPost.close(); 
        int status = client.getResponseCode(); 
        StackTraceElement[] r = Thread.currentThread().getStackTrace(); 
        String toNotepad = ""; 
        for (int i = 0; i < r.length; ++i) { 
         toNotepad += '\n' + String.valueOf(i) + '.' + ':' + r[i].toString(); 
        } 
        // This is where I set a breakpoint and got the stacktrace value from toNotepad,and copy pasted it. 
       } catch (IOException e) { 
        Log.e(TAG, "Error ", e); 
       } finally { 
        if (client != null) { 
         client.disconnect(); 
        } 
        if (outputPost != null) { 
         try { 
          outputPost.close(); 
         } catch (IOException e) { 
          Log.e(TAG, "IO ERROR"); 
         } 
        } 

        return null; 
       } 
      } 
     }; 
     task.execute(); 
    } 
} 

對於這個問題的完整,這裏是「服務器端」簡約代碼

@POST 
@Consumes(MediaType.TEXT_PLAIN) 
@Produces(MediaType.TEXT_PLAIN) 
public String setDebugResource(String a){ 
    return "I got this string:"+a;} 

這裏是堆棧跟蹤(我把它的代碼很明顯上述正是我複製粘貼其值):

不工作的時候(或工作,它是完全一樣的堆棧跟蹤):

0.:dalvik.system.VMStack.getThreadStackTrace(Native Method) 
1.:java.lang.Thread.getStackTrace(Thread.java:580) 
2.:dor.only.dorking.android.apppostrequest.MainActivity$1.doInBackground(MainActivity.java:52) 
3.:dor.only.dorking.android.apppostrequest.MainActivity$1.doInBackground(MainActivity.java:28) 
4.:android.os.AsyncTask$2.call(AsyncTask.java:292) 
5.:java.util.concurrent.FutureTask.run(FutureTask.java:237) 
6.:android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
7.:java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
8.:java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
9.:java.lang.Thread.run(Thread.java:818) 
+0

https://developer.android.com/reference/java/net/HttpURLConnection.html#getResponseCode() –

+0

請在您的問題中提供堆棧跟蹤。 – EJP

+0

@EJP好的我確實爲客戶端提供了堆棧跟蹤(服務器端沒有任何東西,因爲該方法並沒有被調用,我在方法的最開始部署了一個斷點,只有當我調用getResponseCode())。 –

回答

1

根據HttpUrlConnection docs,您必須在客戶端對象上調用setDoOutput(true),而不是將該方法設置爲POST。該方法將通過此自動設置爲POST。他們在「發佈內容」部分有一個例子。

這裏有一個例子here以及和更大的討論here

坦率地說,我會跳過使用原始HttpURLConnection的類,並使用類似排球。

+0

你必須*調用'setDoOutput(true)'。這樣做會將請求方法設置爲POST,但將其設置爲POST不會將'doOutput'設置爲'true'。這兩個都沒有必要。 – EJP

+0

確實沒有必要。還有其他的請求類型(PUT,PATCH,自定義的東西),雖然這兩種請求都需要,但我認爲這是很好的做法。 –

+0

@霍里亞科曼我剛剛嘗試過(我已經在代碼中反映了這個問題),並且行爲完全相同。很煩人吧? :) –