前言
模拟浏览器发请求有两种
| 第几种 | 原理 | 优点 | 
|---|---|---|
| 第一种 | HttpURLConnection 配合 流处理 | 拿状态码等头文件容易 | 
| 第二种 | HttpGet(模拟发送) 配合 CloseableHttpResponse(处理返回值) | 解析字符串数据自动拿字符集(接口拿json用它) | 
目录
第一种代码
初始化
InputStream inputStream=null;
    //这个网站返回的是gbk字符集
    String urladdress="http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";
    String jsonStr = "";
    URL url;
模拟浏览器
1.用url创建HttpURLConnection对象
2.HttpURLConnection设置头文件属性以及连接属性
3.httpConn.setDoInput(true)设置是浏览器输出数据
    try
    {// 获取url连接对象
        url = new URL(urladdress);
        //根据url创建http对象
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        // 设置连接属性
        httpConn.setConnectTimeout(3000);
        httpConn.setDoInput(true);
        httpConn.setRequestMethod("GET");
        //設置发出与接收的字符集
//        httpConn.setRequestProperty("Charsert", "UTF-8");
4.HttpURLConnection得到返回值(状态码和头文件属性和返回数据)
        // 获取相应状态码
        int respCode = httpConn.getResponseCode();
        httpConn.getContentType();  //返回内容字符集utf-8
        httpConn.getContentEncoding();//返回编码头字符集gzip
        //  如果成功发200状态码
        if (respCode == 200)
        {
             inputStream=httpConn.getInputStream();
4.对流解析这里是接口返回json数据
            // ByteArrayOutputStream相当于内存输出流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            // 将输入流转移到内存输出流中
                while ((len = inputStream.read(buffer, 0, buffer.length)) != -1)
                {
                    out.write(buffer, 0, len);
                }
                // 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
                jsonStr=out.toString("GB2312");
//            new String(out.toByteArray(),"GB2312");
        }
    }
    catch (MalformedURLException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
第二种代码
初始化
  CloseableHttpClient httpClient;
         String body = null,status = null;
        // 1 HttpClients是java包里的,用它创建HttpClinet,相当于打开浏览器
        httpClient = HttpClients.createDefault();
        //url太平洋ip接口
        String url = "http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";
将url绑定到HttpGet里
1.1当无参数的绑定时
   HttpGet httpGet = new HttpGet(url);
1.2当有外界传来的map参数的绑定时
map.put(“ip”,ip);
map.put(“json”,“true”);
这里的String url = “http://whois.pconline.com.cn/ipJson.jsp"
        // 声明URIBuilder(动态加变量用)
        URIBuilder uriBuilder = new URIBuilder(url);
       //参数放map里
       Map<String, Object> map = null;
       // 判断参数map是否为非空
       if (map != null) {
           // 遍历参数
          for (Map.Entry<String, Object> entry : map.entrySet()) {
              // 给url上设置参数
               uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
          }
      }
        // 2 创建httpGet对象,相当于设置url请求地址(带参数的)
      HttpGet httpGet = new HttpGet(uriBuilder.build());
向浏览器请求
2.CloseableHttpClient绑定HttpGet并向浏览器请求execute
        // 3 使用HttpClient执行httpGet,相当于按回车,发起请求
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            logger.info(e+"浏览器请求错误");
        }
拿到请求返回来的结果
3.这里可以拿返回来的头文件
eg:返回来的字符集是什么
注意这里是还要用正则表达式解析数据(没写)
// todo:拿状态码(用正则)
        Header[] headers= response.getHeaders("content-type");//拿头文件字符集(包状态码)
        for (Header header : headers) {
            header.getName();               //拿key :content-type
            header.getValue();              //拿值text/html; charset=GBK
            logger.info(header.toString()); //拿全部Content-Type: text/html; charset=GBK
        }
对请求返回的请求体解析
注意CloseableHttpResponse.getEntity()只能用一次
3.1这一部分是对返回的结果是字符串形式的写法
//对返回数据解析
 try {
        if (response.getEntity() != null) {
            //拿状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());
//请求体CloseableHttpResponse.getEntity()不能调用多次,只能调用获取一次
//这种是自动获取发的字符集在解码成字符串,如果没有获取到,在以后面的字符集解码(UTF-8与gbk都行)
            body=EntityUtils.toString(response.getEntity(),"gbk");//body是String
3.2这一部分是对返回的结果是其它文件,用2进制方式(没写)或者用流读取文件
InputToString inputToString = new InputToString();//工具类
  if (response.getEntity() != null) {
            //拿状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());
	//以字节方式读传来的数据
       // byte[] bytes =   EntityUtils.toByteArray(response.getEntity());
//这种方式是以流方式拿数据,所以用gbk解码,因为发来的数据是gbk的
          InputStream in = response.getEntity().getContent();
          body=inputToString.InToString(in);
工具类代码
package com.xiao.demo.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class  InputToString{
    public String InToString(InputStream inputStream) throws IOException {
        String jsonStr;
        // ByteArrayOutputStream相当于内存输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        // 将输入流转移到内存输出流中
        while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
            out.write(buffer, 0, len);
        }
        // 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
        jsonStr = out.toString("GB2312");
        out.close();
        inputStream.close();
        return jsonStr;
    }
}
结尾
        } else {
            //状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());
        }
 } catch (IOException e) {
     e.printStackTrace();
 }
 logger.info("请求体:"+body+"--状态码:"+status);
json解析器
//字符串是这样的{"地址":"内容"}
JSONObject jsonObject = JSONObject.parseObject(String类型);
//取出地址对应内容	
 String pro = jsonObject.getString("地址");
