Http请求的三种方法:Apache HttpClient、Netty HttpClient、Spring RestTemplate(忽略https安全证书)

HttpURLConnection 是Java提供的发起HTTP请求的基础类库

三种Http请求的实现
1、Apache --> http client 
2、Netty --> http client 
3、Spring --> RestTemplate (忽略https安全证书)

一、Apache --》http client


import org.apache.http.NameValuePair;
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.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * http请求实现
 *
 * @author hooyang
 * @date 2019/7/16 10:23
 */
public class HttpClientUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    public HttpClientUtil() {
    }

    public static String doGet(String url, Map param) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String resultString = "";
        CloseableHttpResponse response = null;

        try {
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                Iterator var6 = param.entrySet().iterator();

                while (var6.hasNext()) {
                    Entry entry = (Entry) var6.next();
                    builder.addParameter((String) entry.getKey(), (String) entry.getValue());
                }
            }

            URI uri = builder.build();
            HttpGet httpGet = new HttpGet(uri);
            response = httpclient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception var16) {
            logger.error(var16.getMessage(), var16);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }

                httpclient.close();
            } catch (IOException var15) {
                logger.error(var15.getMessage(), var15);
            }

        }

        return resultString;
    }

    public static String doGet(String url) {
        return doGet(url, (Map) null);
    }

    public static String doPost(String url, Map param) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            HttpPost httpPost = new HttpPost(url);
            if (param != null) {
                List paramList = new ArrayList();
                Iterator var7 = param.entrySet().iterator();

                while (var7.hasNext()) {
                    Entry entry = (Entry) var7.next();
                    paramList.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue()));
                }

                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                httpPost.setEntity(entity);
            }

            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception var17) {
            logger.error(var17.getMessage(), var17);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException var16) {
                logger.error(var16.getMessage(), var16);
            }

        }

        return resultString;
    }

    public static String doPost(String url) {
        return doPost(url, (Map) null);
    }

    public static String doPostJson(String url, String json) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";

        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception var15) {
            logger.error(var15.getMessage(), var15);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException var14) {
                logger.error(var14.getMessage(), var14);
            }

        }

        return resultString;
    }

}


二、Netty --》http client 


import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;

import java.net.URI;

public class HttpClient {

    private String host;
    private int port;
    private String requri;
    private String reqmsg;
    final HttpClientHandler clientHandler;

    public HttpClient() {
        clientHandler = new HttpClientHandler();
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getRequri() {
        return requri;
    }

    public void setRequri(String requri) {
        this.requri = requri;
    }

    public String getReqmsg() {
        return reqmsg;
    }

    public void setReqmsg(String reqmsg) {
        this.reqmsg = reqmsg;
    }

    @SuppressWarnings("finally")
    public String connect() throws Exception {
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.handler(new ChannelInitializer() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码
                    ch.pipeline().addLast(new HttpResponseDecoder());
                    // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码
                    ch.pipeline().addLast(new HttpRequestEncoder());
                    ch.pipeline().addLast(new NioEventLoopGroup());
                    ch.pipeline().addLast(clientHandler);
                }
            });
            ChannelFuture f = b.connect(host, port).sync();
            URI uri = new URI(requri);
            DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST,
                    uri.toASCIIString(), Unpooled.wrappedBuffer(reqmsg.getBytes()));
            // 构建http请求
            request.headers().set(HttpHeaderNames.HOST, host);
            request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderNames.CONNECTION);
            request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes());

            // 发送http请求
            f.channel().write(request);
            f.channel().flush();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            return clientHandler.getResStr();
        }
    }

}


三、Spring --》RestTemplate 


import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * http请求实现
 *
 * @author hooyang
 * @date 2019/7/16 10:23
 */
public class RestTemplateUtil {
    private static Logger logger = LoggerFactory.getLogger(RestTemplateUtil.class);

    public RestTemplateUtil() {
    }

    /**
     * 
     *
     * @param url
     * @param securityValue
     * @return
     */
    public static String postForEntity(String url, String securityValue) {
        String reData = "";

        try {
//            RestTemplate template = new RestTemplate();
            RestTemplate template = new RestTemplate(generateHttpRequestFactory());

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED + "; charset=UTF-8"));

            //参数放入一个map中,restTemplate不能用hashMap
            MultiValueMap param = new LinkedMultiValueMap();
            param.add("securityMsg", securityValue);

            //将参数和header组成一个请求
            HttpEntity> request = new HttpEntity>(param, headers);
            ResponseEntity response = template.postForEntity(url, request, String.class);
            logger.debug("postForEntity reStatusCode:=" + response.getStatusCode());
            logger.debug("postForEntity reHeaders:=" + response.getHeaders());
            logger.debug("postForEntity reBody:=" + response.getBody());
            reData = response.getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reData;
    }

    /**
     * RestTemplete 忽略安全证书
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     * @throws KeyStoreException
     */
    private static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory()
            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
//        TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
        TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                return true;
            }
        };

        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());

        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);
        CloseableHttpClient httpClient = httpClientBuilder.build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient);
        return factory;
    }

}

1、Apache --》http client 是阻塞式的读取 Http request(异步读写网络数据性能更好些)。当 client 到 server 的连接中断时,http client 无法感知到这件事的发生,需要开发者主动的轮训校验
2、Netty --》http client 是事件驱动的,逻辑主要基于回调函数。数据包到来了也好,网络连接中断也好,都要通过写回调函数确定这些事件来临后的后续操作
3、Spring --》RestTemplate  简化了发起HTTP请求以及处理响应的过程,并且支持REST

RestTemplate能大幅简化了提交表单数据的难度,并且附带了自动转换JSON数据的功能,但只有理解了HttpEntity的组成结构(header与body),且理解了与uriVariables之间的差异,才能真正掌握其用法


REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格的名词。REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web 服务

1、REST成熟度的四个层次
  第一个层次(Level0)的Web 服务,只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形  式。SOAP和 XML-RPC都属于此类。
  第二个层次(Level1)的Web 服务,引入了资源的概念。每个资源有对应的标识符和表达。
  第三个层次(Level2)的Web 服务,使用不同的 HTTP 方法来进行不同的操作,并且使用HTTP 状态码来表示不同的结果。如 HTTPGET 方法来获取资源,HTTPDELETE 方法来删除资源。
  第四个层次(Level3)的Web 服务,使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。
 
  其中第三个层次建立了创建、读取、更新和删除(create,read, update, and delete,CRUD)操作与 HTTP方法之间的一对一映射。根据此映射:
(1)若要在服务器上创建资源,应该使用POST 方法。
(2)若要检索某个资源,应该使用GET 方法。
(3)若要更改资源状态或对其进行更新,应该使用PUT 方法。
(4)若要删除某个资源,应该使用DELETE 方法。

2、HTTP请求的状态码
(1)成功Successful              2xx:此类状态码标识客户端的请求被成功接收、理解并接受。常见如200(OK)、204(NoContent)。
(2)重定向Redirection         3xx:这个类别的状态码标识用户代理要做出进一步的动作来完成请求。常见如301(MovedPermanently)、302(MovedTemprarily)。
(3)客户端错误Client Error   4xx:4xx类别的状态码是当客户端象是出错的时使用的。常见如400(BadRequest)、401(Unauthorized)、403(Forbidden)、404(NotFound)。
(4)服务器错误Server Error   5xx:响应状态码以5开头表示服务器知道自己出错或者没有能力执行请求。常见如500(InternalServer Error)、502(BadGateway)、504(GatewayTimeout)。

你可能感兴趣的:(web开发,http,apache,spring)