(一)HttpURLConnection

URL编程

URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。通过 URL 我们可以访问 Internet 上的各种网络资源,比如最常见的 www,ftp 站点。浏览器通过解析给定的 URL 可以在网络上查找相应的文件或其他资源。
URL的基本结构由5部分组成:
     <传输协议>://<主机名>:<端口号>/<文件名>

      例如: http://192.168.1.100:8080/helloworld/index.jsp

public void testURL() throws IOException{
      URL url = new URL("http://127.0.0.1:8080/examples/hello.txt?id=10");
          
          System.out.println(url.getProtocol()); // 获取URL协议名:http
          System.out.println(url.getHost());     // 获取URL主机名:127.0.0.1
          System.out.println(url.getPort());     // 获取URL端口号: 8080
          System.out.println(url.getPath());     // 获取URL文件路径:/examples/hello.txt
          System.out.println(url.getFile());     // 获取URL文件名:/examples/hello.txt?id=10
          System.out.println(url.getRef());      // 获取URL在文件中的相对位置:null
          System.out.println(url.getQuery());    // 获取URL查询名:id=10
}

 

http请求

	public static String doPostProcessHttp(String urlAddr, Map<String, String> map, String inputCharset) {
		HttpURLConnection conn = null;
		InputStream is = null;
		OutputStreamWriter out = null;
		String returnStr = null;
		StringBuffer params = new StringBuffer();

		Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, String> element = it.next();
			String value = element.getValue();
			params.append(element.getKey());
			params.append("=");
			params.append(value);
			params.append("&");
		}
		if (params.length() > 0) {
			params.deleteCharAt(params.length() - 1);
		}
		try {
			//和指定站点建立连接 既可以向指定站点获取资源 也可以发送资源 
			URL url = new URL(urlAddr);
			//此处的urlConnection对象实际上是根据URL的请求协议(此处是http)生成的URLConnection类 的子类 HttpURLConnection,故此处最好将其转化为
			//HttpURLConnection类型的对象,以便用到HttpURLConnection更多的API.如下
			conn = (HttpURLConnection) url.openConnection();
			//设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在 http正文内,因此需要设为true, 默认情况下是false;
			conn.setDoOutput(true);
			//设置是否从httpUrlConnection读入,默认情况下是true; 
			conn.setDoInput(true);
			//设定请求的方法为"POST",默认是GET 
			conn.setRequestMethod("POST");
			//Post 请求不能使用缓存
			conn.setUseCaches(false);
			// 设定传送的内容类型是可序列化的java对象  (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能java.io.EOFException)  
			conn.setRequestProperty("Content-type", "application/x-java-serialized- object");
			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			conn.setRequestProperty("Content-Length", String.valueOf(params.length()));
			//连接主机的超时时间
			conn.setConnectTimeout(500000000);
			//从主机读取数据的超时时间
			conn.setReadTimeout(500000000);
			//连接,从上述url.openConnection()至此的配置必须要在connect()之前完成,
			conn.connect();

			//现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。
			out = new OutputStreamWriter(conn.getOutputStream(), inputCharset);
			//向对象输出流写出数据,这些数据将存到内存缓冲区中 
			out.write(params.toString());
			//刷新对象输出流,将任何字节都写入潜在的流中
			out.flush();
			//关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中,   
			//在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器 
			out.close();

			//调用HttpURLConnection连接对象的getInputStream()函数,将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端,
			//此处getInputStream会隐含的进行connect()(即:如同调用上面的connect()方法, 所以在开发中不调用上述的connect()也可以)
			is = conn.getInputStream(); // <===注意,实际发送请求的代码段就在这里

			//获取请求响应结果
			BufferedReader br = new BufferedReader(new InputStreamReader(is, inputCharset));
			StringBuffer retCodeBuffer = new StringBuffer();
			while ((returnStr = br.readLine()) != null) {
				retCodeBuffer.append(returnStr);
			}
			is.close();
			conn.disconnect();
			returnStr = retCodeBuffer.toString();
		} catch (MalformedURLException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (ProtocolException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (UnsupportedEncodingException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (IOException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} finally {
			try {
				if (is != null) is.close();
				if (out != null) out.close();
				if (conn != null) conn.disconnect();
			} catch (Exception ex) {
				ex.printStackTrace();
				returnStr = null;
			}
		}
		if (returnStr != null) {
			returnStr = returnStr.trim();
		}
		return returnStr;
	}

https请求

public static String doPostProcessHttps(String urlAddr, Map<String, String> map, String inputCharset) {
		HttpURLConnection conn = null;
		InputStream is = null;
		OutputStreamWriter out = null;
		String returnStr = null;
		StringBuffer params = new StringBuffer();

		Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, String> element = it.next();
			String value = element.getValue();

			params.append(element.getKey());
			params.append("=");
			params.append(value);
			params.append("&");
		}

		if (params.length() > 0) {
			params.deleteCharAt(params.length() - 1);
		}

		try {
			// 创建SSLContext对象,并使用我们指定的信任管理器初始化 实现三个空方法 用来绕过证书
			TrustManager[] tm = {new MyX509TrustManager()};
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(urlAddr);
			//conn = (HttpURLConnection) url.openConnection();
			HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
			conn1.setSSLSocketFactory(ssf);
			conn1.setDoOutput(true);
			conn1.setRequestMethod("POST");
			conn1.setUseCaches(false);
			conn1.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			conn1.setRequestProperty("Content-Length", String.valueOf(params.length()));
			conn1.setDoInput(true);
			conn1.setConnectTimeout(600000);
			conn1.setReadTimeout(600000);
			conn1.connect();
			out = new OutputStreamWriter(conn1.getOutputStream(), inputCharset);
			out.write(params.toString());
			out.flush();
			out.close();

			is = conn1.getInputStream(); //实际发送请求的代码段就在这里
			BufferedReader br = new BufferedReader(new InputStreamReader(is, inputCharset));
			StringBuffer retCodeBuffer = new StringBuffer();
			while ((returnStr = br.readLine()) != null) {
				retCodeBuffer.append(returnStr);
			}
			is.close();
			conn1.disconnect();

			returnStr = retCodeBuffer.toString();
		} catch (MalformedURLException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (ProtocolException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (UnsupportedEncodingException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (IOException e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} catch (Exception e) {
			LOG.info("doPostProcess error >>>> " + e.getMessage(), e);
			returnStr = null;
		} finally {
			try {
				if (is != null) is.close();
				if (out != null) out.close();
				if (conn != null) conn.disconnect();
			} catch (Exception ex) {
				ex.printStackTrace();
				returnStr = null;
			}
		}
		if (returnStr != null) {
			returnStr = returnStr.trim();
		}
		return returnStr;
	}
/**
 * 证书信任管理器(用于https请求)
 * 在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。
 * 我们可以自己实现该接口,让它信任我们指定的证书。
 */
public class MyX509TrustManager implements X509TrustManager {

	//该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,
	//因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager
	public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
	}

	//该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。
	//在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
	public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
	}

	//返回受信任的X509证书数组。
	public X509Certificate[] getAcceptedIssuers() {
		return null;
	}
}

 

 

 

总结

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(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpUrlConnection 是 Java 标准库中用于发送 HTTP 请求和处理 HTTP 响应的类。它提供了一种简单的方式来与远程服务器进行通信。您可以使用 HttpUrlConnection 类来建立连接、发送请求、读取响应和处理错误。 以下是使用 HttpUrlConnection 发送 GET 请求的示例代码: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpUrlConnectionExample { public static void main(String[] args) { try { URL url = new URL("http://example.com/api"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); System.out.println("Response Code: " + responseCode); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); System.out.println("Response: " + response.toString()); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } ``` 这个示例中,我们创建了一个 URL 对象来指定要发送请求的目标 URL。然后,我们打开一个 HttpURLConnection 连接并设置请求方法为 GET。发送请求后,我们可以获取响应码、读取响应内容,并在最后关闭连接。 您可以根据需要设置请求头、添加请求参数等。同时,HttpUrlConnection 也支持其他的 HTTP 方法,如 POST、PUT、DELETE 等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值