序本文主要研究一下springboot jest autoconfigureJestPropertiesspring-boot-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/elasticsearch/jest/JestProperties.java@ConfigurationProperties(prefix = “spring.elasticsearch.jest”)public class JestProperties { /** * Comma-separated list of the Elasticsearch instances to use. / private List<String> uris = new ArrayList<>( Collections.singletonList(“http://localhost:9200”)); /* * Login username. / private String username; /* * Login password. / private String password; /* * Whether to enable connection requests from multiple execution threads. / private boolean multiThreaded = true; /* * Connection timeout. / private Duration connectionTimeout = Duration.ofSeconds(3); /* * Read timeout. / private Duration readTimeout = Duration.ofSeconds(3); /* * Proxy settings. / private final Proxy proxy = new Proxy(); //…… public static class Proxy { /* * Proxy host the HTTP client should use. / private String host; /* * Proxy port the HTTP client should use. */ private Integer port; public String getHost() { return this.host; } public void setHost(String host) { this.host = host; } public Integer getPort() { return this.port; } public void setPort(Integer port) { this.port = port; } }}JestProperties提供了uris、username、password、multiThreaded(默认true)、connectionTimeout(默认3s)、readTimeout(默认3s)、proxy的配置JestAutoConfigurationspring-boot-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java@Configuration@ConditionalOnClass(JestClient.class)@EnableConfigurationProperties(JestProperties.class)@AutoConfigureAfter(GsonAutoConfiguration.class)public class JestAutoConfiguration { private final JestProperties properties; private final ObjectProvider<Gson> gsonProvider; private final ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers; public JestAutoConfiguration(JestProperties properties, ObjectProvider<Gson> gson, ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers) { this.properties = properties; this.gsonProvider = gson; this.builderCustomizers = builderCustomizers; } @Bean(destroyMethod = “shutdownClient”) @ConditionalOnMissingBean public JestClient jestClient() { JestClientFactory factory = new JestClientFactory(); factory.setHttpClientConfig(createHttpClientConfig()); return factory.getObject(); } protected HttpClientConfig createHttpClientConfig() { HttpClientConfig.Builder builder = new HttpClientConfig.Builder( this.properties.getUris()); PropertyMapper map = PropertyMapper.get(); map.from(this.properties::getUsername).whenHasText().to((username) -> builder .defaultCredentials(username, this.properties.getPassword())); Proxy proxy = this.properties.getProxy(); map.from(proxy::getHost).whenHasText().to((host) -> { Assert.notNull(proxy.getPort(), “Proxy port must not be null”); builder.proxy(new HttpHost(host, proxy.getPort())); }); map.from(this.gsonProvider::getIfUnique).whenNonNull().to(builder::gson); map.from(this.properties::isMultiThreaded).to(builder::multiThreaded); map.from(this.properties::getConnectionTimeout).whenNonNull() .asInt(Duration::toMillis).to(builder::connTimeout); map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis) .to(builder::readTimeout); customize(builder); return builder.build(); } private void customize(HttpClientConfig.Builder builder) { this.builderCustomizers.orderedStream() .forEach((customizer) -> customizer.customize(builder)); }}JestAutoConfiguration在没有jestClient的bean情况下会通过JestProperties创建了HttpClientConfig,然后使用JestClientFactory创建JestClient,同时标记其destroyMethod为shutdownClient方法JestClientFactoryjest-6.3.1-sources.jar!/io/searchbox/client/JestClientFactory.javapublic class JestClientFactory { final static Logger log = LoggerFactory.getLogger(JestClientFactory.class); private HttpClientConfig httpClientConfig; public JestClient getObject() { JestHttpClient client = new JestHttpClient(); if (httpClientConfig == null) { log.debug(“There is no configuration to create http client. Going to create simple client with default values”); httpClientConfig = new HttpClientConfig.Builder(“http://localhost:9200”).build(); } client.setRequestCompressionEnabled(httpClientConfig.isRequestCompressionEnabled()); client.setServers(httpClientConfig.getServerList()); final HttpClientConnectionManager connectionManager = getConnectionManager(); final NHttpClientConnectionManager asyncConnectionManager = getAsyncConnectionManager(); client.setHttpClient(createHttpClient(connectionManager)); client.setAsyncClient(createAsyncHttpClient(asyncConnectionManager)); // set custom gson instance Gson gson = httpClientConfig.getGson(); if (gson == null) { log.info(“Using default GSON instance”); } else { log.info(“Using custom GSON instance”); client.setGson(gson); } // set discovery (should be set after setting the httpClient on jestClient) if (httpClientConfig.isDiscoveryEnabled()) { log.info(“Node Discovery enabled…”); if (!Strings.isNullOrEmpty(httpClientConfig.getDiscoveryFilter())) { log.info(“Node Discovery filtering nodes on "{}"”, httpClientConfig.getDiscoveryFilter()); } NodeChecker nodeChecker = createNodeChecker(client, httpClientConfig); client.setNodeChecker(nodeChecker); nodeChecker.startAsync(); nodeChecker.awaitRunning(); } else { log.info(“Node Discovery disabled…”); } // schedule idle connection reaping if configured if (httpClientConfig.getMaxConnectionIdleTime() > 0) { log.info(“Idle connection reaping enabled…”); IdleConnectionReaper reaper = new IdleConnectionReaper(httpClientConfig, new HttpReapableConnectionManager(connectionManager, asyncConnectionManager)); client.setIdleConnectionReaper(reaper); reaper.startAsync(); reaper.awaitRunning(); } else { log.info(“Idle connection reaping disabled…”); } Set<HttpHost> preemptiveAuthTargetHosts = httpClientConfig.getPreemptiveAuthTargetHosts(); if (!preemptiveAuthTargetHosts.isEmpty()) { log.info(“Authentication cache set for preemptive authentication”); client.setHttpClientContextTemplate(createPreemptiveAuthContext(preemptiveAuthTargetHosts)); } client.setElasticsearchVersion(httpClientConfig.getElasticsearchVersion()); return client; } public void setHttpClientConfig(HttpClientConfig httpClientConfig) { this.httpClientConfig = httpClientConfig; } //……}JestClientFactory的getObject方法首先创建JestHttpClient,然后设置HttpClient、AsyncClient如果isDiscoveryEnabled为true则会创建NodeChecker并执行Node Discovery如果maxConnectionIdleTime大于0则会创建IdleConnectionReaper,进行Idle connection reaping小结JestProperties提供了uris、username、password、multiThreaded(默认true)、connectionTimeout(默认3s)、readTimeout(默认3s)、proxy的配置JestAutoConfiguration在没有jestClient的bean情况下会通过JestProperties创建了HttpClientConfig,然后使用JestClientFactory创建JestClient,同时标记其destroyMethod为shutdownClient方法JestClientFactory的getObject方法首先创建JestHttpClient,然后设置HttpClient、AsyncClient;如果isDiscoveryEnabled为true则会创建NodeChecker并执行Node Discovery;如果maxConnectionIdleTime大于0则会创建IdleConnectionReaper,进行Idle connection reapingdocJestAutoConfiguration