REST访问(RestTemplate)

经常需要发送一个GET/POST请求到其他系统(REST API),通过JDK自带的HttpURLConnection、Apache HttpClient、Netty 4、OkHTTP 2/3都可以实现。

HttpClient的使用:http://rensanning.iteye.com/blog/1550436

Spring的RestTemplate封装了这些库的实现,使用起来更简洁。

RestTemplate包含以下几个部分:

HttpMessageConverter 对象转换器
ClientHttpRequestFactory 默认是JDK的HttpURLConnection
ResponseErrorHandler 异常处理
ClientHttpRequestInterceptor 请求拦截器

这里写图片描述

Java代码

    @Service  
    public class AccountService {  

        @Autowired  
        private RestTemplate restTemplate;  

        // ...  

    }  

(1)发送GET请求(getForObject()、getForEntity()、exchange())

Java代码

    // 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())

    // 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信息

    // 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);  

)异常处理

捕获HttpServerErrorException

    int retryCount = 0;  
    while (true) {  
        try {  
            responseEntity = restTemplate.exchange(requestEntity, String.class);  
            break;  
        } catch (HttpServerErrorException e) {  
            if (retryCount == 3) {  
                throw e;  
            }  
            retryCount++;  
        }  
    }  

自定义异常处理

    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;  
        }  

    }  

(5)设置超时时间

    @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)设置连接池

  @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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值