Java 中使用 HttpClinet 工具详解 · 小豆丁个人博客

标签: | 发表时间:2020-03-30 09:20 | 作者:
出处:http://www.mydlq.club

  !版权声明:本博客内容均均为原创,每篇博文作为知识积累,写博不易,转载请注明出处。

http://www.mydlq.club/article/68/

目录[-]


系统环境:

  • JDK 版本:1.8
  • HttpClient 版本:5.0

参考地址:

一、HttpClient 简介

       超文本传输协议(HTTP)可能是当今 Internet上使用的最重要的协议。 Web服务,支持网络的设备和网络计算的增长继续将 HTTP协议的作用扩展到用户驱动的Web浏览器之外,同时增加了需要 HTTP支持的应用程序的数量。

       尽管 java.net软件包提供了用于通过 HTTP访问资源的基本功能,但它并未提供许多应用程序所需的全部灵活性或功能。 HttpClient试图通过提供高效,最新且功能丰富的程序包来实现此空白,以实现最新 HTTP 标准和建议的客户端。

       HttpClient 是为扩展而设计的,同时提供了对基本 HTTP协议的强大支持,对于构建 HTTP感知的客户端应用程序(例如 Web 浏览器,Web 服务客户端或利用或扩展 HTTP协议进行分布式通信的系统)的任何人来说, HttpClient都可能会感兴趣。

二、示例前准备

1、接口测试 Server 项目

       在介绍如何使用 HttpClient的示例前,需要提前准备示例项目进行测试的接口,这里本人使用 SpringBoot提前写了个测试项目,用于后续方便演示,该测试项目 Github 地址为: https://github.com/my-dlq/blog-example/tree/master/java/java-httpclient-example

2、HttpClient 工具使用 Client 项目

(1)、Maven 引入相关依赖

这里是使用 Maven 管理示例项目中的依赖,下面除了需要引入 httpclient依赖外,还需要引入 logbacklombokfastjson相关依赖来提供使用工具时的便利,其中每个依赖的作用分别为:

  • logback:日志框架,方便打印日志。
  • fastjson:用于转换 Json 的工具框架。
  • lombok:这里是用于方便快速实现实体类的 Get 与 Set 方法,且集成 Slf4j 方法与各个日志框架融合。
      <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>club.mydlq</groupId>
    <artifactId>java-httpclient-use-example</artifactId>
    <version>1.0.0</version>
    <name>java-httpclient-use-example</name>
    <description>java httpclient use example</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--httpclient-->
        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
            <version>5.0</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <optional>true</optional>
        </dependency>
        <!--logback-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

</project>

(2)、用于测试的实体类 UserInfo

为了方便后续测试 Json 序列化传递消息的示例,这里提前封装一个用于测试的实体类。

      import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class UserInfo {

    private String name;
    private String sex;

}

二、HttpClient 使用示例(同步)

1、HttpClient 工具类封装

      import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.config.Registry;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.util.TimeValue;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpClientUtil {

    private HttpClientUtil(){}

    /** HttpClient 对象 */
    private static CloseableHttpClient httpClient = null;
    /** CookieStore 对象 */
    private static CookieStore cookieStore = null;
    /** Basic Auth 管理对象 **/
    private static BasicCredentialsProvider basicCredentialsProvider = null;

    // Httpclient 初始化
    static {
        // 注册访问协议相关的 Socket 工厂
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        // Http 连接池
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
        poolingHttpClientConnectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
        poolingHttpClientConnectionManager.setMaxTotal(200);
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(200);
        poolingHttpClientConnectionManager.setValidateAfterInactivity(TimeValue.ofMinutes(5));
        // Http 请求配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000, TimeUnit.MILLISECONDS)
                .setResponseTimeout(5000, TimeUnit.MILLISECONDS)
                .setConnectionRequestTimeout(5000, TimeUnit.MILLISECONDS)
                .build();
        // 设置 Cookie
        cookieStore = new BasicCookieStore();
        // 设置 Basic Auth 对象
        basicCredentialsProvider = new BasicCredentialsProvider();
        // 创建监听器,在 JVM 停止或重启时,关闭连接池释放掉连接
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                log.info("执行关闭 HttpClient");
                httpClient.close();
                log.info("已经关闭 HttpClient");
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }));
        // 创建 HttpClient 对象
        httpClient = HttpClients.custom()
                // 设置 Cookie
                .setDefaultCookieStore(cookieStore)
                // 设置 Basic Auth
                .setDefaultCredentialsProvider(basicCredentialsProvider)
                // 设置 HttpClient 请求参数
                .setDefaultRequestConfig(requestConfig)
                // 设置连接池
                .setConnectionManager(poolingHttpClientConnectionManager)
                // 设置定时清理连接池中过期的连接
                .evictExpiredConnections()
                .evictIdleConnections(TimeValue.ofMinutes(3))
                .build();
    }

    /**
     * 获取 Httpclient 对象
     *
     * @return CloseableHttpClient
     */
    public static CloseableHttpClient getHttpclient() {
        return httpClient;
    }

    /**
     * 获取 CookieStore 对象
     *
     * @return CookieStore
     */
    public static CookieStore getCookieStore() {
        return cookieStore;
    }

    /**
     * 获取 BasicCredentialsProvider 对象
     *
     * @return BasicCredentialsProvider
     */
    public static BasicCredentialsProvider getBasicCredentialsProvider(){
        return basicCredentialsProvider;
    }

}

2、基本操作示例

HttpClient 基本 get、post、form 表单等操作示例:

      import club.mydlq.entity.UserInfo;
import club.mydlq.utils.HttpClientUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * HttpClient 基本 get、post、form 表单等操作示例
 */
@Slf4j
public class BaseExample {

    /**
     * Http Get 请求示例
     */
    public static void httpGet() {
        CloseableHttpResponse response = null;
        try {
            // 创建 HttpGet 对象
            HttpGet httpGet = new HttpGet("http://localhost:8080/base/get?name=mydlq&sex=man");
            // 执行 Http Get 请求
            response = HttpClientUtil.getHttpclient().execute(httpGet);
            // 输出响应内容
            if (response.getEntity() != null) {
                log.info(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            }
            // 销毁流
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ParseException e) {
            log.error("", e);
        } finally {
            // 释放资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /**
     * Http Post Form 表单请求示例
     */
    public static void httpPostForm(){
        CloseableHttpResponse response = null;
        try {
            // 创建 HttpPost 对象
            HttpPost httpPost = new HttpPost("http://localhost:8080/base/form");
            // 设置 HttpPost 请求参数
            List<NameValuePair> params = new ArrayList<>(2);
            params.add(new BasicNameValuePair("name", "mydlq"));
            params.add(new BasicNameValuePair("sex", "man"));
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
            httpPost.setEntity(urlEncodedFormEntity);
            // 设置 Content-Type
            httpPost.addHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.getMimeType());
            // 执行 Http Post 请求
            response = HttpClientUtil.getHttpclient().execute(httpPost);
            // 输出响应内容
            if (response.getEntity() != null) {
                log.info(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            }
            // 销毁流
            EntityUtils.consume(urlEncodedFormEntity);
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ParseException e) {
            log.error("",e);
        } finally {
            // 释放资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /**
     * Http Post Json 表单请求示例
     */
    public static void httpPostJson(){
        CloseableHttpResponse response = null;
        InputStream inputStream = null;
        try {
            // 创建 HttpPost 对象
            HttpPost httpPost = new HttpPost("http://localhost:8080/base/json");
            // 设置请求对象
            UserInfo requestUserInfo = new UserInfo();
            requestUserInfo.setName("mydlq");
            requestUserInfo.setSex("man");
            // 将请求对象通过 fastjson 中方法转换为 Json 字符串,并创建字符串实体对象
            StringEntity stringEntity = new StringEntity(JSON.toJSONString(requestUserInfo), StandardCharsets.UTF_8);
            // 设置 HttpPost 请求参数
            httpPost.setEntity(stringEntity);
            // 设置 Content-Type
            httpPost.addHeader("Content-Type",ContentType.APPLICATION_JSON);
            // 执行 Http Post 请求
            response = HttpClientUtil.getHttpclient().execute(httpPost);
            // 输出响应内容
            if (response.getEntity() != null) {
                inputStream = response.getEntity().getContent();
                UserInfo userInfo = JSON.parseObject(inputStream, UserInfo.class);
                log.info(userInfo.toString());
            }
            // 销毁流
            EntityUtils.consume(stringEntity);
            EntityUtils.consume(response.getEntity());
        } catch (IOException e) {
            log.error("",e);
        } finally {
            // 释放资源
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /** 测试 Main 方法 */
    public static void main(String[] args) {
        // 执行 Http Get 请求
        httpGet();
        // 执行 Http Post Form 表单请求
        httpPostForm();
        // 执行 Http Post Json 请求
        httpPostJson();
    }

}

3、Form 表单登录示例

      import club.mydlq.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
public class LoginExample {

    /**
     * Form 表单登录,登录成功后会自动存 Session,然后再访问一个需要鉴权的页面
     */
    public static void httpFormLogin() {
        CloseableHttpResponse response = null;
        try {
            // 创建 Http 请求
            ClassicHttpRequest request = ClassicRequestBuilder.post("http://localhost:8080/login/from")
                    .addParameter("t_username", "admin")
                    .addParameter("t_password", "123456")
                    .build();
            // 执行 Http 请求,进行登录
            HttpClientUtil.getHttpclient().execute(request);
            // 如果登录成功,则能获取 sessionid
            String jsessionid = HttpClientUtil.getCookieStore().getCookies().get(0).getValue();
            log.info("获取的 sessionid 为:{}", jsessionid);
            // 创建 HttpGet 对象
            HttpGet httpGet = new HttpGet("http://localhost:8080/login/test");
            // 执行 Http Get 请求进行测试
            response = HttpClientUtil.getHttpclient().execute(httpGet);
            // 输出响应内容
            if (response.getEntity() != null) {
                log.info(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            }
            // 销毁流
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ParseException e) {
            log.error("", e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /** 测试 Main 方法 */
    public static void main(String[] args) {
        // 执行 Form 表单登录
        httpFormLogin();
    }

}

4、Basic Auth 验证示例

      import club.mydlq.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
public class BasicAuthExample {

    /**
     * Basic Auth 访问验证测试
     */
    public static void httpBasicAuth() {
        CloseableHttpResponse response = null;
        // 配置 Credentials
        HttpClientUtil.getBasicCredentialsProvider().setCredentials(
                new AuthScope("localhost", 8080),
                new UsernamePasswordCredentials("admin", "123456".toCharArray()));
        try {
            // 创建 Http 请求
            HttpGet httpget = new HttpGet("http://localhost:8080/basic/test");
            // 执行 Http 请求,进行登录
            response = HttpClientUtil.getHttpclient().execute(httpget);
            // 输出响应内容
            if (response.getEntity() != null) {
                log.info(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            }
            // 销毁流
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ParseException e) {
            log.error("", e);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /** 测试 Main 方法 */
    public static void main(String[] args) {
        // 访问需要 BasicAuth 验证的地址,进行测试
        httpBasicAuth();
    }

}

5、文件上传、下载示例

      import club.mydlq.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.*;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

@Slf4j
public class FileExample {

    /**
     * Http Post 上传文件示例
     */
    public static void httpPostUpload() {
        File file = new File("D:" +File.separator + "测试.xlsx");
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost("http://localhost:8080/file/upload");
            HttpEntity entity = MultipartEntityBuilder.create()
                    // 设置编码方式
                    .setCharset(StandardCharsets.UTF_8)
                    // 设置为兼容模式,解决返回中文乱码问题
                    .setMode(HttpMultipartMode.LEGACY)
                    .addPart("file", new FileBody(file))
                    .build();
            httpPost.setEntity(entity);
            // 执行提交
            response = HttpClientUtil.getHttpclient().execute(httpPost);
            // 输出响应内容
            if (response.getEntity() != null) {
                log.info(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            }
            // 销毁流
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ParseException e) {
            log.error("", e);
        } finally {
            // 释放资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /**
     * Http Get 下载文件示例
     */
    public static void httpGetDownload() {
        CloseableHttpResponse response = null;
        try {
            // 创建 HttpGet 对象
            HttpGet httpGet = new HttpGet("http://localhost:8080/file/download");
            // 执行 Http Get 请求
            response = HttpClientUtil.getHttpclient().execute(httpGet);
            // 从 headers 中获取文件名
            String content = response.getHeader("Content-Disposition").getValue();
            String filename = content.substring(content.lastIndexOf('=') + 1, content.lastIndexOf('.'));
            String suffix = content.substring(content.lastIndexOf('.'));
            // 将文件名转码
            filename = URLDecoder.decode(filename, "UTF-8");
            // 获取响应实体对象
            HttpEntity entity = response.getEntity();
            if (entity != null){
                // 获取输入流并且将保存下载的文件
                try (InputStream inputStream = entity.getContent();
                     FileOutputStream fileOutputStream = new FileOutputStream("d://" + filename + suffix)
                ) {
                    byte[] tmp = new byte[1024];
                    int l;
                    while ((l = inputStream.read(tmp)) != -1) {
                        fileOutputStream.write(tmp, 0, l);
                    }
                    fileOutputStream.flush();
                }
            }
            // 销毁流
            EntityUtils.consume(response.getEntity());
        } catch (IOException | ProtocolException e) {
            log.error("", e);
        } finally {
            // 释放资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("", e);
                }
            }
        }
    }

    /** 测试 Main 方法 */
    public static void main(String[] args) {
        // 执行下载文件
        httpGetDownload();
        // 执行上传文件
        httpPostUpload();
    }

}

三、HttpClient 使用示例(异步)

1、HttpAsyncClient 工具类封装

      import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.util.TimeValue;

@Slf4j
public class HttpClientAsycnUtil {

    /**
     * HttpAsyncClient 对象
     */
    private static CloseableHttpAsyncClient closeableHttpAsyncClient = null;

    // HttpAsyncclient 初始化
    static {
        //配置io线程
        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
                .setIoThreadCount(Runtime.getRuntime().availableProcessors())
                .build();
        // Http 异步连接池
        PoolingAsyncClientConnectionManager poolingAsyncClientConnectionManager = new PoolingAsyncClientConnectionManager();
        poolingAsyncClientConnectionManager.setMaxTotal(200);
        poolingAsyncClientConnectionManager.setDefaultMaxPerRoute(200);
        poolingAsyncClientConnectionManager.setValidateAfterInactivity(TimeValue.ofMinutes(5));
        // HttpAsyncClient
        closeableHttpAsyncClient = HttpAsyncClients.custom()
                .setIOReactorConfig(ioReactorConfig)
                .setConnectionManager(poolingAsyncClientConnectionManager)
                .build();
        // 运行
        closeableHttpAsyncClient.start();
    }

    /**
     * 获取 HttpAsyncclient 对象
     *
     * @return CloseableHttpAsyncClient
     */
    public static CloseableHttpAsyncClient getHttpclient() {
        return closeableHttpAsyncClient;
    }

}

2、基本操作示例

      import club.mydlq.utils.HttpClientAsycnUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.Method;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Slf4j
public class BaseExample {

    /**
     * Http 异步请求
     */
    public static void asyncRequest() {
        try {
            HttpHost httpHost = new HttpHost("http","localhost",8080);
            SimpleHttpRequest simpleHttpRequest = SimpleHttpRequests.create(Method.GET,httpHost,"/base/get?name=test&sex=man");
            final Future<SimpleHttpResponse> future = HttpClientAsycnUtil.getHttpclient()
                    .execute(simpleHttpRequest, new FutureCallback<SimpleHttpResponse>() {

                        @Override
                        public void completed(final SimpleHttpResponse response) {
                            log.info(response.toString());
                        }

                        @Override
                        public void failed(final Exception ex) {
                            log.error("执行请求失败:", ex);
                        }

                        @Override
                        public void cancelled() {
                            log.info("取消请求");
                        }

                    });
            String responseBody = future.get().getBody().getBodyText();
            log.info(responseBody);
        } catch (ExecutionException | InterruptedException e) {
            log.error("", e);
            Thread.currentThread().interrupt();
        }
    }

    /** 测试 Main 方法 */
    public static void main(final String[] args) {
        asyncRequest();
    }

}

—END—

相关 [java 中使 httpclinet] 推荐:

Java 中使用 HttpClinet 工具详解 · 小豆丁个人博客

- -
  !版权声明:本博客内容均均为原创,每篇博文作为知识积累,写博不易,转载请注明出处. HttpClient 版本:5.0. Apache Httpclient 官方文档. 博文示例项目 Github 地址:. 一、HttpClient 简介.        超文本传输协议(HTTP)可能是当今. Internet上使用的最重要的协议.

Spring Boot 中使用 Java API 调用 lucene

- - SegmentFault 最新的文章
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言). Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎.

POJO中使用ThreadLocal实现Java嵌套事务

- - ImportNew
大多嵌套事务都是通过EJB实现的,现在我们尝试实现对POJO的嵌套事务. 这里我们使用了ThreadLocal的功能. 所以内层事务或外层事务可以在不影响其他事务的条件下进行回滚或提交. 新建的事务嵌套在外层事务中. 如果内层事务完成(不论是回滚或是提交),外层的事务就可以进行回滚或提交,这样的操作并不会影响内层事务.

Java应用中使用ShutdownHook友好地清理现场(转帖)

- - Java - 编程语言 - ITeye博客
转帖地址:http://www.cnblogs.com/nexiyi/p/java_add_ShutdownHook.html. 在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码. Java中得ShutdownHook提供了比较好的方案.

Elasticsearch:在 Java 客户端中使用 truststore 来创建 HTTPS 连接

- - 掘金 后端
在我之前的文章 “ Elasticsearch:使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群” 里,我使用了两种方法,一直是使用 token 的方式,另外一种是使用 PEM 证书来进行连接的. 在实际的使用中,有时我们的证书是以 PCKS12 格式的 truststore 格式的,那么我们该如何建立这种 HTTPS 的连接呢.

为何要在Java中使用内存映射文件(Memory Mapped File)或者MappedByteBuffer

- - 编程语言 - ITeye博客
尽管从JDK 1.4版本开始,Java内存映射文件(Memory Mapped Files)就已经在java.nio包中,但它对很多程序开发者来说仍然是一个相当新的概念. 引入NIO后,Java IO已经相当快,而且内存映射文件提供了Java有可能达到的最快IO操作,这也是为什么那些高性能Java应用应该使用内存映射文件来持久化数据.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees RUN@Cloud. 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.