美文网首页Java In Mind
使用Apache HttpClient发送HTTP请求

使用Apache HttpClient发送HTTP请求

作者: SevenLin1993 | 来源:发表于2019-11-05 23:08 被阅读0次

    技术公众号:Java In Mind(Java_In_Mind),欢迎关注!

    HttpComponents HttpClient 简介

    HttpClient属于Apache HttpComponents项目,基于HttpCore,支持HTTP代理实现,支持状态管理,连接管理,自定义结果处理等功能,代替原先的Commons HttpClient 3.x。

    HttpClient是比较实用的Http请求客户端,相比HttpURLConnection来说封装性更好,也提供了许多用户自定义以及拓展的能力,下面简单来使用一下:

    模拟服务

    @RestController
    @RequestMapping("/demo")
    @SpringBootApplication
    @Slf4j
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        private List<Foo> foos = new CopyOnWriteArrayList<>();
    
        @GetMapping("/list")
        public ResponseEntity list(@RequestParam(value = "name") String name) {
            log.info("accept a list request...");
            return ResponseEntity.ok(foos.stream().filter(i -> i.getName().equals(name)).collect(Collectors.toList()));
        }
    
        @PostMapping
        public ResponseEntity create(@RequestBody Foo foo) {
            log.info("accept create request,foo:{}", foo);
            foos.add(foo);
            return ResponseEntity.ok(foo);
        }
    
        @GetMapping("/error")
        public ResponseEntity error() {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("error");
        }
    
        @GetMapping("/redirect")
        public ResponseEntity redirect() {
            return ResponseEntity.status(HttpStatus.FOUND).header(HttpHeaders.LOCATION, "http://www.baidu.com").build();
        }
    
    
        @Data
        @AllArgsConstructor
        public static class Foo {
            private String name;
            private int age;
        }
    }
    

    发起POST请求

    //request body
    Map<String, String> foo = new HashMap<>();
    foo.put("name", "HTTP");
    foo.put("age", "18");
    
    HttpUriRequest request = RequestBuilder.post().setUri("http://localhost:8080/demo")
        .setEntity(new StringEntity(JSONObject.toJSONString(foo), ContentType.APPLICATION_JSON)).build();
    
    CloseableHttpClient httpClient = HttpClients.createDefault();
    CloseableHttpResponse response = httpClient.execute(request);
    int statusCode = response.getStatusLine().getStatusCode();
    //错误判断
    if (statusCode >= 200 & statusCode < 300) {
        String body = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8.name());
        log.info("请求结果:{}", body);
    } else {
        log.error("请求错误,statusCode={}", statusCode);
    }
    

    发起Get请求

    HttpUriRequest request = RequestBuilder.get().setUri("http://localhost:8080/demo/list")
        .addParameter("name", "HTTP").addHeader("Content-Type", "application/json").build();
            
    //设置超时
    RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000 * 5).build();
    
    CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
    
    CloseableHttpResponse response = httpClient.execute(request);
    
    System.out.println(response);
    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode >= 200 & statusCode < 300) {
        String body = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8.name());
        log.info("请求结果:{}", body);
    } else {
        log.error("请求错误,statusCode={}", statusCode);
    }
    

    使用BasicResponseHandler处理结果

    HttpUriRequest request = RequestBuilder.get().setUri("http://localhost:8080/demo/error")
        .addHeader("Content-Type", "application/json").build();
    CloseableHttpClient httpClient = HttpClients.custom().build();
    try {
        String response = httpClient.execute(request, new BasicResponseHandler());
        System.out.println(response);
    } catch (HttpResponseException e) {
        log.error("error,code={},message={}", e.getStatusCode(), e.getMessage(), e);
    }
    

    设置超时

    // 备注,socketTimeout指接收数据时的超时,connectTimeout指的是建立连接的超时
    RequestConfig.custom()
                    .setSocketTimeout(5 * 1000)//socket超时
                    .setConnectTimeout(10 * 1000)//连接超时
                      .setConnectionRequestTimeout(5000)//从连接池获取连接的超时时间
                    .build();
    

    常用配置(官方例子)

    /*
     * ====================================================================
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     * ====================================================================
     *
     * This software consists of voluntary contributions made by many
     * individuals on behalf of the Apache Software Foundation.  For more
     * information on the Apache Software Foundation, please see
     * <http://www.apache.org/>.
     *
     */
    
    package org.apache.http.examples.client;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.nio.charset.CodingErrorAction;
    import java.util.Arrays;
    
    import javax.net.ssl.SSLContext;
    
    import org.apache.http.Consts;
    import org.apache.http.Header;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpRequest;
    import org.apache.http.HttpResponse;
    import org.apache.http.ParseException;
    import org.apache.http.client.CookieStore;
    import org.apache.http.client.CredentialsProvider;
    import org.apache.http.client.config.AuthSchemes;
    import org.apache.http.client.config.CookieSpecs;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.protocol.HttpClientContext;
    import org.apache.http.config.ConnectionConfig;
    import org.apache.http.config.MessageConstraints;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.config.SocketConfig;
    import org.apache.http.conn.DnsResolver;
    import org.apache.http.conn.HttpConnectionFactory;
    import org.apache.http.conn.ManagedHttpClientConnection;
    import org.apache.http.conn.routing.HttpRoute;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.DefaultHttpResponseFactory;
    import org.apache.http.impl.client.BasicCookieStore;
    import org.apache.http.impl.client.BasicCredentialsProvider;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.DefaultHttpResponseParser;
    import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
    import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.impl.conn.SystemDefaultDnsResolver;
    import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
    import org.apache.http.io.HttpMessageParser;
    import org.apache.http.io.HttpMessageParserFactory;
    import org.apache.http.io.HttpMessageWriterFactory;
    import org.apache.http.io.SessionInputBuffer;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.message.BasicLineParser;
    import org.apache.http.message.LineParser;
    import org.apache.http.ssl.SSLContexts;
    import org.apache.http.util.CharArrayBuffer;
    import org.apache.http.util.EntityUtils;
    
    /**
     * This example demonstrates how to customize and configure the most common aspects
     * of HTTP request execution and connection management.
     */
    public class ClientConfiguration {
    
        public final static void main(String[] args) throws Exception {
    
            // Use custom message parser / writer to customize the way HTTP
            // messages are parsed from and written out to the data stream.
            HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {
    
                @Override
                public HttpMessageParser<HttpResponse> create(
                    SessionInputBuffer buffer, MessageConstraints constraints) {
                    LineParser lineParser = new BasicLineParser() {
    
                        @Override
                        public Header parseHeader(final CharArrayBuffer buffer) {
                            try {
                                return super.parseHeader(buffer);
                            } catch (ParseException ex) {
                                return new BasicHeader(buffer.toString(), null);
                            }
                        }
    
                    };
                    return new DefaultHttpResponseParser(
                        buffer, lineParser, DefaultHttpResponseFactory.INSTANCE, constraints) {
    
                        @Override
                        protected boolean reject(final CharArrayBuffer line, int count) {
                            // try to ignore all garbage preceding a status line infinitely
                            return false;
                        }
    
                    };
                }
    
            };
            HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();
    
            // Use a custom connection factory to customize the process of
            // initialization of outgoing HTTP connections. Beside standard connection
            // configuration parameters HTTP connection factory can define message
            // parser / writer routines to be employed by individual connections.
            HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
                    requestWriterFactory, responseParserFactory);
    
            // Client HTTP connection objects when fully initialized can be bound to
            // an arbitrary network socket. The process of network socket initialization,
            // its connection to a remote address and binding to a local one is controlled
            // by a connection socket factory.
    
            // SSL context for secure connections can be created either based on
            // system or application specific properties.
            SSLContext sslcontext = SSLContexts.createSystemDefault();
    
            // Create a registry of custom connection socket factories for supported
            // protocol schemes.
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslcontext))
                .build();
    
            // Use custom DNS resolver to override the system DNS resolution.
            DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
    
                @Override
                public InetAddress[] resolve(final String host) throws UnknownHostException {
                    if (host.equalsIgnoreCase("myhost")) {
                        return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
                    } else {
                        return super.resolve(host);
                    }
                }
    
            };
    
            // Create a connection manager with custom configuration.
            PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry, connFactory, dnsResolver);
    
            // Create socket configuration
            SocketConfig socketConfig = SocketConfig.custom()
                .setTcpNoDelay(true)
                .build();
            // Configure the connection manager to use socket configuration either
            // by default or for a specific host.
            connManager.setDefaultSocketConfig(socketConfig);
            connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);
            // Validate connections after 1 sec of inactivity
            connManager.setValidateAfterInactivity(1000);
    
            // Create message constraints
            MessageConstraints messageConstraints = MessageConstraints.custom()
                .setMaxHeaderCount(200)
                .setMaxLineLength(2000)
                .build();
            // Create connection configuration
            ConnectionConfig connectionConfig = ConnectionConfig.custom()
                .setMalformedInputAction(CodingErrorAction.IGNORE)
                .setUnmappableInputAction(CodingErrorAction.IGNORE)
                .setCharset(Consts.UTF_8)
                .setMessageConstraints(messageConstraints)
                .build();
            // Configure the connection manager to use connection configuration either
            // by default or for a specific host.
            connManager.setDefaultConnectionConfig(connectionConfig);
            connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);
    
            // Configure total max or per route limits for persistent connections
            // that can be kept in the pool or leased by the connection manager.
            connManager.setMaxTotal(100);
            connManager.setDefaultMaxPerRoute(10);
            connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);
    
            // Use custom cookie store if necessary.
            CookieStore cookieStore = new BasicCookieStore();
            // Use custom credentials provider if necessary.
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            // Create global request configuration
            RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setCookieSpec(CookieSpecs.DEFAULT)
                .setExpectContinueEnabled(true)
                .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
                .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
                .build();
    
            // Create an HttpClient with the given custom dependencies and configuration.
            CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setDefaultCookieStore(cookieStore)
                .setDefaultCredentialsProvider(credentialsProvider)
                .setProxy(new HttpHost("myproxy", 8080))
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();
    
            try {
                HttpGet httpget = new HttpGet("http://httpbin.org/get");
                // Request configuration can be overridden at the request level.
                // They will take precedence over the one set at the client level.
                RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .setProxy(new HttpHost("myotherproxy", 8080))
                    .build();
                httpget.setConfig(requestConfig);
    
                // Execution context can be customized locally.
                HttpClientContext context = HttpClientContext.create();
                // Contextual attributes set the local context level will take
                // precedence over those set at the client level.
                context.setCookieStore(cookieStore);
                context.setCredentialsProvider(credentialsProvider);
    
                System.out.println("executing request " + httpget.getURI());
                CloseableHttpResponse response = httpclient.execute(httpget, context);
                try {
                    System.out.println("----------------------------------------");
                    System.out.println(response.getStatusLine());
                    System.out.println(EntityUtils.toString(response.getEntity()));
                    System.out.println("----------------------------------------");
    
                    // Once the request has been executed the local context can
                    // be used to examine updated state and various objects affected
                    // by the request execution.
    
                    // Last executed request
                    context.getRequest();
                    // Execution route
                    context.getHttpRoute();
                    // Target auth state
                    context.getTargetAuthState();
                    // Proxy auth state
                    context.getProxyAuthState();
                    // Cookie origin
                    context.getCookieOrigin();
                    // Cookie spec used
                    context.getCookieSpec();
                    // User security token
                    context.getUserToken();
    
                } finally {
                    response.close();
                }
            } finally {
                httpclient.close();
            }
        }
    
    }
    

    总结

    HttpClient是我们常用的Http客户端,了解熟悉API以及相关配置有利于我们更好的使用,一般场景下使用默认的配置都能满足要求,如果有特殊的要求也支持自定义配置。

    相关文章

      网友评论

        本文标题:使用Apache HttpClient发送HTTP请求

        本文链接:https://www.haomeiwen.com/subject/pekybctx.html