HTTPS、HTTP协议的调用方式实践(WebSerice\HttpToolKit\HttpClient\RestTemplate\OkHttp)

275 阅读6分钟

HTTP 协议

HTTPS协议

跟数据库的CRUD增删改查操作对应关系:

CREATE :PUT READ:GET UPDATE:POST DELETE:DELETE

Http协议支持的请求方法:8种

HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。 HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACECONNECT 方法

GET:## “网址即数据”的形式,缺点不安全,能传递的信息不够长,URL的长度是有限的,不同浏览器不同.最常见,本质就是发送一个请求来取得服务器上的某一资源。

HEAD请求常常被忽略,但是能提供很多有用的信息,特别是在有限的速度和带宽下。主要有以下特点:
1、只请求资源的首部;
2、检查超链接的有效性;
3、检查网页是否被修改;
4、多用于自动搜索机器人获取网页的标志信息,获取rss种子信息,或者传递安全认证信息等

HEAD方法:它与GET方法几乎是一样的,对于HEAD请求的回应部分来说,它的HTTP头部中包含的信息与通过GET请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到Request-URI所标识的资源的信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。\

HTTP状态码:\

1xx:指示信息--表示请求已接收,继续处理。
2xx:成功--表示请求已被成功接收、理解、接受。
3xx:重定向--要完成请求必须进行更进一步的操作。
4xx:客户端错误--请求有语法错误或请求无法实现。
5xx:服务器端错误--服务器未能实现合法的请求。常见状态代码、状态描述的说明如下。
200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。

WebSerice

WebService 请求调用 “WebService采用HTTP协议传输数据,采用XML格式封装数据(即XML中说明调用远程服务对象的哪个方法,传递的参数是什么,以及服务对象的返回结果是什么)。WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式

有状态:有数据存储功能。  有状态对象,就是有实例化的对象,可保存数据,是非线程安全,在不同方法调用间不保留任何状态。
无状态:一次性操作,  不能保存数据。无状态对象,就是没有实例化变量的对象,不能保存数据,是不变类,是线程安全的

WebSerice 请求



    /**
     * http调webservice接口
     *
     * @param url
     * @param paramContent
     * @param user
     * @param pw
     * @return
     * @throws IOException
     */
    public static String doPost(String url, String paramContent, String user, String pw) throws IOException {
//        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        CloseableHttpClient httpClient = createSSLClientDefault();
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(paramContent, "utf-8");
        httpPost.setEntity(entity);
        httpPost.setHeader("Content-Type", "text/xml;charset=utf8");
        String basicAuth = "Basic " + Base64Util.encode((user + ":" + pw).getBytes());
        httpPost.setHeader("Authorization", basicAuth);
        CloseableHttpResponse response = null;
        response = httpClient.execute(httpPost);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8"));
        String str = null;
        StringBuffer buffer = new StringBuffer();
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }
        return buffer.toString();
    }

信任证书


    /**
     * 信任证书
     * @return
     */
    public static CloseableHttpClient createSSLClientDefault(){
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                @Override
                public boolean isTrusted(X509Certificate[] chain,
                                         String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return  HttpClients.createDefault();
    }
}

REST

Representational State Transfer
由Roy Fielding提出
REST是一种架构的风格,这种风格基于一套预定义的规则,这些规则描述了网络资源是如何定义和寻址的。

REST的6个约束

REST所关注的性能,可扩展性,简洁性,互操作性,通信可见性,组件便携性和可靠性都包含在这6个约束里

  1. 客户端-服务端约束:客户端和服务端是分离的,他们可以独自进化。
  2. 无状态:客户端和 服务端的通信必须是无状态的,状态应该包含在请求里。也就是说请求里包含服务端所需要的所有信息,以便服务端可以理解请求并可以创造上下文。
  3. 分层系统:像其他软件架构一样,REST也需要分层结构,但是不允许某层直接访问不相邻的层。
  4. 统一接口:分为4点:
    4.1 资源标识符(URI)
    4.2 资源的操作(也就是方法Method,HTTP动词)
    4.3 自描述的相应(可以认为是媒体类型Media-Type)
    4.4 状态管理(超媒体作为应用状态的引擎HATEOAS,Hypermedia as the Engine of Application State).
  5. 缓存:缓存约束派生于无状态约束,它要求从服务端返回的响应必须明确表明是可缓存的还是不可缓存的。
  6. 按需编码:这允许客户端可以从服务端访问特定的资源而无需知晓如何处理他们。服务器可以扩展或者自定义客户端的功能。

HttpToolKit

HttpClient


 
public String getReulst(String restApiUrl, Map<String, String> paramsMap) throws Exception {

    HttpClient httpClient = createSSLClientDefault();    //信任所有https证书
    
    HttpPost httpPost = new HttpPost(DOMAIN + restApiUrl + "?appid=" + APPID);
    // 构造POST表单Map
    String sign = this.sign(paramsMap);
    
    httpPost.addHeader("sign", sign);
    
    List<NameValuePair> list = new ArrayList<>();
    Iterator<Entry<String, String>> iterator = paramsMap.entrySet().iterator();
    while (iterator.hasNext()) {
        Entry<String, String> elem = iterator.next();
        list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
    }
    if (list.size() > 0) {
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
        httpPost.setEntity(entity);
    }
    
    
    // 发送http post请求,并得到响应结果
    HttpResponse response = httpClient.execute(httpPost);
    
    
    String result = null;
    if (response != null) {
        HttpEntity resEntity = response.getEntity();
        if (resEntity != null) {
            result = EntityUtils.toString(resEntity, "UTF-8");
            //System.out.println(result);
        }
    }
    return result;
}

RestTemplate (Spring)

OkHttp

OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时(简单来说,响应速度快);透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求。 当网络出现问题的时候OkHttp依然坚守自己的职责,它会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP,OkHttp使用现代TLS技术(SNI, ALPN)初始化新的连接,当握手失败时会回退到TLS 1.0。不断请求尝试连接

HTTPS 认证

HttpClient httpClient = createSSLClientDefault();    //信任所有https证书
    
private static CloseableHttpClient createSSLClientDefault() {
    try {
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        }).build();

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        });
        return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    return HttpClients.createDefault();
}

参考文件

HTTP 认证- FineReport帮助文档 - 全面的报表使用教程和学习资料 (fanruan.com)