本文的目的是介绍SpringRestTemplate详解的详细情况,特别关注spring的resttemplate的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Sp
本文的目的是介绍Spring RestTemplate详解的详细情况,特别关注spring的resttemplate的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Spring RestTemplate详解的机会,同时也不会遗漏关于RestTemplate详解、Spring boot 之 RestTemplate、Spring Boot 的 TestRestTemplate 使用、Spring Boot的TestRestTemplate使用的知识。
本文目录一览:- Spring RestTemplate详解(spring的resttemplate)
- RestTemplate详解
- Spring boot 之 RestTemplate
- Spring Boot 的 TestRestTemplate 使用
- Spring Boot的TestRestTemplate使用
Spring RestTemplate详解(spring的resttemplate)
-
1、什么是REST?
REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格的名词。REST定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的Web 服务,包括使用不同语言编写的客户端如何通过 HTTP处理和传输资源状态。
为什么称为 REST?Web本质上由各种各样的资源组成,资源由URI 唯一标识。浏览器(或者任何其它类似于浏览器的应用程序)将展示出该资源的一种表现方式,或者一种表现状态。如果用户在该页面中定向到指向其它资源的链接,则将访问该资源,并表现出它的状态。这意味着客户端应用程序随着每个资源表现状态的不同而发生状态转移,也即所谓REST。
附:REST定义、REST与SOAP的比较
2、REST成熟度的四个层次
第一个层次(Level0)的Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形 式。SOAP和 XML-RPC都属于此类。
第二个层次(Level1)的Web 服务引入了资源的概念。每个资源有对应的标识符和表达。
第三个层次(Level2)的Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用HTTP 状态码来表示不同的结果。如 HTTPGET 方法来获取资源,HTTPDELETE 方法来删除资源。
第四个层次(Level3)的Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。
其中第三个层次建立了创建、读取、更新和删除(create,read, update, and delete,CRUD)操作与 HTTP方法之间的一对一映射。根据此映射:
(1)若要在服务器上创建资源,应该使用POST 方法。
(2)若要检索某个资源,应该使用GET 方法。
(3)若要更改资源状态或对其进行更新,应该使用PUT 方法。
(4)若要删除某个资源,应该使用DELETE 方法。
3、HTTP请求的方法
(1)GET:通过请求URI得到资源
(2)POST:用于添加新的内容
(3)PUT:用于修改某个内容,若不存在则添加
(4)DELETE:删除某个内容
(5)OPTIONS :询问可以执行哪些方法
(6)HEAD :类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据
(7)CONNECT :用于代理进行传输,如使用SSL
(8)TRACE:用于远程诊断服务器4、HTTP请求的状态码
(1)成功Successful2xx:此类状态码标识客户端的请求被成功接收、理解并接受。常见如200(OK)、204(NoContent)。
(2)重定向Redirection3xx:这个类别的状态码标识用户代理要做出进一步的动作来完成请求。常见如301(MovedPermanently)、302(MovedTemprarily)。
(3)客户端错误Client Error 4xx:4xx类别的状态码是当客户端象是出错的时使用的。常见如400(BadRequest)、401(Unauthorized)、403(Forbidden)、404(NotFound)。
(4)服务器错误Server Error 5xx:响应状态码以5开头表示服务器知道自己出错或者没有能力执行请求。常见如500(InternalServer Error)、502(BadGateway)、504(GatewayTimeout)。附HTTP1.1的标准简介:http://blog.chinaunix.net/uid-9188830-id-2007021.html
5、RestTemplate
5.1 简介
Spring''scentral class for synchronous client-side HTTP access.It simplifies communication with HTTPservers, and enforces RESTful principles. Ithandles HTTP connections, leaving application code to provide URLs(with possible template variables) andextract results.
简单说就是:简化了发起HTTP请求以及处理响应的过程,并且支持REST。为什么说简化了呢?
来看两种实现方式
(1)使用java.net包下的URLConnection建立连接
[java] view plain copy- String result= "";
- BufferedReaderin = null;
- try {
- String urlNameString= url +"?" + param;
- URL realUrl= new URL(urlNameString);
- // 打开和URL之间的连接
- URLConnectionconnection = realUrl.openConnection();
- // 设置通用的请求属性
- connection.setRequestProperty("accept","*/*");
- connection.setRequestProperty("connection","Keep-Alive");
- connection.setRequestProperty("user-agent",
- "Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1;SV1)");
- // 建立实际的连接
- connection.connect();
- // 获取所有响应头字段
- Map<String,List<String>> map = connection.getHeaderFields();
- // 遍历所有的响应头字段
- for(String key : map.keySet()) {
- System.out.println(key+ "--->" + map.get(key));
- }
- // 定义 BufferedReader输入流来读取URL的响应
- in =new BufferedReader(newInputStreamReader(
- connection.getInputStream()));
- String line;
- while ((line = in.readLine())!= null) {
- result += line;
- }
- } catch (Exception e) {
- …
- }
- // 使用finally块来关闭输入流
- finally{
- // 关闭流
- }
(2)使用RestTempalte
[java] view plain copy- ResponseEntity<SsoUrlPrm>result = restTemplate.getForEntity(requestPathUrl,SsoUrlPrm.class);
5.2 对外开放的接口
(1)
DELETE delete GET getForObject getForEntity HEAD headForHeaders OPTIONS optionsForAllow POST postForLocation postForObject PUT put any exchange execute (2)每一个小类又分三种,这三种有什么区别?
* 第一种和第二种的首个参数都是用String表示一个URI。但它们的最后一个参数分别是Object[]和Map* 第三种的首个参数使用java.net.URI表示一个URI。且只有两个参数
这是因为,String类型的URI支持占位符。比如:
restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",String.class,"42", "21");
那么最终访问的URI为:http://example.com/hotels/42/bookings/21
但是String有一个小缺陷:String形式的URI会被URL编码两次(URL encode请自行百度),这就要求服务器在获取URI中的参数时主动进行一次解码,但如果服务的提供者不这么做呢?
这时就需要使用不会使用任何编码的java.net.URI
PS:参数‘Class<T> responseType’定义了返回数据的类型。
(3)Exchange
与其它接口的不同:>允许调用者指定HTTP请求的方法(GET,POST,PUT等)
>可以在请求中增加body以及头信息,其内容通过参数‘HttpEntity<?>requestEntity’描述
>exchange支持‘含参数的类型’(即泛型类)作为返回类型,该特性通过‘ParameterizedTypeReference<T>responseType’描述。比如:
[java] view plain copy- List<String> a = new ArrayList<String>();
- System.out.println(a.getClass());
- System.out.println(a.getClass().getGenericSuperclass());
- ParameterizedTypeReference pt = new ParameterizedTypeReference<ArrayList<String>>() {};
- System.out.println(pt.getType());
[java] view plain copy- class java.util.ArrayList
- java.util.AbstractList<E>
- java.util.ArrayList<java.lang.String>
* 这是因为ParameterizedTypeReference<ArrayList<String>>并不根据实参而是使用getGenericSuperclass()方法获取其父类的类型(注意这里的new有花括号,是ParameterizedTypeReference的子类),父类的类型通过java.lang.reflect.Type描述,然后通过Type的getActualTypeArguments()获得了父类的实参类型,注意得到的Type类,并不是class类。
(4)excute
所有的get、post、delete、put、options、head、exchange方法最终调用的都是excute方法。举个栗子:
[java] view plain copy- @Override
- public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
- RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
- HttpMessageConverterExtractor<T> responseExtractor =
- <span style="white-space:pre"> </span>new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
- return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
- }
Excute方法只是将String格式的URI转成了java.net.URI,之后调用了doExecute方法。整个调用过程
6.doExcute
6.1 定义[java] view plain copy- protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,ResponseExtractor<T> responseExtractor) throws RestClientException {…}
6.2 RequestCallback
Callback interface for code that operates on a ClientHttpRequest. Allows to manipulate the request headers, and write to the request body.
简单说:用于操作请求头和body,在请求发出前执行。
该接口有两个实现类:AcceptHeaderRequestCallback 只处理请求头,用于getXXX()方法。 HttpEntityRequestCallback 继承于AcceptHeaderRequestCallback可以处理请求头和body,用于putXXX()、postXXX()和exchange()方法。
* DELETE、HEAD、OPTIONS没有使用这个接口。6.3 发起请求6.4 ResponseExtractor6.4.1 定义Generic callback interface used by RestTemplate''s retrieval methods Implementations of this interface perform the actual work of extracting data from a ClientHttpResponse, but don''t need to worry about exception handling or closing resources.
简单说:解析HTTP响应的数据,而且不需要担心异常和资源的关闭。该接口有三个实现类:HeadersExtractor 用于提取请求头。 HttpMessageConverterExtractor 用于提取响应body。 ResponseEntityResponseExtractor 使用HttpMessageConverterExtractor提取body(委托模式),然后将body和响应头、状态封装成ResponseEntity对象。 6.4.2 提取响应body提取分三步:
(1)提取器HttpMessageConverterExtractor寻找可用的转化器在默认的RestTemplate的构造函数中初始化了转化器集合,包括:转化器
可转化的类型 ByteArrayHttpMessageConverter byte[] StringHttpMessageConverter String ResourceHttpMessageConverter Resource SourceHttpMessageConverter javax.xml.transform.* AllEncompassingFormHttpMessageConverter MultiValueMap Jaxb2RootElementHttpMessageConverter XmlRootElement,XmlType(注解) ... MappingJackson2HttpMessageConverter Json
提取器遍历转化器集合以查找可用的转化器,其中MappingJackson2HttpMessageConverter总是在最后一个,因为该类实现了GenericHttpMessageConverter,算是一个通用转化器,只有在找不到合适的转化器时才轮到它。Spring提供了一个该类的实现,以保证总是能得到该类。
(2)转化器寻找可用的反序列化器转化器持有一个反序列化器缓存集合,首先从缓存中寻找
如果已有可用的反序列化器,则直接返回。否则创建一个新的反序列化器。反序列化器保存着待反序列化类的域、方法、构造器等信息,反序列化时就是使用构造器创建了一个新的实例。以jackson为例,创建反序列化器的过程在jackson-databind-xxx.jar中,有兴趣的可以看一下。调用栈如下(由下往上找):BeanDeserializerFactory.addBeanProps/addObjectIdReader/addReferenceProperties/addInjectables
BeanDeserializerFactory.buildBeanDeserializer
BeanDeserializerFactory.createBeanDeserializer
(3)反序列化器执行反序列化TOKEN
Json的一个或一组字符 START_OBJECT { END_OBJECT } START_ARRAY [ END_ARRAY ] VALUE_TRUE true VALUE_FALSE false ... 调用栈:
版权声明:本文为博主原创文章,未经博主允许不得转载。
RestTemplate详解
RestTemplate详解 -Get请求 在RestTemplate中通过如下两个方法进行调用 --第一种:getForEntity()函数 返回:ResponseEntity(对HTTP响应的封装,重要元素:HTTP请求状态的枚举对象HttpStatus, HTTP请求头信息对象HttpHeaders,泛型的请求体对象) 例如: RestTemplate restTemplate = new RestTemplate(); ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://USER-SERVICE /user?name={1}", String.class, "didi"); String body = responseEntity.getBody(); 解析:该请求是访问USER-SERVICE服务的/user请求,同时最后一个请求参数"didi"会替换url中的{1}的占位符,而返回的 ResponseEntity对象中的body内容会根据第二个参数转换成String类型 例如: RestTemplate restTemplate = new RestTemplate(); ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://SERVICE- USER/user?name={1}", User.class, "didi"); User body = responseEntity.getBidy(); 解析:该请求访问USER-SERVICE服务的/user请求,同时最后一个请求参数"didi"会替换url中的{1}的占位符,而返回的 ResponseEntity对象中的body内容会根据第二个参数转换成User类型 三个重载方法: getForEntity(String url, Class<T> responseType, Object... uriVariables) 解析: url为请求地址,responseType为请求响应体body的包装类型,uriVariables为url中的参数绑定 注意:uriVariables是一个数组,所以他的顺序会对应url中占位符定义的数字的顺序 getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) 解析:这里只有uriVariables这个参数不同,这里使用了Map类型, 注意:使用该方法进行参数绑定时需要在占位符中指定Map的key 例如: RestTemplate restTemplate = new RestTemplate(); Map<String, String> params = new HashMap<>(); params.put("name","dada"); ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://SERVICE- USER/user?name={name}", String.class, params); getForEntity(URI url, Class<T> responseType) 解析:该方法使用URI替换之前的url和urlVariables参数来指定访问地址和参数绑定。 例如: RestTemplate restTemplate = new RestTemplate(); UriComponents uriComponenets = UriComponentsBuilder.formUriString{ "http://USER-SERVICE/user?name={name}" .build() .expand("dodo") .encode(); } URI uri = UriComponents.toUri(); ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class).getBody(); --第二种:getForObject()函数 解析:它可以理解为getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP请求响应体body内容进行 对象转换,实现请求直接返回包装好的对象内容 例如: RestTemplate restTemplate = new RestTemplate(); String result = restTemplate.getForObject(uri, String.class); 当body是一个User对象的时候,可以直接这样实现 RestTemplate restsTemplate = new RestTempalte(); User user = restTemplate.getForObject(uri, User.class); 使用场景:当不需要关注请求响应除body外的其他内容时,该函数就非常好用,可以少一个从Response中获取body的步骤。 三个重载方法: 1.getForObject(String url, Class<T> responseType, Object... uriVariables) 解析:url指定访问的地址,responseType指定访问的地址,urlVariables为url中占位符对应的参数 2.getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) 解析:该函数使用Map类型的urlVariables替代上面数组形式的urlVariables,因此使用时在url中需要将占位符的 名称与Map类型中的Key一一对应设置 3.getForObject(URI url, Class<T> responseType) 解析:该方法使用URI对象来替换之前的url和urlVariabels参数使用 -Post请求 在RestTempalte中,对POST请求时可以通过如下三个方法进行调用 --第一种:postForEntity()函数 解析:该方法与Get请求中的getForEntity()函数类似,返回ResponseEntity<T>对象,其中T为请求响应的body类型。 例如: RestTemplate restTemplate = new RestTempalte(); User user = new User("didi", 30); ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://USER-SERVICE/user", user, String); String body = responseEntity.getBody(); 三个重载方法: 1.postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables) 2.postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) 3.postForEntity(URI url, Object request, Class<T> responseType) 解析:重载函数中的uriVariables用来对url中的参数进行绑定,responseType参数是对请求响应的body内容的类型定 义 注意:新增的request参数,改参数可以是一个普通的对象,也可以是一个HttpEntity对象。 如果request是一个普通对象时,RestTemplate会将这个普通对象转换成HttpEntity对象来处理,其中Object就是 request的类型,request内容会被当成一个完整的body来处理; 如果resuqet是一个HttpEntity对象时,那么request会被当成一个完整的HTTP请求对象来处理,这个request中不 仅包含了body内容,也包含了header的内容 --第二种:postForObject()函数 解析:它简化了postForEntity()的后续处理,通过直接将请求响应的body内容包装陈对象来简化返回使用。 例如: RestTemplate restTemplate = new RestTemplate(); User user = new User("didi", 20); String postResult = restTemplate.postForObject("http[://USER-SERVICE/user", user, String.class); 三个重载方法: postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) postForObject(URI url, Object request, Class<T> responseType) 解析:参考postForEntity说明 --第三种:postForLocation()函数 解析:该函数实现了以post请求提交资源,并放回新资源的URI 例如: User user = new User("didi", 40); URI responseUri = restTemplate.postForLocation("http://USER-SERVICE/user", user); 三个重载方法: postForLocation(String url, Object request, Object... uriVariables) postForLocation(String url, Object request, Map<String, ?> uriVariables) postForLocation(URI url, Object request) 解析:由于postForLocation函数会返回新资源的URI,该URI就相当于指定了放回类型,所以此方法实现的post请求不需 要像postforEntity和postForObject一样执行responseType。 其他参数用法相同 -Put请求 在RestTemplate中,对PUT请求可以通过put方法进行调用实现 例如: RestTemplate restTemplate = new RestTemplate(); Long id = 100L; User user = new User("didi", 40); restTemplate.put("http://USER-SERVICE/user/{1}", user, id); 解析:put函数返回类型为void类型,所以没有返回内容,也就没有其他函数定义的responseType参数,除此之外的其他传入参数定义和 用法与postForObject基本一致。 -Delete请求 在RestTemplate中,对DELETE请求可以通过delete方法进行调用实现 例如: RestTemplate restTemplate = new RestTemplate(); Long id = 100L; restTemplate.delete("http://USER-SERVICE/user/{1}",id); 三个重载方法: delete(String url, Object... urlVariables) delete(String url, Map urlVariables) delete(URI uri) 解析:由于我们在进行REST请求时,通常都将delete请求的唯一标识拼接在url中,所以delete请求也不需要requestType的body信 息,就如上面三个函数一样,非常简单。 url指定delete请求的位置,urlVariable绑定url中的参数即可。
Spring boot 之 RestTemplate
传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。Spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。
内置发送get post delete等请求的方法,在SpringBoot中只要导入spring-boot-starter-web的依赖可以直接使用。
为什么说是简单便捷呢?我们来看以下两种实现方式:
/**
* @param url
* @param param
* @param headers
* @param connectTimeout milliseconds
* @param readTimeout milliseconds
* @return
*/
public static String get(String url, String param, Map<String, String> headers, int connectTimeout, int readTimeout) {
BufferedReader in = null;
StringBuilder builder = new StringBuilder();
try {
String urlNameString = url;
if (param != null) {
urlNameString += "?" + param;
}
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection)realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", USER_AGENT);
if (connectTimeout > 0) {
conn.setConnectTimeout(connectTimeout);
}
if (readTimeout > 0) {
conn.setReadTimeout(readTimeout);
}
if (headers != null) {
for (Entry<String, String> entry: headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
conn.getInputStream(), DEFAULT_CHARSET));
String line;
while ((line = in.readLine()) != null) {
builder.append(line).append("\n");
}
}
} catch (Exception e) {
LOGGER.error("HttpUtil.get error.", e);
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
LOGGER.error("HttpUtil.get finally error.", e2);
}
}
return builder.toString();
}
- 使用RestTempalte
String result = restTemplate.getForObject(url,String.class);
快速开始
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第一步:配置RestTemplate
/**
* RestTemplate配置
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//超时设置
factory.setReadTimeout(6000);
factory.setConnectTimeout(10000);
return factory;
}
}
第二步:使用RestTemplate的Api发送请求
/**
* 测试get请求
*/
@Test
public void test1(){
/**
* getForObject
*
* 参数1 要请求的地址的url 必填项
* 参数2 响应数据的类型 是String 还是 Map等 必填项
* 参数3 请求携带参数 选填
*
* getForObject 方法的返回值就是 被调用接口响应的数据
*/
String result = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a",String.class);
System.out.println(result);
}
Get请求的API
getForObject API:参数1 url地址,参数2 响应数据类型 参数3 请求携带参数 返回值类型为String。
getForEntity API:参数1 url地址,参数2 响应数据类型 参数3 请求携带参数 返回值类型为ResponseEntity。
Get请求传递参数可以是以占位符的方式,或者是通过map传参。
/**
* 测试get请求
*/
@Test
public void test2(){
String result = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a", String.class);
System.out.println("getForObject返回值:"+result);
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a", String.class);
System.out.println("通过ResponseEntity获取的响应状态码:"+responseEntity.getStatusCode());
System.out.println("通过ResponseEntity获取的响应数据:"+responseEntity.getBody());
/**
* 通过Map传参
*/
Map map= new HashMap();
map.put("phone","13429667914");
map.put("key","1cca71876dc0669109ed3f9501a85e8a");
String resultId = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone={phone}&key={key}",
String.class,map);
System.out.println("map传参" + resultId);
}
可以看到如下效果:
getForObject返回值:{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
通过ResponseEntity获取的响应状态码:200 OK
通过ResponseEntity获取的响应数据:{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
map传参{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
Post请求的API
postForObject API:
参数1 url地址
参数2 通过LinkedMultiValueMap对象封装请求参数
参数3 响应数据类型返回值类型为String
postForLocation API:
参数1 url地址
参数2 通过LinkedMultiValueMap对象封装请求参数
响应值:获取返回的URI
postForLocation使用场景:在登录或注册完成,跳转到别的页面时,并获取要跳转的URI。
**注意:**postForLocation方法返回的URI实际上是指响应头的Location字段,所以,请求的接口的响应头必须要有Location字段(即请求的接口实际上是一个重定向的接口),否则返回值为null。
package com.example.restdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/test")
public class HelloController {
/**
* 测试 postForLocation
*/
@PostMapping("/postLocation")
public String testPostForLocation(String username,String password){
System.out.println(username);
return "redirect:/index.html";
}
}
测试Post请求
/**
* 测试Post请求
*/
@Test
public void test3(){
LinkedMultiValueMap<String, String> request = new LinkedMultiValueMap<>();
request.set("key","9363eb48d9bd745e7627322e2ae78099");
request.set("date","2021-10-22");
String result = restTemplate.postForObject("http://v.juhe.cn/laohuangli/d",request,String.class);
System.out.println("通过LinkedMultiValueMap对象封装请求参数");
System.out.println(result);
Map map = new HashMap();
map.put("key","9363eb48d9bd745e7627322e2ae78099");
map.put("date","2021-10-22");
String result2 = restTemplate.postForObject("http://v.juhe.cn/laohuangli/d?key={key}&date={date}",request,
String.class,map);
System.out.println("通过参数拼接的方式:");
System.out.println(result2);
LinkedMultiValueMap<String, String> req = new LinkedMultiValueMap<>();
req.set("username","小明");
req.set("password","decs3465523");
URI uri = restTemplate.postForLocation("http://localhost:8085/test/postLocation", req);
System.out.println("postForLocation请求到的地址为:"+uri);
}
执行效果如下:
通过LinkedMultiValueMap对象封装请求参数
{"reason":"successed","result":{"id":"4190","yangli":"2021-10-22","yinli":"辛丑(牛)年九月十七","wuxing":"杨柳木 收执位","chongsha":"冲牛(丁丑)煞西","baiji":"癸不词讼理弱敌强 未不服药毒气入肠","jishen":"天恩 母仓 四相 不将 玉宇","yi":"祭祀 作灶 纳财 捕捉 畋猎 馀事勿取","xiongshen":"河魁 月刑 五虚 朱雀 触水龙","ji":"动土 破土 开市 安葬"},"error_code":0}
通过参数拼接的方式:
{"reason":"successed","result":{"id":"4190","yangli":"2021-10-22","yinli":"辛丑(牛)年九月十七","wuxing":"杨柳木 收执位","chongsha":"冲牛(丁丑)煞西","baiji":"癸不词讼理弱敌强 未不服药毒气入肠","jishen":"天恩 母仓 四相 不将 玉宇","yi":"祭祀 作灶 纳财 捕捉 畋猎 馀事勿取","xiongshen":"河魁 月刑 五虚 朱雀 触水龙","ji":"动土 破土 开市 安葬"},"error_code":0}
postForLocation请求到的地址为:http://localhost:8085/index.html
总结
本文主要向大家介绍了 RestTemplate 这样一个 HTTP 请求工具类的常见用法,并没有涉及到源码,其实内部源码很多很深,包括和解析url模板,绑定参数的UriBuilderFactory UriTemplateHandler等等,建议跟踪源码跑一遍会更加理解restTemplate。这里就简单提下。
更多技术文章
Spring Boot 的 TestRestTemplate 使用
Spring Boot 的 TestRestTemplate 使用
TestRestTemplate 和 RestTemplate 很类似,不过它是专门用在测试环境中的,本文我们将会讲述 TestRestTemplate 的一些常用方法。
如果我们在测试环境中使用 @SpringBootTest,则可以直接使用 TestRestTemplate。
添加 maven 依赖
要使用 TestRestTemplate,我们需要首先添加如下的 maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
TestRestTemplate VS RestTemplate
TestRestTemplate 和 RestTemplate 的功能很类似,都可以用来和 HTTP API 进行交互。实际上 TestRestTemplate 就是 RestTemplate 的封装。我们看下 TestRestTemplate 的代码:
public class TestRestTemplate {
private final RestTemplateBuilder builder;
private final HttpClientOption[] httpClientOptions;
private final RestTemplate restTemplate;
...
public void setUriTemplateHandler(UriTemplateHandler handler) {
this.restTemplate.setUriTemplateHandler(handler);
}
...
以 setUriTemplateHandler 为例,我们看到实际上 TestRestTemplate 调用了 restTemplate 里面的具体方法。
我们看一下 TestRestTemplate 基本的使用:
@Test
public void testGet (){
TestRestTemplate testRestTemplate = new TestRestTemplate();
ResponseEntity<String> response = testRestTemplate.
getForEntity(FOO_RESOURCE_URL + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
使用 Basic Auth Credentials
TestRestTemplate 封装了基本的 Auth Credentials,我们可以这样使用:
TestRestTemplate testRestTemplate
= new TestRestTemplate("user", "passwd");
ResponseEntity<String> response = testRestTemplate.
getForEntity(URL_SECURED_BY_AUTHENTICATION, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
使用 HttpClientOption
HttpClientOption 提供了如下几个选项:ENABLE_COOKIES, ENABLE_REDIRECTS, 和 SSL。
我们看下 TestRestTemplate 怎么使用:
TestRestTemplate testRestTemplate = new TestRestTemplate("user",
"passwd", TestRestTemplate.HttpClientOption.ENABLE_COOKIES);
ResponseEntity<String> response = testRestTemplate.
getForEntity(URL_SECURED_BY_AUTHENTICATION, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
如果我们不需要认证,则可以这样使用:
TestRestTemplate(TestRestTemplate.HttpClientOption.ENABLE_COOKIES)
我们也可以在创建 TestRestTemplate 之后添加认证:
TestRestTemplate testRestTemplate = new TestRestTemplate();
ResponseEntity<String> response = testRestTemplate.withBasicAuth(
"user", "passwd").getForEntity(URL_SECURED_BY_AUTHENTICATION,
String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
使用 RestTemplateBuilder
RestTemplateBuilder 为我们提供了自定义 RestTemplate 的机会,我们可以使用它来对 RestTemplate 进行封装:
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
restTemplateBuilder.configure(restTemplate);
TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder);
ResponseEntity<String> response = testRestTemplate.getForEntity(
FOO_RESOURCE_URL + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
本文的例子可以参考 https://github.com/ddean2009/learn-springboot2/tree/master/springboot-testRestTemplate
更多教程请参考 flydean 的博客
本文分享自微信公众号 - 程序那些事(flydean-tech)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。
Spring Boot的TestRestTemplate使用
Spring Boot的TestRestTemplate使用
TestRestTemplate和RestTemplate很类似,不过它是专门用在测试环境中的,本文我们将会讲述TestRestTemplate的一些常用方法。
如果我们在测试环境中使用@SpringBootTest,则可以直接使用TestRestTemplate。
添加maven依赖
要使用TestRestTemplate,我们需要首先添加如下的maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
TestRestTemplate VS RestTemplate
TestRestTemplate和RestTemplate的功能很类似,都可以用来和HTTP API进行交互。实际上TestRestTemplate就是RestTemplate的封装。 我们看下TestRestTemplate的代码:
public class TestRestTemplate {
private final RestTemplateBuilder builder;
private final HttpClientOption[] httpClientOptions;
private final RestTemplate restTemplate;
...
public void setUriTemplateHandler(UriTemplateHandler handler) {
this.restTemplate.setUriTemplateHandler(handler);
}
...
以setUriTemplateHandler为例,我们看到实际上TestRestTemplate调用了restTemplate里面的具体方法。
我们看一下TestRestTemplate基本的使用:
@Test
public void testGet (){
TestRestTemplate testRestTemplate = new TestRestTemplate();
ResponseEntity<String> response = testRestTemplate.
getForEntity(FOO_RESOURCE_URL + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
使用Basic Auth Credentials
TestRestTemplate封装了基本的Auth Credentials,我们可以这样使用:
TestRestTemplate testRestTemplate
= new TestRestTemplate("user", "passwd");
ResponseEntity<String> response = testRestTemplate.
getForEntity(URL_SECURED_BY_AUTHENTICATION, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
使用HttpClientOption
HttpClientOption提供了如下几个选项:ENABLE_COOKIES, ENABLE_REDIRECTS, 和 SSL。
我们看下TestRestTemplate怎么使用:
TestRestTemplate testRestTemplate = new TestRestTemplate("user",
"passwd", TestRestTemplate.HttpClientOption.ENABLE_COOKIES);
ResponseEntity<String> response = testRestTemplate.
getForEntity(URL_SECURED_BY_AUTHENTICATION, String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
如果我们不需要认证,则可以这样使用:
TestRestTemplate(TestRestTemplate.HttpClientOption.ENABLE_COOKIES)
我们也可以在创建TestRestTemplate之后添加认证:
TestRestTemplate testRestTemplate = new TestRestTemplate();
ResponseEntity<String> response = testRestTemplate.withBasicAuth(
"user", "passwd").getForEntity(URL_SECURED_BY_AUTHENTICATION,
String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
使用RestTemplateBuilder
RestTemplateBuilder为我们提供了自定义RestTemplate的机会,我们可以使用它来对RestTemplate进行封装:
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
restTemplateBuilder.configure(restTemplate);
TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder);
ResponseEntity<String> response = testRestTemplate.getForEntity(
FOO_RESOURCE_URL + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
本文的例子可以参考https://github.com/ddean2009/learn-springboot2/tree/master/springboot-testRestTemplate
更多教程请参考 flydean的博客
关于Spring RestTemplate详解和spring的resttemplate的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于RestTemplate详解、Spring boot 之 RestTemplate、Spring Boot 的 TestRestTemplate 使用、Spring Boot的TestRestTemplate使用的相关信息,请在本站寻找。
本文标签: