Springboot2.1中使用RestTemplate
pom中引用httpclient
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
参数类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component("proxyConfig")
@ConfigurationProperties(prefix="rest-poxy",ignoreUnknownFields = false)
public class ProxyConfig {
//是否启用代理
private Boolean enabled;
//代理的主机
private String host;
//代理的端口
private Integer port;
//连接超时
private Integer connectTimeout;
//读取超时
private Integer readTimeout;
//认证码
private String authorizationCode;
//最大连接数
private Integer maxTotal;
//同路由并发数
private Integer maxPerRoute;
//重连接次数
private Integer retryHandler;
//连接不够用时的等待时间
private Integer connectionRequestTimeout;
//请求的前缀
private String urlPrefix;
public String getUrlPrefix() {
return "http://"+ host + ":" + port + "/openapi";
}
}
yml
rest-poxy:
# 数据平台提供接口的主机地址
host: 127.0.0.1
# 接口的端口
port: 8080
# 读取超时
readTimeout: 35000
# 连接超时
connectTimeout: 5000
# 最大连接数
maxTotal: 500
# 同路由并发数100
maxPerRoute: 100
# 重连接次数
retryHandler: 3
# 连接不够用时的等待时间
connectionRequestTimeout: 20000
# 连接需要的认真码
authorizationCode: xxxxxxxxxxxxxxxxxxxx
配置类
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import static org.apache.http.conn.socket.PlainConnectionSocketFactory.*;
/**
* RestTemplate的配置类
*/
@Configuration
@ConditionalOnClass(ProxyConfig.class)
public class RestConfiguration {
Logger logger = LoggerFactory.getLogger(RestConfiguration.class);
@Autowired
private ProxyConfig proxyConfig;
@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
try {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
httpClientBuilder.setSSLContext(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
RegistryBuilder<ConnectionSocketFactory> connectionSocketFactoryRegistryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
connectionSocketFactoryRegistryBuilder.register("http", getSocketFactory());
connectionSocketFactoryRegistryBuilder.register("https", sslConnectionSocketFactory);
Registry<ConnectionSocketFactory> socketFactoryRegistry = connectionSocketFactoryRegistryBuilder.build();// 注册http和https请求
// 开始设置连接池
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolingHttpClientConnectionManager.setMaxTotal(proxyConfig.getMaxTotal());
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(proxyConfig.getMaxPerRoute());
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(proxyConfig.getRetryHandler(), true));
HttpClient httpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
clientHttpRequestFactory.setConnectTimeout(proxyConfig.getConnectTimeout());
clientHttpRequestFactory.setReadTimeout(proxyConfig.getReadTimeout());
clientHttpRequestFactory.setConnectionRequestTimeout(proxyConfig.getConnectionRequestTimeout());
return clientHttpRequestFactory;
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
logger.error("初始化HTTP连接池出错", e);
}
return null;
}
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(clientHttpRequestFactory());
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
//用拦截器的方式统一设置认证信息等公共参数
restTemplate.setInterceptors(Collections.singletonList(new ClientHttpRequestInterceptor(){
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
headers.add("Authorization", proxyConfig.getAuthorizationCode());
return execution.execute(request, body);
}
}));
return restTemplate;
}
}
前端调用我的接口,我调用别的服务接口,将结果返回给前端
@RestController
public class proxyController {
Logger logger = LoggerFactory.getLogger(proxyController.class);
@Autowired
private ProxyConfig proxyConfig;
@Autowired
private RestTemplate restTemplate;
/**
*以/proxy开头的url都会被拦截,然后用resttemplate统一调用别的服务接口并返回结果
*proxy后的路径以及传递的参数需要符合被调用的服务接口的样式
*/
@RequestMapping(value = "/proxy/**") //(value = "/proxy/**",method = {RequestMethod.GET,RequestMethod.POST,})
public Object proxy(@RequestBody Map parm, HttpServletRequest request) {
try {
String uri = request.getRequestURI();
String suffix = StringUtils.substringAfter(uri,"/proxy");
HttpMethod method = HttpMethod.valueOf(request.getMethod());
HttpEntity entity = new HttpEntity(parm);
//调用数据平台的url
String url = proxyConfig.getUrlPrefix() + suffix;
return restTemplate.exchange(url,method,entity,Map.class);
} catch (Exception e) {
logger.error("resttemplate中调用时出错", e);
return null;
}
}
}