经常需要发送一个GET/POST请求到其他系统(REST API),通过JDK自带的HttpURLConnection、Apache HttpClient、Netty 4、OkHTTP 2/3都可以实现。
HttpClient的使用:[url=http://rensanning.iteye.com/blog/1550436]http://rensanning.iteye.com/blog/1550436[/url]
Spring的RestTemplate封装了这些库的实现,使用起来更简洁。
RestTemplate包含以下几个部分:
[list][*]HttpMessageConverter 对象转换器
[*]ClientHttpRequestFactory 默认是JDK的HttpURLConnection
[*]ResponseErrorHandler 异常处理
[*]ClientHttpRequestInterceptor 请求拦截器[/list]
[img]http://dl2.iteye.com/upload/attachment/0123/6851/cce612d5-bc90-3b56-a877-264cdc10df6b.png[/img]
[b](1)发送GET请求(getForObject()、getForEntity()、exchange())[/b]
[b](2)发送POST请求(postForObject()、postForEntity()、exchange())[/b]
[b](3)设置HTTP Header信息[/b]
[b](4)异常处理[/b]
[b]捕获HttpServerErrorException[/b]
[b]自定义异常处理[/b]
[b](5)设置超时时间[/b]
[b](6)设置连接池[/b]
[b](7)发送文件[/b]
[b](8)下载文件[/b]
[b](9)Spring Boot的RestTemplateBuilder[/b]
[b]全局设置[/b]
[b]单独设置[/b]
参考:
http://qiita.com/kazuki43zoo/items/7cf3c8ca4f6f2283cefb
http://terasolunaorg.github.io/guideline/5.1.0.RELEASE/ja/ArchitectureInDetail/RestClient.html
HttpClient的使用:[url=http://rensanning.iteye.com/blog/1550436]http://rensanning.iteye.com/blog/1550436[/url]
Spring的RestTemplate封装了这些库的实现,使用起来更简洁。
RestTemplate包含以下几个部分:
[list][*]HttpMessageConverter 对象转换器
[*]ClientHttpRequestFactory 默认是JDK的HttpURLConnection
[*]ResponseErrorHandler 异常处理
[*]ClientHttpRequestInterceptor 请求拦截器[/list]
[img]http://dl2.iteye.com/upload/attachment/0123/6851/cce612d5-bc90-3b56-a877-264cdc10df6b.png[/img]
@Service
public class AccountService {
@Autowired
private RestTemplate restTemplate;
// ...
}
[b](1)发送GET请求(getForObject()、getForEntity()、exchange())[/b]
// 1-getForObject()
User user1 = this.restTemplate.getForObject(uri, User.class);
// 2-getForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
HttpStatus statusCode = responseEntity1.getStatusCode();
HttpHeaders header = responseEntity1.getHeaders();
User user2 = responseEntity1.getBody();
// 3-exchange()
RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
User user3 = responseEntity2.getBody();
[b](2)发送POST请求(postForObject()、postForEntity()、exchange())[/b]
// 1-postForObject()
User user1 = this.restTemplate.postForObject(uri, user, User.class);
// 2-postForEntity()
ResponseEntity<User> responseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);
// 3-exchange()
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
[b](3)设置HTTP Header信息[/b]
// 1-Content-Type
RequestEntity<User> requestEntity = RequestEntity
.post(new URI(uri))
.contentType(MediaType.APPLICATION_JSON)
.body(user);
// 2-Accept
RequestEntity<User> requestEntity = RequestEntity
.post(new URI(uri))
.accept(MediaType.APPLICATION_JSON)
.body(user);
// 3-Other
RequestEntity<User> requestEntity = RequestEntity
.post(new URI(uri))
.header("Authorization", "Basic " + base64Credentials)
.body(user);
[b](4)异常处理[/b]
[b]捕获HttpServerErrorException[/b]
int retryCount = 0;
while (true) {
try {
responseEntity = restTemplate.exchange(requestEntity, String.class);
break;
} catch (HttpServerErrorException e) {
if (retryCount == 3) {
throw e;
}
retryCount++;
}
}
[b]自定义异常处理[/b]
public class CustomErrorHandler extends DefaultResponseErrorHandler {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
}
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomErrorHandler());
return restTemplate;
}
}
[b](5)设置超时时间[/b]
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(clientHttpRequestFactory());
}
private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(2000);
factory.setConnectTimeout(2000);
return factory;
}
}
[b](6)设置连接池[/b]
@Configuration
public class RestClientConfig {
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(5);
connectionManager.setDefaultMaxPerRoute(5);
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(8000)
.setConnectTimeout(8000)
.setConnectionRequestTimeout(8000)
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
[b](7)发送文件[/b]
MultiValueMap<String, Object> multiPartBody = new LinkedMultiValueMap<>();
multiPartBody.add("file", new ClassPathResource("/tmp/user.txt"));
RequestEntity<MultiValueMap<String, Object>> requestEntity = RequestEntity
.post(uri)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(multiPartBody);
[b](8)下载文件[/b]
// 小文件
RequestEntity requestEntity = RequestEntity.get(uri).build();
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, byte[].class);
byte[] downloadContent = responseEntity.getBody();
// 大文件
ResponseExtractor<ResponseEntity<File>> responseExtractor = new ResponseExtractor<ResponseEntity<File>>() {
@Override
public ResponseEntity<File> extractData(ClientHttpResponse response) throws IOException {
File rcvFile = File.createTempFile("rcvFile", "zip");
FileCopyUtils.copy(response.getBody(), new FileOutputStream(rcvFile));
return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(rcvFile);
}
};
File getFile = this.restTemplate.execute(targetUri, HttpMethod.GET, null, responseExtractor);
[b](9)Spring Boot的RestTemplateBuilder[/b]
[b]全局设置[/b]
@Component
public class CustomRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
new RestTemplateBuilder()
.detectRequestFactory(false)
.basicAuthorization("username", "password")
.uriTemplateHandler(new OkHttp3ClientHttpRequestFactory())
.errorHandler(new CustomResponseErrorHandler())
.configure(restTemplate);
}
}
[b]单独设置[/b]
@Service
public class MyRestClientService {
private RestTemplate restTemplate;
public MyRestClientService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder
.basicAuthorization("username", "password")
.setConnectTimeout(3000)
.setReadTimeout(5000)
.rootUri("http://api.example.com/")
.errorHandler(new CustomResponseErrorHandler())
.additionalMessageConverters(new CustomHttpMessageConverter())
.uriTemplateHandler(new OkHttp3ClientHttpRequestFactory())
.build();
}
public String site() {
return this.restTemplate.getForObject("http://rensanning.iteye.com/", String.class);
}
}
参考:
http://qiita.com/kazuki43zoo/items/7cf3c8ca4f6f2283cefb
http://terasolunaorg.github.io/guideline/5.1.0.RELEASE/ja/ArchitectureInDetail/RestClient.html