话不多说
场景就是 我调用外部需要鉴权的接口, 需要按照对方的格式写参数。呜呜呜
官网 说这个东西 5.0后 处于维护阶段。
大概下面这个意思
As of 5.0 the RestTemplate is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the WebClient which offers a more modern API and supports sync, async, and streaming scenarios.
先直接贴配置
@Configuration
public class RestTemplateConfig {
private static final Logger logger= LoggerFactory.getLogger(RestTemplateConfig.class);
@Bean
public RestTemplate restTemplate() {
// 添加内容转换器,使用默认的内容转换器
RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
// 设置编码格式为UTF-8
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
HttpMessageConverter<?> converterTarget = null;
for (HttpMessageConverter<?> item : converterList) {
if (item.getClass() == StringHttpMessageConverter.class) {
converterTarget = item;
break;
}
}
if (converterTarget != null) {
converterList.remove(converterTarget);
}
HttpMessageConverter<?> converter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
converterList.add(1,converter);
// 为啥加这个。 理解了 mvc 的消息转换器可以🈶️多个。
// 坑1
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_HTML));
restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
logger.info("-----restTemplate-----初始化完成");
return restTemplate;
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public HttpClient httpClient() {
// 长连接保持30秒
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
//设置整个连接池最大连接数 根据自己的场景决定
connectionManager.setMaxTotal(100);
//同路由的并发数,路由是对maxTotal的细分
connectionManager.setDefaultMaxPerRoute(100);
//requestConfig
RequestConfig requestConfig = RequestConfig.custom()
//服务器返回数据(response)的时间,超过该时间抛出read timeout
.setSocketTimeout(3000)
//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
.setConnectTimeout(2000)
//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(500)
.build();
//headers
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN"));
headers.add(new BasicHeader("Connection", "Keep-Alive"));
headers.add(new BasicHeader("Content-type", "application/json;charset=UTF-8"));
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.setDefaultHeaders(headers)
// 保持长连接配置,需要在头添加Keep-Alive
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy())
//重试次数,默认是3次,没有开启
.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
.build();
}
}
坑1 为啥 我返回的字符串转不了对象。
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class [xx.xx.xx.Employee;] and content type [text/html] ...
他喵的 返回报文媒体格式 竟然 text/html ,我转了几个小时 也没有转处理 气死我了。 多谢下面的博客
思路大概就是让你支持 这个转换器就好了。
参考
https://www.technicalkeeda.com/spring-tutorials/could-not-extract-response-no-suitable-httpmessageconverter-found-for-response-type
坑2 RestTemplate 传递 form 表单 的参数
得 自己设置头 和参数格式
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map= new LinkedMultiValueMap<String, String>();
map.add("xxxx", "f哈哈哈");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
贴下我的代码
GtwShippingRequest shippingRequest = new GtwShippingRequest();
shippingRequest.setBillNo("1");
shippingRequest.setTrafName("1");
shippingRequest.setVoyage("1");
shippingRequest.setIeFlag("E");
shippingRequest.setRegion("sh");
Gson gson = new Gson();
String content = gson.toJson(shippingRequest);
String timestamp = String.valueOf(System.currentTimeMillis());
String sign = getSign(bizCode92, bizId, content, timestamp, appKey);
MultiValueMap<String, String> parameters= new LinkedMultiValueMap<String, String>();
parameters.add("appId", appId);
parameters.add("bizCode", bizCode92);
parameters.add("bizId", bizId);
parameters.add("content", content);
parameters.add("timestamp", timestamp);
parameters.add("sign", sign);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(parameters,headers);
ParameterizedTypeReference<GtwResponse<GtwShippingInfo>> ptr = new ParameterizedTypeReference<GtwResponse<GtwShippingInfo>>(){};
try {
ResponseEntity<GtwResponse<GtwShippingInfo>> response = restTemplate.exchange(url, HttpMethod.POST, request, ptr);
System.out.println(response.getBody());
} catch ( Exception e) {
e.printStackTrace();
}