Http协议简述和Http请求在Java中的实现

前言

    最近,项目上要对接几个不同商家提供的第三方接口,这些商家给出的Demo各不相同,一些人对此感到迷惑,在此简单总结一下,以澄清思路。

HTTP协议简述

Http协议是B/S结构程序的理论基础,非常重要,这里简单回顾。
这篇文章介绍比较清楚,需要详细了解,请参考:
https://www.cnblogs.com/coderwhytop/p/14769174.html
本节内容部分参考该文。
概念:
HTTP:HyperText Transfer Protocol(超文本传输协议),用于实现传统的web服务端和客户端之间的通信,是一种无状态协议,短连接协议;是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等),是基于TCP/IP的应用层协议。
Http协议有两个核心内容:
http请求头和http响应头。

1、http请求格式

在这里插入图片描述
请求行:
Method:请求方法(GET,POST,PUT,DELETE,OPTION,TRACE…)
URL:请求的资源地址(相对路径)
Version: http协议的版本(默认HTTP1.1)
请求头:
请求头中包含一系列请求参数,这些参数均已键值对结构形式表示,代表请求的配置信息,例如:content-Type:text/html,text/json,/,Cookie: scroll-cookie=0等
空白行:
在发送请求正文时必须保留空白行
请求体:
请求体即需要发送的数据内容:例如: username=admin&password=123456

我们在应用时,需要注意请求方法(GET,POST),Header设定,业务参数设置。
2、HTTP响应格式
在这里插入图片描述
根据上图,我可以根据需求解析自己对应的内容,比如,header里的内容,响应正文的内容。

java 调用Http请求的几种方式

1、通过JDK网络类Java.net.HttpURLConnection;
2、通过common封装好的HttpClient;
3、通过Apache封装好的CloseableHttpClient;
4、通过OKhttp3;
以上方式,除了JDK原生包HttpURLConnection外,大体结构相差不大,都主要涉及到几个对象:
1、一个Http请求的客户端对象,一般HttpClient,负责发起请求和接受响应;
2、一个URL,需要请求的URL地址;
3、一个代表本次Http请求的对象,Request;
4、一个代表本次Http响应的对象,Response;
结合具体业务,设置不同请求方法,参数等,即可完成对应请求。

通过JDK网络类Java.net.HttpURLConnection

1、包的引用
通过标题,就可以看到这个是JDK原生包,不用多说,直接上代码
2、代码结构
代码结构:
1)、创建一个URL对象URLObj;
2)、用URLObj创建HttpURLConnection实例httpConn;
3)、设置httpConn的参数;
4)、创建基于httpConn的输出流,用于输出到服务器outputStream;
5)、设置输出流的参数;
6)、把流输出到服务器;outputStream.write()
7)、获取httConn的反馈,得到输入流inputStream
8)、把inputStream转化成BufferReader
9)、通过bufferReader的read()方法,获取结果

3、代码实现

package com.wcd.console.http;
import com.alibaba.fastjson.JSONObject;
import com.mysql.cj.x.protobuf.MysqlxDatatypes;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * HttpURLConnection ,引用 JDK 原生提供的 net
 *

 *
 * @Auther: BeinLai
 * @Date: 2023/04/20/10:08
 * @Description:
 */

public class HttpURLConnUtils {

    public void doPost(String strUrl){
        HttpURLConnection conn=null;
        BufferedReader reader=null;
        StringBuffer resultBuffer=null;
        try{
            // 创建目标地址
            URL url=new URL(strUrl);
            //获取连接
            conn=(HttpURLConnection)url.openConnection();

            //设置请求方法
            conn.setRequestMethod("POST");

            // 设置请求内容类型,常见的有"application/json" 数据是个json,
            // "application/x-www-form-urlencoded"  数据是个普通表单
            // multipart/form-data 数据里有文件
            conn.setRequestProperty("Content-Type","application/json");
            //
            conn.setRequestProperty("Authorization","58b24aaa5973564b9edf5e98743fcb2f");

            // 允许输入
            conn.setDoInput(true);
            // 允许输出,POST请求必须设置该属性
            conn.setDoOutput(true);
            // 不需要缓存
            conn.setUseCaches(false);

            // 链接服务器
            conn.connect();
            // 创建一个输出流
            OutputStream os=conn.getOutputStream();
            // 设置参数
            Map<String,String> paraMap=new HashMap<>();
            paraMap.put("userName","杨XX");
            paraMap.put("jobStatus","1");
            // 组装入参
            os.write((JSONObject.toJSONString(paraMap)).getBytes());
            os.flush();
            os.close();

            // 获取返回码
            int responseCode=conn.getResponseCode();
            if(responseCode==HttpURLConnection.HTTP_OK){
                // 获取返回输入流
                InputStream is=conn.getInputStream();
                // 把返回输入流转化成字符串
                resultBuffer=new StringBuffer();
                String line;
                // 创建一个ReadBuffer
                reader=new BufferedReader(new InputStreamReader(is,"utf-8"));
                while((line=reader.readLine())!=null){
                    resultBuffer.append(line);
                }
                reader.close();
                System.out.println("result:"+resultBuffer.toString());
            }

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void doGet(String strUrl,String params){
        HttpURLConnection conn=null;
        BufferedReader reader=null;
        StringBuffer resultBuffer=null;
        try{
            // 创建目标地址
            URL url=new URL(strUrl.replace("${param}",params));
            //获取连接
            conn=(HttpURLConnection)url.openConnection();

            //设置请求方法
            conn.setRequestMethod("GET");

            // 设置请求Header内容
            conn.setRequestProperty("Content-Type","application/json");
            conn.setRequestProperty("Authorization","58b24aaa5973564b9edf5e98743fcb2f");

            // 不需要缓存
            conn.setUseCaches(false);

            // 链接服务器
            conn.connect();


            // 获取返回码
            int responseCode=conn.getResponseCode();
            if(responseCode==HttpURLConnection.HTTP_OK){
                // 获取返回输入流
                InputStream is=conn.getInputStream();
                // 把返回输入流转化成字符串
                resultBuffer=new StringBuffer();
                String line;
                // 创建一个ReadBuffer
                reader=new BufferedReader(new InputStreamReader(is,"utf-8"));
                while((line=reader.readLine())!=null){
                    resultBuffer.append(line);
                }
                reader.close();
                System.out.println("result:"+resultBuffer.toString());
            }

        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

通过common封装好的HttpClient

1、Jar包引用

<dependency>
    <groupId>commons-httpclient</groupId>
     <artifactId>commons-httpclient</artifactId>
     <version>3.1</version>
 </dependency>

2、代码结构:
1)、指定URL;
2)、创建一个HttpClient对象,用于执行httpMethod,比如示例中的PostMethod;
3)、创建PostMethod,参数是url,即针对目标URL创建Method对象;
4)、设置header,设置参数;
5)、使用httpClient对象执行PostMethod,httpClient.executeMethod(postMethod);
6)、处理返回结果,比如code,header,body等;

3、代码实现:

package com.wcd.console.http;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.PostMethod;

import java.util.HashMap;
import java.util.Map;

/**
 * HttpClient,需要用到commons-httpclient-3.1.jar
 *
 * @Auther: BeinLai
 * @Date: 2023/04/20/11:18
 * @Description:
 */

public class WcdHttpClientUtils {
    public void doPost(){
        String strUrl="http://api.f6car.cn/maintain/bill/list";
        HttpClient httpClient=new HttpClient();
        PostMethod postMethod=new PostMethod(strUrl);
        // 设置
        postMethod.addRequestHeader("accept","*/*");
        //设置Content-Type,此处根据实际情况确定
        postMethod.addRequestHeader("Content-Type", "application/json");


        String APP_KEY="204169183";
        String APP_SECURITY="IdCgwcV3QlnhS68uQeNylYvJakY7Nk60";
        //postMethod.setParameter("X-Ca-Key",APP_KEY);
        //postMethod.addRequestHeader("X-Ca-Nonce",APP_SECURITY);

        Map<String,Object> paraMap=new HashMap<>();
        paraMap.put("currentPage",1);
        paraMap.put("pageSize",100);
        paraMap.put("beginModifiedTime","2023-04-10 14:10:00");
        paraMap.put("endModifiedTime","2023-04-10 14:40:00");
        postMethod.setParameter("appKey",APP_KEY);
        postMethod.setParameter("appSecurity",APP_SECURITY);
        postMethod.setParameter("paramValues", JSONObject.toJSONString(paraMap));
        String result="1";
        try{
            int code=httpClient.executeMethod(postMethod);
            //Header header= postMethod.getResponseHeader("X-Ca-Error-Code");
            Header[] headers=postMethod.getResponseHeaders();
            for(Header item:headers){
                System.out.println(item.getName()+"="+item.getValue());
            }
            if(code==200){
                result=postMethod.getResponseBodyAsString();
                System.out.println(result);
            }
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

通过Apache封装好的CloseableHttpClient;

1、添加引用

<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

2、代码结构
1)、创建CloseableHttpClient对象;
2)、创建请求配置 RequestConfig;
3)、创建请求方法,Httppost;
4) 、设置参数,List ;
5)、定义响应对象,通过closeablehttpClient的execute方法,获取响应;
6)、根据需要解析响应对象;

3、代码实现

package com.wcd.console.http;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * CloseableHttpClient 需要用到httpclient-4.5.6.jar
 *
 * @Auther: BeinLai
 * @Date: 2023/04/20/11:45
 * @Description:
 */

public class CloseableHttpClientUtils {
    public void doPost(String url) {
        int timeout = 1000 * 10;


        // 1、创建CloseableHttpClient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 2、创建请求配置 RequestConfig
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout)
                .setConnectionRequestTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
        // 3、创建请求方法
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);

        // 4、设置参数
        List<NameValuePair> nvps = new ArrayList<>();
        Map<String, String> paraMap = new HashMap<>();
        paraMap.put("username", "lai");
        paraMap.put("password", "wwww");
        nvps.add(new BasicNameValuePair("appId", "appKeyVal"));
        nvps.add(new BasicNameValuePair("appSecurity", "appSecurityVal"));
        nvps.add(new BasicNameValuePair("params", JSONObject.toJSONString(paraMap)));

        HttpEntity httpEntity =  new UrlEncodedFormEntity(nvps, Consts.UTF_8);
        httpPost.setEntity(httpEntity);


        CloseableHttpResponse closeableHttpResponse = null;
        try {
            // 5、定义响应对象,通过closeablehttpClient的execute方法,获取响应
            closeableHttpResponse = httpClient.execute(httpPost);
            //6、 解析响应对象
            HttpEntity respEntity = closeableHttpResponse.getEntity();
            String result = EntityUtils.toString(respEntity, Consts.UTF_8);
            EntityUtils.consume(respEntity);
            System.out.println(result);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                closeableHttpResponse.close();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

通过OKhttp3;

1、jar包引用

 <dependency>
    <groupId>com.squareup.okhttp3</groupId>
     <artifactId>okhttp</artifactId>
     <version>3.10.0</version>
 </dependency>

2、代码结构
1)、定义OkHttpClient对象httpClient,Http请求的第一步,定义一个请求客户端;
2)、定义Request;
3)、如果是post请求,需要定义RequestBody,来封装请求参数;如果是Get请求,不需要定义,因为Get请求的参数是在URL中;
4)、获取响应对象;httpClient.newCall(request).execute(),或者通过回调处理httpClient.newCall(request).enqueue()定义回调
5)、处理响应

3、代码实现

package com.wcd.console.http;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;


import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * OkHttp,需要用到okhttp-3.10.0.jar
 *
 *
 * @Auther: BeinLai
 * @Date: 2023/04/20/15:57
 * @Description:
 */

public class WcdOkHttpUtils {

    private static final OkHttpClient httpClient=new OkHttpClient();

    /**
     * get
     */
    public void doGet1(String strUrl){
        Request request=new Request.Builder().url(strUrl).build();
        try {
            Response response = httpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                String body = response.body().toString();
                System.out.println(body);
            } else {
                int code = response.code();
                System.out.println("请求失败,错误代码:" + code);
            }
        }catch (IOException ioe){
            ioe.printStackTrace();
        }
    }

    /**
     * doPost1 :
     *      // RequestBody 有三种构建方式: FormBodyhe MultiparBody 继承RequestBody
     * 		// 1.  FormBody.Builder,构建application/x-www-form-urlencoded类型的post表单
     * 		// 2.  MultipartBody.Builder,构建multipart类型的body,多个内容合成到一个body里
     * 		// 3.  RequestBody.create方法构建body体,传入两个参数:类型和内容
     * RequestBody.create(),RequestBody.create方法构建body体,传入两个参数:类型和内容
     */
    public void doPost1(String strUrl,String auth,Map<String,Object> paraMap){
        MediaType mediaType=MediaType.parse("application/json;charset=utf-8");
        RequestBody requestBody=RequestBody.create(mediaType,JSONObject.toJSONString(paraMap));
        Request request=new Request.Builder()
                .url(strUrl)
                .addHeader("Authorization",auth)
                .post(requestBody)
                .build();
        try {
            Response response= httpClient.newCall(request).execute();
            Headers headers= response.headers();
            Set<String> names=headers.names();
            for(String item:names){
                System.out.println(item+":"+headers.get(item));
            }
            int code=response.code();
            System.out.println("code="+code);
            System.out.println(response.body().string());
        }catch (IOException ioe){
            ioe.printStackTrace();
        }
    }

    /**
     * doPost2
     * MultipartBody.Builder,构建multipart类型的body,多个内容合成到一个body里
     */
    public void doPost2(String strUrl){
        //1、实例化
        String authorization="58b24aaa5973564b9edf5e98743fcb2f";
        Map<String,Object> paraMap=new HashMap();
        paraMap.put("userName","杨飞");
        paraMap.put("jobStatus","1");


        MultipartBody requestBody=new MultipartBody.Builder()
                .addFormDataPart("Authorization",authorization)
                .addFormDataPart("userName","杨飞")
                .addFormDataPart("paramValues", JSONObject.toJSONString(paraMap))
                .build();
        // 2、调用之前先实例化一个request
        Request request=new Request.Builder()
                .url(strUrl)
                .post(requestBody)
                .addHeader("Content_Type","application/json")
                .addHeader("aa","bb")
                .addHeader("referer","https://b.fbpic.com/")
                .build();
        try {
            // 3、 构建调用对象并调用
            // Call call=httpClient.newCall(request);
            // Response rsp = call.execute();
            Response rsp = httpClient.newCall(request).execute();
            System.out.println("isSuccessFull="+rsp.isSuccessful());

            // 返回响应状态码
            int code=rsp.code();
            // 返回响应内容
            ResponseBody responseBody= rsp.body();
            System.out.print(responseBody.toString());

        }catch (IOException ioe){
            ioe.printStackTrace();
        }

    }

    /**
     * formBody
     * FormBody.Builder,构建application/x-www-form-urlencoded类型的post表单
     */
    public void doPost3(String strUrl,String auth,Map<String,Object> params){

        for(String keyName:params.keySet()){
            String val=params.get(keyName).toString();
        }

        FormBody formBody=new FormBody.Builder()
                .add("key1","val1")
                .add("key2","val2")
                .addEncoded("key","val3")
                .build();


        Request request=new Request.Builder()
                .url(strUrl)
                .post(formBody)
                .addHeader("",auth)
                .build();
        Call call=httpClient.newCall(request);
        try {
            Response rsp = call.execute();
        }catch(IOException ioe){

        }
        //call.enqueue(   );
    }
}

综上,简单记录。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日生双翼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值