目录
Entity-StringEntity 和 UrlEncodedFormEntity
背景
官网 http://hc.apache.org/httpclient-3.x/
Commons HttpClient项目现已结束,不再开发。它已被HttpClient和HttpCore模块中的Apache HttpComponents项目取代,它提供了更好的性能和更大的灵活性。
我们先从HttpCore开始学习
idea新建maven项目引入jar包
需要引入httpclient和fastjson的依赖
<dependencies>
<!--http://hc.apache.org/httpcomponents-client-ga/httpclient/dependency-info.html-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.7</version>
</dependency>
</dependencies>
quickstart
来源 http://hc.apache.org/httpcomponents-client-ga/quickstart.html
public static void main() throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
/**
* get的请求方式
*/
HttpGet httpGet = new HttpGet("http://httpbin.org/get");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
// The underlying HTTP connection is still held by the response object
// to allow the response content to be streamed directly from the network socket.
//底层HTTP连接仍由响应对象保存,它允许直接从网络套接字流式传输响应内容。
// In order to ensure correct deallocation of system resources
// the user MUST call CloseableHttpResponse#close() from a finally clause.
//为了确保正确释放系统资源,用户必须从finally子句中调用CloseableHttpResponse#close()
// Please note that if response content is not fully consumed the underlying
// connection cannot be safely re-used and will be shut down and discarded
// by the connection manager.
//请注意,如果响应内容没有完全消耗,那么底层连接无法安全重复使用,将被连接管理器关闭并丢弃
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity1);
} finally {
response1.close();
}
/**
* post 请求方式 并携带表单参数
*/
HttpPost httpPost = new HttpPost("http://httpbin.org/post");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("username", "vip"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response2 = httpclient.execute(httpPost);
try {
System.out.println(response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
//对响应主体做一些有用的事情并确保它被完全被消费
EntityUtils.consume(entity2);
} finally {
response2.close();
}
} finally {
httpclient.close();
}
}
使用原生java获取urlStr页面源码并打印响应头和结果
/**
* 使用原生java获取urlStr页面源码并打印响应头和结果
* @param urlStr
* @return
*/
public static String sendGetByJava(String urlStr) {
String result = "";
BufferedReader in = null;
try{
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
connection.setRequestProperty("accept", "*/*");//接受任何 MIME 类型的资源
connection.setRequestProperty("connection", "Keep-Alive");//http连接为长连接
connection.connect();
Map<String, List<String>> map = connection.getHeaderFields();
Set<Map.Entry<String, List<String>>> entries = map.entrySet();
for (Map.Entry<String, List<String>> entry : entries) {
System.out.println(entry.getKey()+"-"+entry.getValue());
}
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null){
result += line;
}
} catch (Exception e){
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally{
try{
if (in != null){
in.close();
}
} catch (Exception e2){
e2.printStackTrace();
}
}
return result;
}
get无参请求返回网页源码
/**
* get方式获取url页面源码
* @param url
* @return
* @throws Exception
*/
public static String getHtmlStr(String url) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet get = new HttpGet(url);
String htmlStr = "";
HttpResponse response = httpClient.execute(get);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
//htmlStr = EntityUtils.toString(response.getEntity());//中文乱码
htmlStr = EntityUtils.toString(response.getEntity(), "UTF-8");
}
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
return htmlStr;
}
get无参请求获取网页源码写入D盘
public static void main() throws IOException {
//使用HttpClient进行网络处理的基本步骤
//1、通过get的方式获取到Response对象。
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://www.baidu.com/");
CloseableHttpResponse response = httpClient.execute(httpGet);
//注意,必需要加上http://的前缀,否则会报:Target host is null异常。
//2、获取Response对象的Entity
HttpEntity entity = response.getEntity();
System.out.println(entity);
//3、通过Entity获取到InputStream对象,然后对返回内容进行处理
InputStream content = entity.getContent();
Scanner scanner = new Scanner(content);
String filename = "D://1.txt";
Writer writer = new PrintWriter(filename);
while (scanner.hasNext()){
//System.out.println(scanner.nextLine());
writer.write(scanner.nextLine());
}
writer.close();//如果此输出流不关闭则数据不会从流中刷到硬盘中
//注意:直接将HttpGet改为HttpPost,返回的结果有误,百度返回302状态,即重定向,新浪返回拒绝访问。怀疑大多网站均不允许POST方法直接访问网站。
}
get请求设置请求时间配置
post类似
//httpclient的请求配置主要是通过RequestConfig封装,然后通过httpGet.setConfig(config);把RequestConfig对象传进来
//https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/config/RequestConfig.html
public static void main() throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet("http://www.baidu.com/");
// 构建请求配置信息
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(1000) //创建连接的最长时间
.setConnectionRequestTimeout(500) //从连接池中获取到连接的最长时间
.setSocketTimeout(10 * 1000) //数据传输的最长时间 socket读数据超时时间:从服务器获取响应数据的超时时间
.build();
// 设置请求配置信息
httpGet.setConfig(config);
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
使用Apache提供的工具类进行转换成字符串
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
httpclient.close();
}
}
get请求传递表单参数1
请求发送
public static void main() throws IOException{
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse=null;
InputStream is = null;
//String url="https://127.0.0.1:8080/httpByGetParams";
//前缀不要为https 否则报错
//javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
String url="http://127.0.0.1:8080/httpByGetParams";
//封装请求参数
List<NameValuePair> params = new ArrayList<>();
BasicNameValuePair basicNameValuePair1 = new BasicNameValuePair("name", "改革开放");
BasicNameValuePair basicNameValuePair2 = new BasicNameValuePair("age", "30");
params.add(basicNameValuePair1);
params.add(basicNameValuePair2);
String str="";
try{
//转换为键值对
str=EntityUtils.toString(new UrlEncodedFormEntity(params,Consts.UTF_8));
System.out.println(str);
//创建get请求
HttpGet httpGet = new HttpGet(url+"?"+str);
//执行get请求
httpResponse = httpClient.execute(httpGet);
//得到响应体
HttpEntity entity = httpResponse.getEntity();
if(entity!=null){
is=entity.getContent();
//转换为字节输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is, Consts.UTF_8));
String body=null;
while ((body=br.readLine())!=null){
System.out.println(body);
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭输入流
if(is!=null){
try {
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
//消耗实体内容
if(httpResponse!=null){
try {
httpResponse.close();
}catch (Exception e){
e.printStackTrace();
}
}
//丢弃http连接
if(httpClient!=null){
try {
httpClient.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
http get请求接收方法
新建 spring boot 项目,直接在启动类上面写方法并启动
@RestController
@SpringBootApplication
@MapperScan("com.whale.luo.mydemo")
public class MydemoApplication {
@GetMapping("httpByGetParams")
public void httpByGetParams(HttpServletRequest request){
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {//传递json数据的时候request是没有表单参数的
String parameterName = parameterNames.nextElement();
System.out.println(parameterName + "===" + request.getParameter(parameterName));
//System.out.println(parameterNames.nextElement()+"=="+request.getParameter(parameterNames.nextElement()));
}
}
public static void main(String[] args) {
SpringApplication.run(MydemoApplication.class, args);
}
}
server:
port: 8080
get 带表单参数和头信息请求方式2 (两种方法)
public static void main() throws IOException {
// 获取连接客户端工具
CloseableHttpClient httpClient = HttpClients.createDefault();
String entityStr = null;
CloseableHttpResponse response = null;
try {
/*
* 由于GET请求的参数都是拼装在URL地址后方,所以我们要构建一个URL,带参数
*/
URIBuilder uriBuilder = new URIBuilder("http://127.0.0.1:8080/httpByGetParams");
//第一种添加参数的形式
//uriBuilder.addParameter("name", "root");
//uriBuilder.addParameter("password", "123456");
//第二种添加参数的形式
List<NameValuePair> list = new LinkedList<>();
BasicNameValuePair param1 = new BasicNameValuePair("name", "root");
BasicNameValuePair param2 = new BasicNameValuePair("password", "123456");
list.add(param1);
list.add(param2);
uriBuilder.setParameters(list);
// 根据带参数的URI对象构建GET请求对象
HttpGet httpGet = new HttpGet(uriBuilder.build());
System.out.println(httpGet.getURI());//http://127.0.0.1:8080/httpByGetParams?name=root&password=123456
/*
* 添加请求头信息
*/
// 浏览器表示
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
// 传输的类型
httpGet.addHeader("Content-Type", "application/x-www-form-urlencoded");
// 执行请求
response = httpClient.execute(httpGet);
// 获得响应的实体对象
HttpEntity entity = response.getEntity();
// 使用Apache提供的工具类进行转换成字符串
entityStr = EntityUtils.toString(entity, "UTF-8");
} catch (ClientProtocolException e) {
System.err.println("Http协议出现问题");
e.printStackTrace();
} catch (ParseException e) {
System.err.println("解析错误");
e.printStackTrace();
} catch (URISyntaxException e) {
System.err.println("URI解析异常");
e.printStackTrace();
} catch (IOException e) {
System.err.println("IO异常");
e.printStackTrace();
} finally {
// 释放连接
if (null != response) {
try {
response.close();
httpClient.close();
} catch (IOException e) {
System.err.println("释放连接出错");
e.printStackTrace();
}
}
}
// 打印响应内容
System.out.println(entityStr);
/*因为GET请求的参数都是拼装到URL后面进行传输的,所以这地方不能直接添加参数,
需要组装好一个带参数的URI传递到HttpGet的构造方法中,构造一个带参数的GET请求。
构造带参数的URI使用URIBuilder类。
上面添加请求参数的方法有两种,建议后者,后者操作更加灵活。*/
}
http接收 共用完善上面已有的接收方法
@GetMapping("httpByGetParams")
public void httpByGetParams(HttpServletRequest request){
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {//传递json数据的时候request是没有表单参数的
String parameterName = parameterNames.nextElement();
System.out.println(parameterName + "===" + request.getParameter(parameterName));
//System.out.println(parameterNames.nextElement()+"=="+request.getParameter(parameterNames.nextElement()));
}
//打印请求头
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
System.out.println(headerName+"=="+request.getHeader(headerName));
}
}
打印结果
post 请求 带表单参数和请求头
接收方法
在 spring boot 启动类上加方法
@PostMapping("httpByPostParams")
public void httpByPostParams(HttpServletRequest request){
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {//传递json数据的时候request是没有表单参数的
String parameterName = parameterNames.nextElement();
System.out.println(parameterName + "===" + request.getParameter(parameterName));
//System.out.println(parameterNames.nextElement()+"=="+request.getParameter(parameterNames.nextElement()));
}
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
System.out.println(headerName+"=="+request.getHeader(headerName));
}
}
post请求
public static void test7() {
// 获取连接客户端工具
CloseableHttpClient httpClient = HttpClients.createDefault();
String entityStr = null;
CloseableHttpResponse response = null;
try {
// 创建POST请求对象
//HttpPost httpPost = new HttpPost("http://www.baidu.com");
HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/httpByPostParams");
/*
* 添加请求参数
*/
// 创建请求参数
List<NameValuePair> list = new LinkedList<>();
BasicNameValuePair param1 = new BasicNameValuePair("name", "root");
BasicNameValuePair param2 = new BasicNameValuePair("password", "123456");
BasicNameValuePair param3 = new BasicNameValuePair("data", "dataStr");
list.add(param1);
list.add(param2);
list.add(param3);
// 使用URL实体转换工具
//HttpEntity reqEntity = new UrlEncodedFormEntity(formparams, "utf-8");
UrlEncodedFormEntity entityParam = new UrlEncodedFormEntity(list, "UTF-8");
httpPost.setEntity(entityParam);
/*
* 添加请求头信息
*/
// 浏览器表示
httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
// 传输的类型
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
// 执行请求
response = httpClient.execute(httpPost);
// 获得响应的实体对象
HttpEntity entity = response.getEntity();
// 使用Apache提供的工具类进行转换成字符串
entityStr = EntityUtils.toString(entity, "UTF-8");
// System.out.println(Arrays.toString(response.getAllHeaders()));
} catch (ClientProtocolException e) {
System.err.println("Http协议出现问题");
e.printStackTrace();
} catch (ParseException e) {
System.err.println("解析错误");
e.printStackTrace();
} catch (IOException e) {
System.err.println("IO异常");
e.printStackTrace();
} finally {
// 释放连接
if (null != response) {
try {
response.close();
httpClient.close();
} catch (IOException e) {
System.err.println("释放连接出错");
e.printStackTrace();
}
}
}
// 打印响应内容
System.out.println(entityStr);
}
参考
https://blog.youkuaiyun.com/YouCanYouUp_/article/details/80769572
https://blog.youkuaiyun.com/wo18237095579/article/details/80482027
Entity-StringEntity 和 UrlEncodedFormEntity
static void testEntity() throws IOException {
Map<String,Object> mapParams = new HashMap<>();
mapParams.put("username","wh");
mapParams.put("password","ale");
StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(mapParams),ContentType.APPLICATION_JSON);
System.out.println(EntityUtils.toString(stringEntity));//{"password":"ale","username":"wh"}
StringEntity stringEntity1 = new StringEntity(JSONObject.toJSONString(mapParams));//{"password":"ale","username":"wh"}
System.out.println(EntityUtils.toString(stringEntity1));
}
- UrlEncodedFormEntity()
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
NameValuePair pair1 = new BasicNameValuePair("supervisor", supervisorEt.getEditableText().toString());
NameValuePair pair2 = new BasicNameValuePair("content", superviseContentEt.getEditableText().toString());
NameValuePair pair3 = new BasicNameValuePair("userId", String.valueOf(signedUser.getId()));
pairs.add(pair1);
pairs.add(pair2);
pairs.add(pair3);
httpPost.setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8))
- StringEntity()
JSONObject postData = new JSONObject();
postData.put("supervisor", supervisorEt.getEditableText().toString());
postData.put("content", superviseContentEt.getEditableText().toString());
postData.put("userId", signedUser.getId());
httpPost.setEntity(new StringEntity(postData.toString(), HTTP.UTF_8));
可以看出,UrlEncodedFormEntity()的形式比较单一,只能是普通的键值对,局限性相对较大。
而StringEntity()的形式比较自由,只要是字符串放进去,不论格式都可以。
https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/HttpEntity.html
https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/entity/StringEntity.html
下一篇在此基础上讲post json数据的 请求与接收