SpringBoot系列 - 使用RestTemplate
2018-05-18 10:07
531 查看
版权声明:© 2018 - 2018 Jean.All Rights Reserved. https://blog.csdn.net/xingxuan4547/article/details/80359867
简介
spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP框架。
本篇介绍如何使用RestTemplate,以及在SpringBoot
实现逻辑
RestTemplate包含以下几个部分:
- HttpMessageConverter 对象转换器
- ClientHttpRequestFactory 默认是JDK的HttpURLConnection
- ResponseErrorHandler 异常处理
- ClientHttpRequestInterceptor 请求拦截器
用一张图可以很直观的理解:
直接使用方式很简单:
public class RestTemplateTest { public static void main(String[] args) { RestTemplate restT = new RestTemplate(); //通过Jackson JSON processing library直接将返回值绑定到对象 Quote quote = restT.getForObject("http://gturnquist-quoters.cfapps.io/api/random", Quote.class); String quoteString = restT.getForObject("http://gturnquist-quoters.cfapps.io/api/random", String.class); System.out.println(quoteString); } }
发送GET请求
// 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();
发送POST请求
// 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);
设置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
try { responseEntity = restTemplate.exchange(requestEntity, String.class); } catch (HttpServerErrorException e) { // log error }
自定义异常处理器
public class CustomErrorHandler extends DefaultResponseErrorHandler { @Override public void handleError(ClientHttpResponse response) throws IOException { // todo } }
然后设置下异常处理器
@Configuration public class RestClientConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new CustomErrorHandler()); return restTemplate; } }
配置类
创建RestClientConfig类,设置连接池大小、超时时间、重试机制等。配置如下:
@Configuration public class RestClientConfig { private static final Logger log = LoggerFactory.getLogger(RestClientConfig.class); @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setRequestFactory(clientHttpRequestFactory()); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); // 使用UTF-8编码集的conver替换默认的conver(默认的stringConver的编码集为"ISO-8859-1"),解决响应体乱码问题 List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator(); while (iterator.hasNext()) { HttpMessageConverter<?> converter = iterator.next(); if (converter instanceof StringHttpMessageConverter) { iterator.remove(); } } messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); //解决微信返回text/plain的解析 //messageConverters.add(new WxMappingJackson2HttpMessageConverter()); return restTemplate; } @Bean public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() { try { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { return true; } }).build(); httpClientBuilder.setSSLContext(sslContext); HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslConnectionSocketFactory).build();// 注册http和https请求 //使用Httpclient连接池的方式配置(推荐),同时支持netty,okHttp以及其他http框架 PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); poolingHttpClientConnectionManager.setMaxTotal(100); // 最大连接数500 poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); // 同路由并发数100 httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); // 重试次数 //设置默认请求头 //List<Header> headers = new ArrayList<>(); //headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36")); //headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate")); //headers.add(new BasicHeader("Accept-Language", "zh-CN")); //headers.add(new BasicHeader("Connection", "Keep-Alive")); //httpClientBuilder.setDefaultHeaders(headers); HttpClient httpClient = httpClientBuilder.build(); HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // httpClient连接配置 clientHttpRequestFactory.setConnectTimeout(20000); // 连接超时 clientHttpRequestFactory.setReadTimeout(10000); // 数据读取超时时间,即SocketTimeout clientHttpRequestFactory.setConnectionRequestTimeout(200); // 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的 return clientHttpRequestFactory; } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { log.error("初始化HTTP连接池出错", e); } return null; } }
注意,如果没有apache的HttpClient类,需要在项目构造工具配置文件中添加:
- pom.xml
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency>
- build.gradle
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3'
发送文件
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);
下载文件
// 小文件 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);
Service注入
@Service public class DeviceService { private static final Logger logger = LoggerFactory.getLogger(DeviceService.class); @Autowired private RestTemplate restTemplate; }
实际使用例子
@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ApplicationTests { private static final Logger logger = LoggerFactory.getLogger(ApplicationTests.class); /** @LocalServerPort 提供了 @Value("${local.server.port}") 的代替*/ @LocalServerPort private int port; @Autowired private RestTemplate restTemplate; @Test public void testRestTemplate() { logger.info("解绑成功后推送消息给对应的POS机"); LoginParam param = new LoginParam(); param.setUsername("admin"); param.setPassword("12345678"); String loginUrl = String.format("http://localhost:%d/login", port); BaseResponse r = restTemplate.postForObject(loginUrl, param, BaseResponse.class); assertThat(r.isSuccess(), is(true)); logger.info("推送消息登录认证成功"); String token = (String) r.getData(); UnbindParam unbindParam = new UnbindParam(); unbindParam.setImei("imei"); unbindParam.setLocation("location"); // 设置HTTP Header信息 String unbindUrl = String.format("http://localhost:%d/unbind", port); URI uri; try { uri = new URI(unbindUrl); } catch (URISyntaxException e) { logger.error("URI构建失败", e); throw new RuntimeException("URI构建失败"); } RequestEntity<UnbindParam> requestEntity = RequestEntity .post(uri) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .header("Authorization", token) .body(unbindParam); ResponseEntity<BaseResponse> responseEntity = restTemplate.exchange(requestEntity, BaseResponse.class); BaseResponse r2 = responseEntity.getBody(); assertThat(r2.isSuccess(), is(true)); assertThat(r2.getData(), is("unbind")); } }
相关文章推荐
- SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别)
- springboot使用restTemplate post提交值 restTemplate post值
- SpringBoot 使用RestTemplate实现调用服务
- springboot-24-restTemplate的使用
- Spring boot 发送http请求组件RestTemplate使用实例
- Spring Boot中RestTemplate的使用
- Spring Boot使用RestTemplate消费REST服务的几个问题记录
- springboot-1-restTemplate的使用
- spring boot / cloud (八) 使用RestTemplate来构建远程调用服务
- springboot中配置restTemplate及简单使用
- Spring-boot RestTemplate 使用 报错问题
- spring boot / cloud (八) 使用RestTemplate来构建远程调用服务
- 在spring boot中使用restTemplate上传大文件Java heap space
- spring boot RestTemplate 发送 get 请求使用误区
- 使用RestTemplate消费spring boot的Restful服务
- springboot restTemplate使用以及相关配置
- SpringBoot系列(一)RestTemplate
- spring boot RestTemplate 发送 get 请求
- springboot RestTemplate 注入
- 使用 Spring RestTemplate 调用 rest 服务时自定义请求头(custom HTTP headers)