bac*_*dev 4 java android httpurlconnection
执行请求后,我想检查请求标头,但它不起作用.
我调用getRequestProperties()了一个实例,sun.net.www.protocol.http.HttpURLConnection我总是得到一个带有"已经连接"消息的IllegalStateException.好像我想设置请求属性.但我只想读它们.
此行为的责任代码位于HttpUrlConnection中:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/protocol/http/HttpURLConnection
的.java#HttpURLConnection.getRequestProperties%28%29
public synchronized Map<String, List<String>> getRequestProperties() {
if (connected)
throw new IllegalStateException("Already connected");
// ...
}
Run Code Online (Sandbox Code Playgroud)
好的,也许我应该只在断开连接后读取请求属性.但事实证明,disconnect()不设置connected到false.虽然它应该:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/protocol/http/HttpURLConnection.java#HttpURLConnection.disconnect% 28%29
如果我将流读到最后,它似乎也没有什么区别.在调用disconnect之前或之后关闭InputStream也没有什么区别.
我糊涂了.你能帮助我吗?
disconnect()设置连接到false?重现这个的代码是Android的单元测试(我使用Robolectric),但我认为你也可以在Java项目中使用它,并在删除测试注释后从main()调用它:
/**
* Test if HttpUrlConnection works as expected, because in some cases it seems it doesn't
*
* @throws Exception
*/
@Test
public void testHttpUrlConnection() throws Exception
{
final URL url = new URL("http://www.stackoverflow.com");
final HttpURLConnection urlConnection = ( HttpURLConnection ) url.openConnection( );
urlConnection.setRequestMethod("GET");
InputStream is = null;
try
{
is = urlConnection.getInputStream();
assertEquals(200, urlConnection.getResponseCode());
}
catch (IOException ex)
{
is = urlConnection.getErrorStream( );
}
final String result = copyStreamToString(is); // some html response
// Streams must be closed before disconnecting (according to http://stackoverflow.com/a/11056207/3596676)
is.close();
assertTrue((Boolean) getFieldViaRecursiveReflection(urlConnection, "connected"));
// urlConnection should always be disconnected (according to http://developer.android.com/reference/java/net/HttpURLConnection.html)
urlConnection.disconnect();
assertFalse((Boolean) getFieldViaRecursiveReflection(urlConnection, "connected")); // AssertionError
// getRequestProperties throws IllegalStateException ("already connected")
Map<String, List<String>> requestProperties = urlConnection.getRequestProperties();
// do stuff with the properties
// return the result
}
private static String copyStreamToString( final InputStream is ) throws IOException
{
if ( is == null )
{
return "";
}
BufferedReader reader = new BufferedReader( new InputStreamReader( is ) );
String result = copyBufferedReaderToString( reader );
reader.close( );
return result;
}
private static String copyBufferedReaderToString( final BufferedReader bufferedReader ) throws IOException
{
StringBuffer sb = new StringBuffer( );
String line;
while ( ( line = bufferedReader.readLine( ) ) != null )
{
sb.append( line );
}
return sb.toString( );
}
private static Object getFieldViaRecursiveReflection(final Object object, final String attribute) throws Exception
{
return getFieldViaRecursiveReflection(object, object.getClass(), attribute);
}
private static Object getFieldViaRecursiveReflection(final Object object, final Class<?> c, final String attribute) throws Exception
{
try
{
final Field field = c.getDeclaredField(attribute);
field.setAccessible(true);
return field.get(object);
}
catch (NoSuchFieldException ex)
{
/* end of type hierarchy? */
Class<?> superClass = c.getSuperclass();
if (superClass == null)
{
throw ex;
}
else
{
return getFieldViaRecursiveReflection(object, superClass, attribute);
}
}
}
Run Code Online (Sandbox Code Playgroud)
自从我提出问题以来的2个月里没有人发布答案,但今天我不得不再次处理问题并找到解决方案,我将回答我自己的问题.
我不能回答的回答所有的问题(例如,"为何不urlConnection.disconnect()设定connected的属性urlConnection来false?"),但我发现的主要问题的解决方案,这是读请求的头不工作当urlConnection连接时.
由于某些原因,我不记得了,我希望/需要在请求完成后检查请求标头并且响应在那里.但是我再次查看了getRequestProperties()in 的实现sun.net.www.protocol.http.HttpURLConnection(参见此处的代码)并注意到一个名为filterAndAddHeadersgets 的方法被调用.因此,标题不仅可以在该方法中读取,而且可以设置.我不确定为什么这是在getter方法(getRequestProperties()一个)中完成的,但是当请求已经完成时,你应该在用户尝试添加请求标头时警告用户 - 在这种情况下IllegalStateException是打扰的我这么多.
来解决方案:
我只是在请求发送之前将呼叫转移getRequestProperties()到了.现在一切正常.
PS:
请注意,这不是全部.即使我getRequestProperties()在请求后打电话,我的一个单元测试也成功运行.在这种情况下,urlConnection内部属性connected设置为false.我没有想到这一切,但它可能与响应状态代码304(未修改)有关.如果您必须处理此问题并且出于某种原因无法getRequestProperties()在发送请求之前移动呼叫,这可能有助于提示.
| 归档时间: |
|
| 查看次数: |
3076 次 |
| 最近记录: |