经常需要发送一个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())
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代码
- // 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代码
- int retryCount = 0;
- while (true) {
- try {
- responseEntity = restTemplate.exchange(requestEntity, String.class);
- break;
- } catch (HttpServerErrorException e) {
- if (retryCount == 3) {
- throw e;
- }
- retryCount++;
- }
- }
自定义异常处理
Java代码
- public class CustomErrorHandler extends DefaultResponseErrorHandler {
- @Override
- public void handleError(ClientHttpResponse response) throws IOException {
- }
- }
Java代码
- @Configuration
- public class RestClientConfig {
- @Bean
- public RestTemplate restTemplate() {
- RestTemplate restTemplate = new RestTemplate();
- restTemplate.setErrorHandler(new CustomErrorHandler());
- return restTemplate;
- }
- }
(5)设置超时时间
Java代码
- @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代码
- @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
大数据技术与运用的成熟,应用集中于互联网、金融、医疗、新能源、通信和房地产等行业。整理平均薪资情况和大数据学习大纲供查看
来源:oschina
链接:https://my.oschina.net/u/3377232/blog/2247743