配置
定义bean方式一
@Configuration
public class SpringConfig {
@Bean
public RestTemplate getRestTemplate() {
System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "8888");
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
int mseconds = Integer.valueOf(8000);
httpRequestFactory.setConnectionRequestTimeout(mseconds);
httpRequestFactory.setConnectTimeout(mseconds);
httpRequestFactory.setReadTimeout(mseconds);
return new RestTemplate(httpRequestFactory);
}
}
定义bean方式二
@Configuration
public class SpringConfig {
@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory() {{
setProxy(new java.net.Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)));
}});
return restTemplate;
}
}
说明:设置代理8888是为了fiddler抓包。
参见:
https://www.okcode.net/article/47473
那么我们第一种和第二种定义有什么区别尼?
ClientHttpRequestFactory接口主要提供了两种实现方式
- 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接HttpURLConnection,默认使用此方式。
- 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。
参见:
https://stackoverflow.com/questions/25698072/simpleclienthttprequestfactory-vs-httpcomponentsclienthttprequestfactory-for-htt
https://juejin.im/entry/5b21c6d55188257d9b79e1e8
By default RestTemplate uses
SimpleClientHttpRequestFactory
which depends on default configuration ofHttpURLConnection
.
If you want to use HttpComponentsClientHttpRequestFactory - it has a connection pooling configuration which SimpleClientHttpRequestFactory does not have.
model定义
@Data
public class AuthInfo implements Serializable {
private String CSPID;
private String UserID;
private String ContentID;
private String ProductID;
private String ServiceID;
private String Token;
}
调用
public String auth(AuthInfo authInfo) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//如果对方返回类型不为json,不加这句话,会报404错误。
headers.set("Accept","*/*");
HttpEntity<AuthInfo> entity = new HttpEntity<AuthInfo>(authInfo, headers);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(authUrl, entity, String.class);
String result = responseEntity.getBody();
System.out.println(result);
return result;
}
坑1:对方返回类型为Content-Type: text/html; charset=UTF-8,如果accept类型不匹配,会报404,故,需要增加headers.set("Accept","/");
坑2:参数要求首字母大写。如定义。
要求格式:
{
"CSPID": 2316,
"ContentID": "asdf",
"ProductID": "asfs",
"UserID": "sdfs",
"Token": "sfss",
"ServiceID":"20171902141"
}
我们序列化的格式
{
"cspid": 2316,
"contentID": "asdf",
"productID": "asfs",
"userID": "sdfs",
"token": "sfss",
"serviceID":"20171902141"
}
如何处理参数大写问题?
首先我们需要确认,restTemplate使用的什么序列化json.
消息转换核心代码
//getMessageConverters()获取消息转换 的方法
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter instanceof GenericHttpMessageConverter) {
GenericHttpMessageConverter<Object> genericMessageConverter = (GenericHttpMessageConverter<Object>) messageConverter;
if (genericMessageConverter.canWrite(requestBodyType, requestBodyClass, requestContentType)) {
.......
genericMessageConverter.write(
requestBody, requestBodyType, requestContentType, httpRequest);
return;
}
}
else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
.....
}
}
//messageConverters包含的转换器
public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters;
}
//messageConverters初始化
public RestTemplate() {
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
}
else if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
this.messageConverters.add(new GsonHttpMessageConverter());
}
}
//加载jackson2Present 的条件
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
RestTemplate.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
RestTemplate.class.getClassLoader());
//成功加载,即为成功。
public static boolean isPresent(String className, ClassLoader classLoader) {
try {
forName(className, classLoader);
return true;
}
catch (Throwable ex) {
// Class or one of its dependencies is not present...
return false;
}
}
以下是messageConverters运行时 包含的对象.
image.png我们可以看到,消息转换器默认使用的是jackson2。
所以我们需要使用@JsonProperty
参见:
https://blog.csdn.net/qingguiyu/article/details/79215448
使用后和@Data使用,发现会生成多份数据。需要移除@Data,将@JsonProperty放到get方法上。
参见:
https://blog.csdn.net/weixin_41450959/article/details/87691788
其他一些技巧:
https://www.cnblogs.com/soul-wonder/p/8890728.html
连接池信息
https://juejin.im/post/5d2c72cde51d4555fd20a3f6
网友评论