发送HTTP 请求有两种方式,一种是使用java自带的api,使用HttpURLConnection,第二种是使用第三方类库,例如apache httpclient。
第一种方法较为简单,无需配置。第二种方法功能较为强大。
本节摘要:
之前介绍过采用httpclient发送get和post请求到http服务器端,那么我们不用这个插件是否也可以正常的用get/post方式发送http请求到http服务端呢?
毕竟用这个插件要下载,还要去看一大推的API,不是那么的方便。
那么,咱们就用JDK自带的URL类和HttpURLConnection类来完成get/post方式的HTTP请求。
场景介绍:
项目中采用http+json的方法访问http服务,客户端发送二进制数据给http服务器端,http服务器端收到请求后,先把二进制数据转换为json字符串,然后再去做一推的逻辑处理,最后把处理的结果以json格式的字符串返回给客户端。
HTTP服务器端----服务端采用的是servlet来写的一个http服务,这里只贴出服务器端接收到二进制数据并且转换为json字符串的代码
/**
* 获取二进制的报文体,并转换成字符串
*/
public String getContext(HttpServletRequest request) throws ServletException, IOException {
byte[] buffer = new byte[64*1024];
InputStream in = request.getInputStream();
int length = in.read(buffer);
String encode = request.getCharacterEncoding();
byte[] data = new byte[length];
System.arraycopy(buffer, 0, data, 0, length);
String context = new String(data, encode);
return context;
}
HTTP客户端----先拼装json字符串,然后转换为二进制数据流发送http请求。拼装json字符串采用jsonobject插件来实现,这里就不贴出来了。
正文内容其实跟get的URL中'?'后的参数字符串一致。拼接的时候,形如:
"userName=" + userName + "&" + "password=" + password;
注意点:
Content-Type和字符集,容易出错,跟服务器端得要配对。
返回内容BufferedReader,得要循环读取。
/**
* 发送请求到http服务然后接收返回报文
* @param jsonStr 请求的json格式的字符串
* @param path 请求的http服务的路径
* @return 返回请求的响应信息
* @throws IOException
*/
public static String post(String jsonStr, String path)
throws IOException {
// 得到请求报文的二进制数据
byte[] data = jsonStr.getBytes();
java.net.URL url = new java.net.URL(path);
//openConnection() 返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接
java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();// 打开一个连接
conn.setRequestMethod("POST");// 设置post方式请求
conn.setConnectTimeout(5 * 1000);// 设置连接超时时间为5秒 JDK1.5以上才有此方法
conn.setReadTimeout(20 * 1000);// 设置读取超时时间为20秒 JDK1.5以上才有此方法
// 打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true
conn.setDoOutput(true);
// 这里只设置内容类型与内容长度的头字段根据传送内容决定
// 内容类型Content-Type:
// application/x-www-form-urlencoded、text/xml;charset=GBK
// 内容长度Content-Length: 38
// conn.setRequestProperty("Content-Type", "text/xml;charset=GBK");
conn.setRequestProperty("Content-Type", "x-www-form-urlencoded;charset=UTF-8");
conn.setRequestProperty("Content-Length", String.valueOf(data.length));
OutputStream outStream = conn.getOutputStream();// 返回写入到此连接的输出流
// 把二进制数据写入是输出流
outStream.write(data);
// 内存中的数据刷入
outStream.flush();
//关闭流
outStream.close();
String msg = "";// 保存调用http服务后的响应信息
// 如果请求响应码是200,则表示成功
if (conn.getResponseCode() == 200) {
// HTTP服务端返回的编码是UTF-8,故必须设置为UTF-8,保持编码统一,否则会出现中文乱码
BufferedReader reader= new BufferedReader(new InputStreamReader(
(InputStream) conn.getInputStream(), "UTF-8"));//返回从此打开的连接读取的输入流
String line;
while ((line = reader.readLine()) != null){
System.out.println(line);
msg += line;
}
reader.close();
}
conn.disconnect();// 断开连接
return msg;
}
说明:
1.因为我们项目组是写服务端,客户端不需要我们写,我只是写了一个客户端来模拟http服务端的调用,故对异常只是抛出,实际中应该捕获住这些异常,比如无法连接到指定的服务,读取数据超时,请求响应失败(200表示响应成功)等等。
2.在处理的过程中遇到的一个大的问题就是请求和输出报文的中文问题。
对于请求报文,只要是请求头部和请求内容字段编码统一,服务器端就可以正常的接受,客户端字符串jsonStr编码是GBK,请求头设置为GBK,已经验证服务器端可以正常接受。
对于输出报文,服务器端采用UTF-8的形式输出,客户端也采用UTF-8的形式接受,也已经通过验证,客户端可以正常接受服务器端返回的中文。
3.关于java.net.URL和java.net.HttpURLConnection类的介绍请查看JDK的API,本客户端基于JDK1.5开发。
4.客户端和服务器端未写明导入类的路径的类,都是普通的java I/O类,此种方式请求http服务端没有采用任何的插件。
5.如果不设置请求头的编码,服务端在下面的一句代码会报空指针异常
String context = new String(data, encode);
6.关于get方法的请求,这里就不列出来了。只是把post改为get而已。
哪位大侠理解的比较深入的,可以说说httpclient请求和此种请求有什么区别?用的时候要怎么来选择呢?
参考资料:
get/post发送HTTP请求2
https://www.cnblogs.com/java-pan/archive/2012/04/27/HTTP-POST-GET.html
HttpUrlConnection用get和post请求发送参数
https://blog.csdn.net/weixin_40321535/article/details/78438478
java httpURL连接远程服务器并返回数据(httpurlconnection)
https://www.cnblogs.com/golon/archive/2012/06/29/httpURL.html