HttpURLConnectionを使用してURLに投稿リクエストを送信しようとしています(JavaでcUrlを使用するため)。リクエストのコンテンツはxmlであり、エンドポイントでは、アプリケーションがxmlを処理し、データベースにレコードを保存してから、xml文字列の形式で応答を送り返します。アプリは、Apache-Tomcatでローカルにホストされます。
このコードを端末から実行すると、期待どおりに行がdbに追加されます。ただし、接続からInputStreamを取得中に、次のように例外がスローされます
Java.io.FileNotFoundException: http://localhost:8080/myapp/service/generate
at Sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.Java:1401)
at org.kodeplay.helloworld.HttpCurl.main(HttpCurl.Java:30)
ここにコードがあります
public class HttpCurl {
public static void main(String [] args) {
HttpURLConnection con;
try {
con = (HttpURLConnection) new URL("http://localhost:8080/myapp/service/generate").openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setDoInput(true);
File xmlFile = new File("test.xml");
String xml = ReadWriteTextFile.getContents(xmlFile);
con.getOutputStream().write(xml.getBytes("UTF-8"));
InputStream response = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
for (String line ; (line = reader.readLine()) != null;) {
System.out.println(line);
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
例外はInputStream response = con.getInputStream();
行にトレースされ、FileNotFoundExceptionに関係するファイルがないように見えるため、混乱を招きます。
Xmlファイルへの接続を直接開こうとしても、この例外はスローされません。
サービスアプリは、スプリングフレームワークとJaxb2Marshallerを使用して応答xmlを作成します。
クラスReadWriteTextFileは here から取得されます
ありがとう。
Edit:データをDBに保存し、同時に404応答ステータスコードを送り返します。
また、phpを使用してcurlを実行し、CURLINFO_HTTP_CODE
を出力してみましたが、200になりました。
これをデバッグするにはどうすればよいですか?サービスとクライアントの両方がローカルサーバー上にあります。
解決済み:SO自体で answer を参照した後、問題を解決できました。
非標準ポートでURLに接続すると、HttpURLConnectionは常に404応答を返すようです。
これらの行を追加すると解決しました
con.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
con.setRequestProperty("Accept","*/*");
Spring/JAXBの組み合わせについては知りませんが、平均REST WebサービスはPOST/PUTで応答本文を返さず、単に response status を返します。あなたは体の代わりにそれを決定したいです。
交換
InputStream response = con.getInputStream();
沿って
int status = con.getResponseCode();
使用可能なすべてのステータスコードとその意味は、前にリンクしたとおり、HTTP仕様で使用できます。 Webサービス自体には、Webサービスでサポートされるすべてのステータスコードとその特別な意味(存在する場合)の概要を示すドキュメントも付属する必要があります。
ステータスが4nn
または5nn
で始まる場合、代わりにgetErrorStream()
を使用して、エラーの詳細が含まれている可能性のある応答本文を読み取ります。
InputStream error = con.getErrorStream();
FileNotFound
は、Webサーバーが404を返したことを示すために使用される不幸な例外です。
将来この問題を抱える人にとって、理由はステータスコードが404(または私の場合は500)だったからです。ステータスコードが200でない場合、InpuStream
関数はエラーをスローするようです。
私の場合、自分のサーバーを制御し、エラーが発生したことを示す500ステータスコードを返していました。エラーの詳細を示す文字列メッセージを含む本文も送信しましたが、inputstream
は、本文が完全に読み取り可能であってもエラーをスローしました。
サーバーを制御している場合、200ステータスコードを自分で送信し、文字列エラーレスポンスが何であれ処理することで処理できると思います。
これにつまずいた人は、SOAPリクエストヘッダーをSOAPサービスに送信しようとしたときに同じことが起こりました。この問題はコードの順序が間違っていたため、XMLボディを送信する前に入力ストリームを最初に要求しました。以下のコードでは、InputStream in = conn.getInputStream();
行はByteArrayOutputStream out = new ByteArrayOutputStream();
の直後にありますが、これは間違った順序です。
ByteArrayOutputStream out = new ByteArrayOutputStream();
// send SOAP request as part of HTTP body
byte[] data = request.getHttpBody().getBytes("UTF-8");
conn.getOutputStream().write(data);
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
Log.d(TAG, "http response code is " + conn.getResponseCode());
return null;
}
InputStream in = conn.getInputStream();
この場合のFileNotFound
は、HTTP応答コード400をエンコードする残念な方法でした。
この場合のFileNotFoundは、サーバーから404を取得したことを意味します。サーバーが「POST」リクエストを好まない可能性がありますか?
解決策:
変更localhostのIPあなたのPC
これを知りたい場合:Windows + r> cmd> ipconfig
例:http://192.168.0.107/directory/service/program.php?action=sendSomething
自分のIPに192.168.0.107を置き換える(127.0.0.1localhost)と同じため