Http请求相关工具类
2014-07-28 13:50
281 查看
1.Android封装Http请求的工具类
[java] viewplaincopy
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.content.Context;
import android.net.ConnectivityManager;
/**
* 网络工具类
*
* @author malinkang
*
*/
public class NetUtils {
/**
* 对网络连接状态进行判断
*
* @return true, 可用; false, 不可用
*/
public static boolean isOpenNetwork(Context context) {
ConnectivityManager connManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connManager.getActiveNetworkInfo() != null) {
return connManager.getActiveNetworkInfo().isAvailable();
}
return false;
}
/**
* get请求
*
* @param urlString
* @param params
* @return
*/
public static String getRequest(String urlString, Map<String, String> params) {
try {
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(urlString);
if (null != params) {
urlBuilder.append("?");
Iterator<Entry<String, String>> iterator = params.entrySet()
.iterator();
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
urlBuilder
.append(URLEncoder.encode(param.getKey(), "UTF-8"))
.append('=')
.append(URLEncoder.encode(param.getValue(), "UTF-8"));
if (iterator.hasNext()) {
urlBuilder.append('&');
}
}
}
// 创建HttpClient对象
HttpClient client = getNewHttpClient();
// 发送get请求创建HttpGet对象
HttpGet getMethod = new HttpGet(urlBuilder.toString());
HttpResponse response = client.execute(getMethod);
// 获取状态码
int res = response.getStatusLine().getStatusCode();
if (res == 200) {
StringBuilder builder = new StringBuilder();
// 获取响应内容
BufferedReader reader = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
for (String s = reader.readLine(); s != null; s = reader
.readLine()) {
builder.append(s);
}
return builder.toString();
}
} catch (Exception e) {
}
return null;
}
/**
* post请求
*
* @param urlString
* @param params
* @return
*/
public static String postRequest(String urlString,
List<BasicNameValuePair> params) {
try {
// 1. 创建HttpClient对象
HttpClient client = getNewHttpClient();
// 2. 发get请求创建HttpGet对象
HttpPost postMethod = new HttpPost(urlString);
postMethod.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
HttpResponse response = client.execute(postMethod);
int statueCode = response.getStatusLine().getStatusCode();
if (statueCode == 200) {
System.out.println(statueCode);
return EntityUtils.toString(response.getEntity());
}
} catch (Exception e) {
}
return null;
}
// 保存时+当时的秒数,
public static long expires(String second) {
Long l = Long.valueOf(second);
return l * 1000L + System.currentTimeMillis();
}
private static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(
params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
}
2.Android封装的Http请求辅助类
此处我封装了一个HTTP的get和post的辅助类,能够更好的使用;类名:HttpRequestUtil
提供了如下功能:
(1)模拟GET请求;
(2)模拟POST请求;
(3)模拟文件上传请求;
(4)发送XML数据;
发送GET请求
(1)public static URLConnection sendGetRequest(String url, Map<String, String> params, Map<String, String> headers)参数:
(1)url:单纯的URL,不带任何参数;
(2)params:参数;
(3)headers:需要设置的HTTP请求头;
返回:
HttpURLConnection
发送POST请求
(2)public static URLConnection sendPostRequest(String url, Map<String, String> params, Map<String, String> headers)参数:
(1)url:单纯的URL,不带任何参数;
(2)params:参数;
(3)headers:需要设置的HTTP请求头;
返回:
HttpURLConnection
文件上传
(3)public static boolean uploadFiles(String url, Map<String, String> params, FormFile[] files)参数:
(1)url:单纯URL
(2)params:参数;
(3)files:多个文件
返回:是否上传成功
(4)public static boolean uploadFile(String path, Map<String, String> params, FormFile file)
参数:
(1)url:单纯URL
(2)params:参数;
(3)file:一个文件
返回:是否上传成功
发送XML数据
(5)public static byte[] postXml(String url, String xml, String encoding)参数:
(1)url:单纯URL
(2)xml:XML数据
(3)XML数据编码
对于上传文件,FormFile的构造函数声明如下:
(1)public FormFile(String filname, byte[] data, String parameterName, String contentType)
参数:
(1)filname:文件的名称
(2)data:文件的数据
(3)parameterName:HTML的文件上传控件的参数的名字
(4)contentType:文件类型,比如text/plain为txt
(2)public FormFile(String filname, File file, String parameterName, String contentType)
参数:
(1)filname:文件的名称
(2)file:文件名
(3)parameterName:HTML的文件上传控件的参数的名字
(4)contentType:文件类型,比如text/plain为txt
FormFile.java
[java] view
plaincopy
package com.xiazdong.netword.http.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 上传文件
*/
public class FormFile {
/* 上传文件的数据 */
private byte[] data;
private InputStream inStream;
private File file;
/* 文件名称 */
private String filname;
/* 请求参数名称*/
private String parameterName;
/* 内容类型 */
private String contentType = "application/octet-stream";
/**
* 此函数用来传输小文件
* @param filname
* @param data
* @param parameterName
* @param contentType
*/
public FormFile(String filname, byte[] data, String parameterName, String contentType) {
this.data = data;
this.filname = filname;
this.parameterName = parameterName;
if(contentType!=null) this.contentType = contentType;
}
/**
* 此函数用来传输大文件
* @param filname
* @param file
* @param parameterName
* @param contentType
*/
public FormFile(String filname, File file, String parameterName, String contentType) {
this.filname = filname;
this.parameterName = parameterName;
this.file = file;
try {
this.inStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(contentType!=null) this.contentType = contentType;
}
public File getFile() {
return file;
}
public InputStream getInStream() {
return inStream;
}
public byte[] getData() {
return data;
}
public String getFilname() {
return filname;
}
public void setFilname(String filname) {
this.filname = filname;
}
public String getParameterName() {
return parameterName;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}
HttpRequestUtil.java
[java] view
plaincopy
package com.xiazdong.netword.http.util;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/*
* 此类用来发送HTTP请求
* */
public class HttpRequestUtil {
/**
* 发送GET请求
* @param url
* @param params
* @param headers
* @return
* @throws Exception
*/
public static URLConnection sendGetRequest(String url,
Map<String, String> params, Map<String, String> headers)
throws Exception {
StringBuilder buf = new StringBuilder(url);
Set<Entry<String, String>> entrys = null;
// 如果是GET请求,则请求参数在URL中
if (params != null && !params.isEmpty()) {
buf.append("?");
entrys = params.entrySet();
for (Map.Entry<String, String> entry : entrys) {
buf.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(), "UTF-8"))
.append("&");
}
buf.deleteCharAt(buf.length() - 1);
}
URL url1 = new URL(buf.toString());
HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
conn.setRequestMethod("GET");
// 设置请求头
if (headers != null && !headers.isEmpty()) {
entrys = headers.entrySet();
for (Map.Entry<String, String> entry : entrys) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.getResponseCode();
return conn;
}
/**
* 发送POST请求
* @param url
* @param params
* @param headers
* @return
* @throws Exception
*/
public static URLConnection sendPostRequest(String url,
Map<String, String> params, Map<String, String> headers)
throws Exception {
StringBuilder buf = new StringBuilder();
Set<Entry<String, String>> entrys = null;
// 如果存在参数,则放在HTTP请求体,形如name=aaa&age=10
if (params != null && !params.isEmpty()) {
entrys = params.entrySet();
for (Map.Entry<String, String> entry : entrys) {
buf.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(), "UTF-8"))
.append("&");
}
buf.deleteCharAt(buf.length() - 1);
}
URL url1 = new URL(url);
HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
OutputStream out = conn.getOutputStream();
out.write(buf.toString().getBytes("UTF-8"));
if (headers != null && !headers.isEmpty()) {
entrys = headers.entrySet();
for (Map.Entry<String, String> entry : entrys) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.getResponseCode(); // 为了发送成功
return conn;
}
/**
* 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:
* <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">
<INPUT TYPE="text" NAME="name">
<INPUT TYPE="text" NAME="id">
<input type="file" name="imagefile"/>
<input type="file" name="zip"/>
</FORM>
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean uploadFiles(String path, Map<String, String> params, FormFile[] files) throws Exception{
final String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线
final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志
int fileDataLength = 0;
if(files!=null&&files.length!=0){
for(FormFile uploadFile : files){//得到文件类型数据的总长度
StringBuilder fileExplain = new StringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("\r\n");
fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
fileExplain.append("\r\n");
fileDataLength += fileExplain.length();
if(uploadFile.getInStream()!=null){
fileDataLength += uploadFile.getFile().length();
}else{
fileDataLength += uploadFile.getData().length;
}
}
}
StringBuilder textEntity = new StringBuilder();
if(params!=null&&!params.isEmpty()){
for (Map.Entry<String, String> entry : params.entrySet()) {//构造文本类型参数的实体数据
textEntity.append("--");
textEntity.append(BOUNDARY);
textEntity.append("\r\n");
textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");
textEntity.append(entry.getValue());
textEntity.append("\r\n");
}
}
//计算传输给服务器的实体数据总长度
int dataLength = textEntity.toString().getBytes().length + fileDataLength + endline.getBytes().length;
URL url = new URL(path);
int port = url.getPort()==-1 ? 80 : url.getPort();
Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
OutputStream outStream = socket.getOutputStream();
//下面完成HTTP请求头的发送
String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";
outStream.write(requestmethod.getBytes());
String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n";
outStream.write(accept.getBytes());
String language = "Accept-Language: zh-CN\r\n";
outStream.write(language.getBytes());
String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "\r\n";
outStream.write(contenttype.getBytes());
String contentlength = "Content-Length: "+ dataLength + "\r\n";
outStream.write(contentlength.getBytes());
String alive = "Connection: Keep-Alive\r\n";
outStream.write(alive.getBytes());
String host = "Host: "+ url.getHost() +":"+ port +"\r\n";
outStream.write(host.getBytes());
//写完HTTP请求头后根据HTTP协议再写一个回车换行
outStream.write("\r\n".getBytes());
//把所有文本类型的实体数据发送出来
outStream.write(textEntity.toString().getBytes());
//把所有文件类型的实体数据发送出来
if(files!=null&&files.length!=0){
for(FormFile uploadFile : files){
StringBuilder fileEntity = new StringBuilder();
fileEntity.append("--");
fileEntity.append(BOUNDARY);
fileEntity.append("\r\n");
fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");
fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");
outStream.write(fileEntity.toString().getBytes());
if(uploadFile.getInStream()!=null){
byte[] buffer = new byte[1024];
int len = 0;
while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1){
outStream.write(buffer, 0, len);
}
uploadFile.getInStream().close();
}else{
outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);
}
outStream.write("\r\n".getBytes());
}
}
//下面发送数据结束标志,表示数据已经结束
outStream.write(endline.getBytes());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if(reader.readLine().indexOf("200")==-1){//读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
return false;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
return true;
}
/**
* 提交数据到服务器
* @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)
* @param params 请求参数 key为参数名,value为参数值
* @param file 上传文件
*/
public static boolean uploadFile(String path, Map<String, String> params, FormFile file) throws Exception{
return uploadFiles(path, params, new FormFile[]{file});
}
/**
* 将输入流转为字节数组
* @param inStream
* @return
* @throws Exception
*/
public static byte[] read2Byte(InputStream inStream)throws Exception{
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inStream.read(buffer)) !=-1 ){
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
return outSteam.toByteArray();
}
/**
* 将输入流转为字符串
* @param inStream
* @return
* @throws Exception
*/
public static String read2String(InputStream inStream)throws Exception{
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inStream.read(buffer)) !=-1 ){
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
return new String(outSteam.toByteArray(),"UTF-8");
}
/**
* 发送xml数据
* @param path 请求地址
* @param xml xml数据
* @param encoding 编码
* @return
* @throws Exception
*/
public static byte[] postXml(String path, String xml, String encoding) throws Exception{
byte[] data = xml.getBytes(encoding);
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);
conn.setRequestProperty("Content-Length", String.valueOf(data.length));
conn.setConnectTimeout(5 * 1000);
OutputStream outStream = conn.getOutputStream();
outStream.write(data);
outStream.flush();
outStream.close();
if(conn.getResponseCode()==200){
return read2Byte(conn.getInputStream());
}
return null;
}
//测试函数
public static void main(String args[]) throws Exception {
Map<String, String> params = new HashMap<String, String>();
params.put("name", "xiazdong");
params.put("age", "10");
HttpURLConnection conn = (HttpURLConnection) HttpRequestUtil
.sendGetRequest(
"http://192.168.0.103:8080/Server/PrintServlet",
params, null);
int code = conn.getResponseCode();
InputStream in = conn.getInputStream();
byte[]data = read2Byte(in);
}
}
测试代码:
[java] view
plaincopy
Map<String,String> params = new HashMap<String,String>();
params.put("name", name.getText().toString());
params.put("age", age.getText().toString());
HttpURLConnection conn = (HttpURLConnection) HttpRequestUtil.sendGetRequest("http://192.168.0.103:8080/Server/PrintServlet", params, null);
文件上传测试代码:
[java] view
plaincopy
FormFile formFile = new FormFile(file.getName(), file, "document", "text/plain");
boolean isSuccess = HttpRequestUtil.uploadFile("http://192.168.0.103:8080/Server/FileServlet", null, formFile);
3.Android开发_使用HttpURLConnection实现多线程下载
HttpURLConnection继承了URLConnection,因此也可用于向指定网站发送GET请求、POST请求,而且它在URLConnection基础上提供了如下便捷方法:实现多线程下载的步骤:
下边的总结对我帮助蛮大的~不仅用法了解,整个连接流程也要明白!
原文链接地址:
http://www.blogjava.net/supercrsky/articles/247449.html
针对JDK中的URLConnection连接Servlet的问题,网上有虽然有所涉及,但是只是说明了某一个或几个问题,是以FAQ的方式来解决的,而且比较零散,现在对这个类的使用就本人在项目中的使用经验做如下总结:
1:> URL请求的类别:
分为二类,GET与POST请求。二者的区别在于:
a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
2:> URLConnection的对象问题:
URLConnection的对象,如下代码示例:
// 下面的index.jsp由<servlet-mapping>映射到
// 一个Servlet(com.quantanetwork.getClientDataServlet)
// 该Servlet的注意点下边会提到
1 URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro/index.jsp"); 2 3 URLConnection rulConnection = url.openConnection(); 4 // 此处的urlConnection对象实际上是根据URL的 5 // 请求协议(此处是http)生成的URLConnection类 6 // 的子类HttpURLConnection,故此处最好将其转化 7 // 为HttpURLConnection类型的对象,以便用到 8 // HttpURLConnection更多的API.如下: 9 10 HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection;
3:> HttpURLConnection对象参数问题
1 // 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在 2 // http正文内,因此需要设为true, 默认情况下是false; 3 httpUrlConnection.setDoOutput(true); 4 5 // 设置是否从httpUrlConnection读入,默认情况下是true; 6 httpUrlConnection.setDoInput(true); 7 8 // Post 请求不能使用缓存 9 httpUrlConnection.setUseCaches(false); 10 11 // 设定传送的内容类型是可序列化的java对象 12 // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException) 13 httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object"); 14 15 // 设定请求的方法为"POST",默认是GET 16 httpUrlConnection.setRequestMethod("POST"); 17 18 // 连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成, 19 httpUrlConnection.connect();
4:> HttpURLConnection连接问题:
1 // 此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法, 2 // 所以在开发中不调用上述的connect()也可以)。 3 OutputStream outStrm = httpUrlConnection.getOutputStream();
5:> HttpURLConnection写数据与发送数据问题:
1 // 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。 2 ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm); 3 4 // 向对象输出流写出数据,这些数据将存到内存缓冲区中 5 objOutputStrm.writeObject(new String("我是测试数据")); 6 7 // 刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream) 8 objOutputStm.flush(); 9 10 // 关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中, 11 // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器 12 objOutputStm.close(); 13 14 // 调用HttpURLConnection连接对象的getInputStream()函数, 15 // 将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。 16 InputStream inStrm = httpConn.getInputStream(); // <===注意,实际发送请求的代码段就在这里 17 18 // 上边的httpConn.getInputStream()方法已调用,本次HTTP请求已结束,下边向对象输出流的输出已无意义, 19 // 既使对象输出流没有调用close()方法,下边的操作也不会向对象输出流写入任何数据. 20 // 因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、 21 // 重新发送数据(至于是否不用重新这些操作需要再研究) 22 objOutputStm.writeObject(new String("")); 23 httpConn.getInputStream()
总结:a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
对connection对象的一切配置(那一堆set函数)
都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。
这些顺序实际上是由http请求的格式决定的。
如果inputStream读操作在outputStream的写操作之前,会抛出例外:
java.net.ProtocolException: Cannot write output after reading input.......
c:) http请求实际上由两部分组成,
一个是http头,所有关于此次http请求的配置都在http头里面定义,
一个是正文content。
connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,
就必须把所有的配置准备好。
d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,
实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,
而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。
至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求
正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http
请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数
之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)
都是没有意义的了,执行这些操作会导致异常的发生。
6:> Servlet端的开发注意点:
a:) 对于客户端发送的POST类型的HTTP请求,Servlet必须实现doPost方法,而不能用doGet方法。
b:) 用HttpServletRequest的getInputStream()方法取得InputStream的对象,比如:
InputStream inStream = httpRequest.getInputStream();
现在调用inStream.available()(该方法用于“返回此输入流下一个方法调用可以不受阻塞地
从此输入流读取(或跳过)的估计字节数”)时,永远都反回0。试图使用此方法的返回值分配缓冲区,
以保存此流所有数据的做法是不正确的。那么,现在的解决办法是
Servlet这一端用如下实现:
InputStream inStream = httpRequest.getInputStream();
ObjectInputStream objInStream = new ObjectInputStream(inStream);
Object obj = objInStream.readObject();
// 做后续的处理
// 。。。。。。
// 。。。 。。。
而客户端,无论是否发送实际数据都要写入一个对象(那怕这个对象不用),如:
ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm);
objOutputStrm.writeObject(new String("")); // 这里发送一个空数据
// 甚至可以发一个null对象,服务端取到后再做判断处理。
objOutputStrm.writeObject(null);
objOutputStrm.flush();
objOutputStrm.close();
注意:上述在创建对象输出流ObjectOutputStream时,如果将从HttpServletRequest取得的输入流
(即:new ObjectOutputStream(outStrm)中的outStrm)包装在BufferedOutputStream流里面,
则必须有objOutputStrm.flush();这一句,以便将流信息刷入缓冲输出流.如下:
ObjectOutputStream objOutputStrm = new ObjectOutputStream(new BufferedOutputStream(outStrm));
objOutputStrm.writeObject(null);
objOutputStrm.flush(); // <======此处必须要有.
objOutputStrm.close();
HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。可以通过以下两个语句来设置相应的超时:
System.setProperty("sun.net.client.defaultConnectTimeout", 超时毫秒数字符串);
System.setProperty("sun.net.client.defaultReadTimeout", 超时毫秒数字符串);
其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒)
sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒)
例如:
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");
System.setProperty("sun.net.client.defaultReadTime
Java中可以使用HttpURLConnection来请求WEB资源。
HttpURLConnection对象不能直接构造,需要通过URL.openConnection()来获得HttpURLConnection对象,示例代码如下:
1 String szUrl = "http://www.ee2ee.com/"; 2 URL url = new URL(szUrl); 3 HttpURLConnection urlCon = (HttpURLConnection)url.openConnection();
HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时(timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。可以通过以下两个语句来设置相应的超时:
System.setProperty("sun.net.client.defaultConnectTimeout", 超时毫秒数字符串);
System.setProperty("sun.net.client.defaultReadTimeout", 超时毫秒数字符串);
其中: sun.net.client.defaultConnectTimeout:连接主机的超时时间(单位:毫秒)
sun.net.client.defaultReadTimeout:从主机读取数据的超时时间(单位:毫秒)
例如:
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");
System.setProperty("sun.net.client.defaultReadTimeout", "30000");
JDK 1.5以前的版本,只能通过设置这两个系统属性来控制网络超时。在1.5中,还可以使用HttpURLConnection的父类URLConnection的以下两个方法:
setConnectTimeout:设置连接主机超时(单位:毫秒)
setReadTimeout:设置从主机读取数据超时(单位:毫秒)
例如:
1 HttpURLConnection urlCon = (HttpURLConnection)url.openConnection(); 2 urlCon.setConnectTimeout(30000); 3 urlCon.setReadTimeout(30000);
需要注意的是,笔者在JDK1.4.2环境下,发现在设置了defaultReadTimeout的情况下,如果发生网络超时,HttpURLConnection会自动重新提交一次请求,出现一次请求调用,请求服务器两次的问题(Trouble)。我认为这是JDK1.4.2的一个bug。在JDK1.5.0中,此问题已得到解决,不存在自动重发现象。out",
"3000
下面用一个示例来示范使用HttpURLConnection实现多线程下载。此代码来源疯狂讲义一书,该代码主要思路:在Activity中点击按钮,调用DownUtil的download()方法,在download()中启动四个线程去下载资源,每个线程负责下载自己的那部分资源,代码如下:
Activity:
[java] view
plaincopy
package com.home.activity;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import com.home.multithreaddown.R;
import com.home.util.DownUtil;
public class MultiThreadDownActivity extends Activity {
private EditText urlText;
private EditText targetText;
private Button downBtn;
private ProgressBar bar;
private DownUtil downUtil;
private int mDownStatus;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取界面中控件
targetText = (EditText) findViewById(R.id.main_et_name);
urlText = (EditText) findViewById(R.id.main_et_url);
downBtn = (Button) findViewById(R.id.main_btn_download);
bar = (ProgressBar) findViewById(R.id.main_progressBar);
// 创建一个Handler对象
handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
bar.setProgress(mDownStatus);
}
}
};
downBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 初始化DownUtil对象
downUtil = new DownUtil(urlText.getText().toString(),
targetText.getText().toString(), 4);
try {
// 开始下载
downUtil.download();
} catch (Exception e) {
e.printStackTrace();
}
// 定义每秒调度获取一次系统的完成进度
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// 获取下载任务的完成比率
double completeRate = downUtil.getCompleteRate();
mDownStatus = (int) (completeRate * 100);
// 发送消息通知界面更新进度条
handler.sendEmptyMessage(0x123);
// 下载完成后取消任务调度
if (mDownStatus >= 100) {
timer.cancel();
}
}
}, 0, 100);
}
});
}
}
下载的工具类(DownUtil):
[java] view
plaincopy
package com.home.util;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownUtil {
// 定义下载资源的路径
private String path;
// 指定所下载的文件的保存位置
private String targetFile;
// 定义需要使用多少线程下载资源
private int threadNum;
// 定义下载的文件的总大小
private int fileSize;
// 定义下载的线程对象
private DownloadThread[] threads;
public DownUtil(String path, String targetFile, int threadNum) {
this.path = path;
this.threadNum = threadNum;
// 初始化threads数组
threads = new DownloadThread[threadNum];
this.targetFile = targetFile;
}
public void download() throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
conn.setRequestProperty(
"Accept",
"image/gif,image/jpeg,image/pjpeg,application/x-shockwaveflash,application/x-ms-xbap,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty(
"User-Agent",
"Mozilla/4.0(compatible;MSIE7.0;Windows NT 5.2;Trident/4.0;.NET CLR 1.1.4322;.NET CLR 2.0.50727;.NET CLR 3.0.04506.30;.NET CLR 3.0.4506.2152;.NET CLR 3.5.30729)");
conn.setRequestProperty("Connection", "Keep-Alive");
// 得到文件大小
fileSize = conn.getContentLength();
conn.disconnect();
int currentPartSize = fileSize / threadNum + 1;
RandomAccessFile file = new RandomAccessFile(targetFile, "rw");
// 设置本地文件的大小
file.setLength(fileSize);
file.close();
for (int i = 0; i < threadNum; i++) {
// 计算每条线程的下载的开始位置
int startPos = i * currentPartSize;
// 每个线程使用一个RandomAccessFile进行下载
RandomAccessFile currentPart = new RandomAccessFile(targetFile,
"rw");
// 定位该线程的下载位置
currentPart.seek(startPos);
// 创建下载线程
threads[i] = new DownloadThread(startPos, currentPartSize,
currentPart);
// 启动下载线程
threads[i].start();
}
}
/**
* 获取下载完成的百分比
*
* @return
*/
public double getCompleteRate() {
// 统计多条线程已经下载的总大小
int sumSize = 0;
for (int i = 0; i < threadNum; i++) {
sumSize += threads[i].length;
}
// 返回已经完成的百分比
return sumSize * 1.0 / fileSize;
}
private class DownloadThread extends Thread {
// 当前线程的下载位置
private int startPos;
// 定义当前线程负责下载的文件大小
private int currentPartSize;
// 当前线程需要下载的文件块
private RandomAccessFile currentPart;
// 定义该线程已下载的字节数
private int length = 0;
public DownloadThread(int startPos, int currentPartSize,
RandomAccessFile currentPart) {
this.startPos = startPos;
this.currentPartSize = currentPartSize;
this.currentPart = currentPart;
}
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
conn.setRequestProperty(
"Accept",
"image/gif,image/jpeg,image/pjpeg,application/x-shockwaveflash,application/x-ms-xbap,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,*/*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
InputStream is = conn.getInputStream();
// 跳过startPos个字符,表明该线程只下载自己负责那部分文件
is.skip(startPos);
byte[] by = new byte[1024];
int hasRead = 0;
// 读取网络数据,并写入本地文件
while (length < currentPartSize
&& (hasRead = is.read(by)) != -1) {
currentPart.write(by, 0, hasRead);
// 累计该线程下载的总大小
length += hasRead;
}
currentPart.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Activity布局XML:
[html] view
plaincopy
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入url:" />
<EditText
android:id="@+id/main_et_url"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="输入保存的文件名:" />
<EditText
android:id="@+id/main_et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:id="@+id/main_btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载" />
<ProgressBar
android:id="@+id/main_progressBar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
权限:
[html] view
plaincopy
<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 授权访问网络 -->
<uses-permission android:name="android.permission.INTERNET"/>
4.Android平台向web应用get、post方式提交信息案例
参考书:疯狂 android讲义1、效果图展示
2、界面布局
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
>
<Button
android:id="@+id/get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get"
/>
<Button
android:id="@+id/post"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/post"
/>
</LinearLayout>
<EditText
android:id="@+id/show"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:editable="false"
android:cursorVisible="false"
android:gravity="top"
/>
</LinearLayout>
3、改发送get、post请求的工具类,如下:
[java] view
plaincopy
public class GetPostUtil
{
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param params
* 请求参数,请求参数应该是name1=value1&name2=value2的形式。
* @return URL所代表远程资源的响应
*/
public static String sendGet(String url, String params)
{
String result = "";
BufferedReader in = null;
try
{
String urlName = url + "?" + params;
URL realUrl = new URL(urlName);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
// 建立实际的连接
conn.connect();
// 获取所有响应头字段
Map<String, List<String>> map = conn.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet())
{
System.out.println(key + "--->" + map.get(key));
}
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null)
{
result += "\n" + line;
}
}
catch (Exception e)
{
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally
{
try
{
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
return result;
}
/**
* 向指定URL发送POST方法的请求
*
* @param url
* 发送请求的URL
* @param params
* 请求参数,请求参数应该是name1=value1&name2=value2的形式。
* @return URL所代表远程资源的响应
*/
public static String sendPost(String url, String params)
{
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try
{
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(params);
// flush输出流的缓冲
out.flush();
// 定义BufferedReade r输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null)
{
result += "\n" + line;
}
}
catch (Exception e)
{
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
return result;
}
}
如果需要发送get请求只要调用URLConnection的connect()方法去建立实际的连接即可;如果需要发送post请求,则需要获取URLConnection的OutputStream,然后再向网络中输出请求参数,如以上程序!!!
4、activity程序代码
[java] view
plaincopy
public class GetPostMain extends Activity
{
Button get , post;
EditText show;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
get = (Button) findViewById(R.id.get);
post = (Button) findViewById(R.id.post);
show = (EditText)findViewById(R.id.show);
get.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
String response = GetPostUtil
.sendGet("http://192.168.65.1:8080/abc/a.jsp" , null);
show.setText(response);
}
});
post.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
String response = GetPostUtil
.sendPost("http://192.168.65.1:8080/abc/login.jsp"
, "name=crazyit.org&pass=leegang");
show.setText(response);
}
});
}
}
该程序所发送的get、post请求都是向本地局域网内:http://192/168.65.1:8080/abc应用下两个页面发送,这个应用都是部署在本机的web应用;
相关文章推荐
- HTTP请求工具类,完成简单的GET POST请求(为了熟悉相关API)。
- 几个http请求相关的函数 HttpWebRequest: Post , Get ; PostAndRedirect
- http请求相关知识备忘 -- 更新中
- 【使用Java原生API编写发送HTTP_POST请求的工具类】
- android HttpClient get请求与post请求工具类
- 获取HttpServletRequest请求参数的工具类
- 几个http请求相关的函数
- android HttpClient get请求与post请求工具类
- 使用JavaSocket编写发送HTTP_POST请求的工具类
- IIS HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效
- HTTP请求工具类(Java)
- 遭遇“HTTP 错误 500.19 无法访问请求的页面,因为该页的相关配置数据无效。”
- HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效
- HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效 的解决办法
- Http请求工具类
- WIN7下.Net开发遇到的又一问题:HTTP 错误 500.19 - Internal Server Error,无法访问请求的页面,因为该页的相关配置数据无效。
- HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效。
- 遭遇“HTTP 错误 500.19 无法访问请求的页面,因为该页的相关配置数据无效。”
- Android封装的http请求实用工具类
- HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效。