简介
本文介绍RestTemplate的用法。RestTemplate是Spring自带的HTTP客户端,推荐使用。
项目中经常需要使用http调用第三方的服务,常用的客户端如下:
- HttpURLConnection(JDK的)
- HttpClient(Apache的)
- OkHttp(Square的)
上边这几个客户端用起来比较麻烦,代码量比较多,而且要注意资源回收问题。Spring提供了一个简单便捷的工具类,它就是RestTemplate。RestTemplate的底层默认是HttpURLConnection(JDK),可以切换为其他客户端,比如:HttpClient(Apache的)、OkHttp(Square的)。
引入依赖
只需引入spring-boot-starter-web即可,它里边包含了RestTemplate。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
配置类
法1:最简配置
@Configuration public class RestTemplateConfig { @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
这种初始化方法,是使用了JDK自带的HttpURLConnection作为底层HTTP客户端实现。
法2:自定义客户端及超时等
建议自定义配置,原因如下:
- 从性能及易用程度来看,OkHttp 优于 HttpClient、HttpClient优于HttpURLConnection。
- 超期时间,请求连接时间等是HTTP客户端必须要设置的,要支持配置。
RestTemplate工具提供两种配置方式。
- RestTemplate类
- 优点:可以便捷创建一些错误处理拦截、添加默认请求参数等。
- RestTemplateBuilder
- 优点:可以便捷设置连接超时和读超时
- Spring已默认将RestTemplateBuilder装配为了Bean,直接使用即可。
package com.knife.example.common.config; import okhttp3.OkHttpClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import java.time.Duration; @Configuration public class RestTemplateConfig { @Value("${custom.restTemplate.connectTimeout:1s}") private Duration connectTimeout; @Value("${custom.restTemplate.readTimeout:1s}") private Duration readTimeout; @Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){ RestTemplate restTemplate = restTemplateBuilder .requestFactory(this::getClientHttpRequestFactory) .setConnectTimeout(connectTimeout) .setReadTimeout(readTimeout) // 响应异常处理。应用场景:响应状态200是正常,可以做统一的非200响应码的拦截 // .errorHandler(ResponseErrorHandler errorHandler) // 设置请求拦截。应用场景:添加一些全局的请求头等。可创建多个,执行顺序和list中对象的顺序一致。 // .interceptors(List<ClientHttpRequestInterceptor> interceptors) // 设置信息转换对象。应用场景:设置一些编码格式、数据类型、json/xml等的类型转换器等。 // .messageConverters(List<HttpMessageConverter<?>> messageConverters) // 配置一个扩展uri模板的策略。应用场景:添加一些统一的请求前缀等。 // .uriTemplateHandler(UriTemplateHandler handler) .build(); return restTemplate; } /** * 使用OkHttpClient作为底层客户端(要引入okhttp依赖:com.squareup.okhttp3:okhttp:xxx) */ private ClientHttpRequestFactory getClientHttpRequestFactory(){ // 这里设置超时时间是无效的,以外边的restTemplateBuilder.setXxxTimeout为准 OkHttpClient okHttpClient = new OkHttpClient.Builder() // .connectTimeout(5, TimeUnit.SECONDS) // .readTimeout(5, TimeUnit.SECONDS) // .writeTimeout(5, TimeUnit.SECONDS) .build(); return new OkHttp3ClientHttpRequestFactory(okHttpClient); } // /** // * 使用HttpClient作为底层客户端(要引入httpclient依赖:org.apache.httpcomponents:httpclient:xxx) // */ // private ClientHttpRequestFactory getClientHttpRequestFactory() { // //这里设置超时时间是无效的,以外边的restTemplateBuilder.setXxxTimeout为准 // RequestConfig config = RequestConfig.custom() // // 单位都是:毫秒 // .setConnectTimeout(2000) // .setConnectionRequestTimeout(1000) // .setSocketTimeout(1000) // .build(); // CloseableHttpClient client = HttpClientBuilder // .create() // .setDefaultRequestConfig(config) // .build(); // // return new HttpComponentsClientHttpRequestFactory(client); // } }
使用
注入RestTemplate即可。
例1:基础用法
package com.knife.controller; import com.knife.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class HelloController { @Autowired private RestTemplate restTemplate; @GetMapping("testGetForObject") public User testGetForObject(String id) { User user = restTemplate.getForObject("http://localhost/get/{id}", User.class, id); System.out.println(user); return user; } @GetMapping("testGetForEntity") public User getForEntity(String id) { ResponseEntity<User> userResponseEntity = restTemplate.getForEntity( "http://localhost/get/{id}", User.class, id); User user = userResponseEntity.getBody(); System.out.println(user); return user; } }
例2:自定义Header、请求方法等
package com.knife.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; @RestController public class HelloController { @Autowired private RestTemplate restTemplate; @PostMapping("testExecute") public void testExecute(Integer id, String name) { HttpHeaders headers = new HttpHeaders(); headers.add("authorization", "aaabbb"); headers.setContentType(MediaType.APPLICATION_JSON); Map<String, Object> body = new HashMap<>(); body.put("userId", id); body.put("name", name); HttpEntity<Map> httpEntity = new HttpEntity<>(body, headers); // 组装 ResponseEntity<User> user = restTemplate.exchange( "http://localhost:8080/demo", HttpMethod.POST, httpEntity, User.class); } }
用法大全
- delete()
- 在特定的URL上对资源执行HTTP DELETE操作
- exchange()
- 通用的方法。在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的。
- execute()
- 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象。这是个偏底层的方法,其他方法是基于此方法的,不建议用户直接使用。
- getForEntity()
- 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
- getForObject()
- 发送一个HTTP GET请求,返回的响应体将映射为一个对象
- postForEntity()
- 发送一个HTTP POST请求,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
- postForObject()
- 发送一个HTTP POST请求,返回根据响应体匹配形成的对象
- headForHeaders()
- 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
- optionsForAllow()
- 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
- postForLocation()
- 发送HTTP POST请求,返回新创建资源的URL
- put()
- 发送HTTP PUT请求
请先
!