¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, DreamLu All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: DreamLu 墿¥æ¢¦ (596392912@qq.com) |
| | | */ |
| | | package org.springblade.core.cloud.http; |
| | | |
| | | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.ConnectionPool; |
| | | import okhttp3.OkHttpClient; |
| | | import org.springblade.core.cloud.http.logger.HttpLoggingInterceptor; |
| | | import org.springblade.core.cloud.http.logger.OkHttpSlf4jLogger; |
| | | import org.springblade.core.tool.ssl.DisableValidationTrustManager; |
| | | import org.springblade.core.tool.ssl.TrustAllHostNames; |
| | | import org.springblade.core.tool.utils.Charsets; |
| | | import org.springblade.core.tool.utils.Holder; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.web.client.RestTemplateBuilder; |
| | | import org.springframework.cloud.client.loadbalancer.LoadBalanced; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; |
| | | import org.springframework.http.converter.HttpMessageConverter; |
| | | import org.springframework.http.converter.StringHttpMessageConverter; |
| | | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.SSLSocketFactory; |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.X509TrustManager; |
| | | import java.security.KeyManagementException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * Http RestTemplateHeaderInterceptor é
ç½® |
| | | * |
| | | * @author L.cm |
| | | */ |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @AutoConfiguration |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.enabled", matchIfMissing = true) |
| | | public class RestTemplateConfiguration { |
| | | private final BladeHttpProperties properties; |
| | | |
| | | /** |
| | | * okhttp3 è¯·æ±æ¥å¿æ¦æªå¨ |
| | | * |
| | | * @return HttpLoggingInterceptor |
| | | */ |
| | | @Bean |
| | | public HttpLoggingInterceptor loggingInterceptor() { |
| | | HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new OkHttpSlf4jLogger()); |
| | | interceptor.setLevel(properties.getLevel()); |
| | | return interceptor; |
| | | } |
| | | |
| | | /** |
| | | * okhttp3 龿¥æ± é
ç½® |
| | | * |
| | | * @return okhttp3.ConnectionPool |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public ConnectionPool httpClientConnectionPool() { |
| | | int maxTotalConnections = properties.getMaxConnections(); |
| | | long timeToLive = properties.getTimeToLive(); |
| | | TimeUnit ttlUnit = properties.getTimeUnit(); |
| | | return new ConnectionPool(maxTotalConnections, timeToLive, ttlUnit); |
| | | } |
| | | |
| | | /** |
| | | * é
ç½®OkHttpClient |
| | | * |
| | | * @param connectionPool 龿¥æ± é
ç½® |
| | | * @param interceptor æ¦æªå¨ |
| | | * @return OkHttpClient |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public OkHttpClient okHttpClient(ConnectionPool connectionPool, HttpLoggingInterceptor interceptor) { |
| | | boolean followRedirects = properties.isFollowRedirects(); |
| | | int connectTimeout = properties.getConnectionTimeout(); |
| | | return this.createBuilder(properties.isDisableSslValidation()) |
| | | .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) |
| | | .writeTimeout(30, TimeUnit.SECONDS) |
| | | .readTimeout(30, TimeUnit.SECONDS) |
| | | .followRedirects(followRedirects) |
| | | .connectionPool(connectionPool) |
| | | .addInterceptor(interceptor) |
| | | .build(); |
| | | } |
| | | |
| | | private OkHttpClient.Builder createBuilder(boolean disableSslValidation) { |
| | | OkHttpClient.Builder builder = new OkHttpClient.Builder(); |
| | | if (disableSslValidation) { |
| | | try { |
| | | X509TrustManager disabledTrustManager = DisableValidationTrustManager.INSTANCE; |
| | | TrustManager[] trustManagers = new TrustManager[]{disabledTrustManager}; |
| | | SSLContext sslContext = SSLContext.getInstance("SSL"); |
| | | sslContext.init(null, trustManagers, Holder.SECURE_RANDOM); |
| | | SSLSocketFactory disabledSslSocketFactory = sslContext.getSocketFactory(); |
| | | builder.sslSocketFactory(disabledSslSocketFactory, disabledTrustManager); |
| | | builder.hostnameVerifier(TrustAllHostNames.INSTANCE); |
| | | } catch (NoSuchAlgorithmException | KeyManagementException e) { |
| | | log.warn("Error setting SSLSocketFactory in OKHttpClient", e); |
| | | } |
| | | } |
| | | return builder; |
| | | } |
| | | |
| | | @Bean |
| | | public RestTemplateHeaderInterceptor requestHeaderInterceptor() { |
| | | return new RestTemplateHeaderInterceptor(); |
| | | } |
| | | |
| | | @AutoConfiguration |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.rest-template.enable") |
| | | public static class RestTemplateAutoConfiguration { |
| | | private final ApplicationContext context; |
| | | |
| | | /** |
| | | * æ®éç RestTemplateï¼ä¸éä¼ è¯·æ±å¤´ï¼ä¸è¬åªåå¤é¨ http è°ç¨ |
| | | * |
| | | * @param okHttpClient OkHttpClient |
| | | * @return RestTemplate |
| | | */ |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) { |
| | | restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient)); |
| | | RestTemplate restTemplate = restTemplateBuilder.build(); |
| | | configMessageConverters(context, restTemplate.getMessageConverters()); |
| | | return restTemplate; |
| | | } |
| | | } |
| | | |
| | | @AutoConfiguration |
| | | @RequiredArgsConstructor |
| | | @ConditionalOnClass(OkHttpClient.class) |
| | | @ConditionalOnProperty(value = "blade.http.lb-rest-template.enable") |
| | | public static class LbRestTemplateAutoConfiguration { |
| | | private final ApplicationContext context; |
| | | |
| | | /** |
| | | * æ¯æè´è½½åè¡¡ç LbRestTemplate |
| | | * |
| | | * @param okHttpClient OkHttpClient |
| | | * @return LbRestTemplate |
| | | */ |
| | | @Bean |
| | | @LoadBalanced |
| | | @ConditionalOnMissingBean |
| | | public LbRestTemplate lbRestTemplate(RestTemplateBuilder restTemplateBuilder, OkHttpClient okHttpClient) { |
| | | restTemplateBuilder.requestFactory(() -> new OkHttp3ClientHttpRequestFactory(okHttpClient)); |
| | | LbRestTemplate restTemplate = restTemplateBuilder.build(LbRestTemplate.class); |
| | | restTemplate.getInterceptors().add(context.getBean(RestTemplateHeaderInterceptor.class)); |
| | | configMessageConverters(context, restTemplate.getMessageConverters()); |
| | | return restTemplate; |
| | | } |
| | | } |
| | | |
| | | private static void configMessageConverters(ApplicationContext context, List<HttpMessageConverter<?>> converters) { |
| | | converters.removeIf(x -> x instanceof StringHttpMessageConverter || x instanceof MappingJackson2HttpMessageConverter); |
| | | converters.add(new StringHttpMessageConverter(Charsets.UTF_8)); |
| | | converters.add(new MappingJackson2HttpMessageConverter(context.getBean(ObjectMapper.class))); |
| | | } |
| | | } |