常常須要發送一個GET/POST請求到其餘系統(REST API),經過JDK自帶的HttpURLConnection、Apache HttpClient、Netty 四、OkHTTP 2/3均可以實現。
HttpClient的使用:http://rensanning.iteye.com/blog/1550436
Spring的RestTemplate封裝了這些庫的實現,使用起來更簡潔。
RestTemplate包含如下幾個部分: javascript
- HttpMessageConverter 對象轉換器
- ClientHttpRequestFactory 默認是JDK的HttpURLConnection
- ResponseErrorHandler 異常處理
- ClientHttpRequestInterceptor 請求攔截器
Java代碼 php
- @Service
- public class AccountService {
-
- @Autowired
- private RestTemplate restTemplate;
-
- // ...
-
- }
(1)發送GET請求(getForObject()、getForEntity()、exchange())
Java代碼 html
- // 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();
(2)發送POST請求(postForObject()、postForEntity()、exchange())
Java代碼 java
- // 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);
(3)設置HTTP Header信息
Java代碼 git
- // 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);
(4)異常處理
捕獲HttpServerErrorException
Java代碼 github
- int retryCount = 0;
- while (true) {
- try {
- responseEntity = restTemplate.exchange(requestEntity, String.class);
- break;
- } catch (HttpServerErrorException e) {
- if (retryCount == 3) {
- throw e;
- }
- retryCount++;
- }
- }
自定義異常處理
Java代碼 api
- public class CustomErrorHandler extends DefaultResponseErrorHandler {
-
- @Override
- public void handleError(ClientHttpResponse response) throws IOException {
-
- }
-
- }
Java代碼 app
- @Configuration
- public class RestClientConfig {
-
- @Bean
- public RestTemplate restTemplate() {
- RestTemplate restTemplate = new RestTemplate();
- restTemplate.setErrorHandler(new CustomErrorHandler());
- return restTemplate;
- }
-
- }
(5)設置超時時間
Java代碼 ide
- @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;
- }
- }
(6)設置鏈接池
Java代碼 post
- @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();
- }
-
- }
(7)發送文件
Java代碼
- 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);
(8)下載文件
Java代碼
- // 小文件
- 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);
(9)Spring Boot的RestTemplateBuilder
全局設置
Java代碼
- @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);
- }
- }
單獨設置
Java代碼
- @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
程序猿必關注這個技術,風頭正勁,僅4個月薪酬35K+
大數據技術與運用的成熟,應用集中於互聯網、金融、醫療、新能源、通訊和房地產等行業。整理平均薪資狀況和大數據學習大綱供查看