Spring的RestTemplate的使用

本文详细介绍了Spring Boot中RestTemplate的使用,包括如何设置超时时间、GET和POST请求的方法,如getForObject、postForLocation及exchange等。通过示例展示了如何通过RestTemplate调用接口并处理响应,强调了正确设置超时时间以避免内存溢出问题的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

您好,我是码农飞哥,感谢您阅读此文。作为一名Java开发者,我们怎么都绕不开调用外部接口的场景,调用的方式要么是通过Http协议来调用,要么是通过RPC协议来调用,通过Http协议调用的话我们就需要用到Http的Api。比较常用的有Apache的HttpClient和原生的HttpURLConnection。这些Api都比较好用,但是我们今天要介绍一种更加好用API,Spring自带的RestTemplate,能力更强,使用更方便。

目录

    写在前面
    怎么用?
        SpringBoot项目
        设置超时时间
    GET请求
        返回业务对象类getForObject方法
    POST 请求
    postForLocation
    exchange 方法的使用
    总结

怎么用?
SpringBoot项目

SpringBoot项目中,只需要引入spring-boot-starter-web依赖就可以了,其实spring-boot-starter-web依赖也是SpringBoot项目必备的一个依赖。

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

设置超时时间

引入依赖之后,就来开始使用吧,任何一个Http的Api我们都可以设置请求的连接超时时间,请求超时时间,如果不设置的话,就可能会导致连接得不到释放,造成内存溢出。这个是我们需要重点注意的点,下面就来看看RestTemplate如何来设置超时时间呢?我们可以在SimpleClientHttpRequestFactory类中设置这两个时间,然后将factory传给RestTemplate实例,设置如下:

@Configuration
public class RestTemplateConfig {
/**
* 服务器返回数据(response)的时间
/
private static final Integer READ_TIME_OUT = 6000;
/
*
* 连接上服务器(握手成功)的时间
*/
private static final Integer CONNECT_TIME_OUT = 6000;

@Bean
public RestTemplate restTemplate(){
    ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient());
    return new RestTemplate(requestFactory);
}

@Bean
public HttpClient httpClient(){
   //默认证书有效
    SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
    SSLContext sslContext = null;
    try {
        //信任所有的SSL证书
        sslContext = SSLContextBuilder.create().setProtocol(SSLConnectionSocketFactory.SSL)
                .loadTrustMaterial((x, y) -> true).build();
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (sslContext != null) {
        sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
    }
    // 支持HTTP、HTTPS
    Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.getSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    connectionManager.setMaxTotal(200);
    connectionManager.setDefaultMaxPerRoute(100);
    connectionManager.setValidateAfterInactivity(2000);
    RequestConfig requestConfig = RequestConfig.custom()
            // 服务器返回数据(response)的时间,超时抛出read timeout
            .setSocketTimeout(READ_TIME_OUT)
            // 连接上服务器(握手成功)的时间,超时抛出connect timeout
            .setConnectTimeout(CONNECT_TIME_OUT)
            // 从连接池中获取连接的超时时间,超时抛出ConnectionPoolTimeoutException
            .setConnectionRequestTimeout(1000)
            .build();
    return HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();
}

}

说完了RestTemplate的相关设置,下面就来看看平时我们用的最多两种请求方法:get方法和post方法吧。
GET请求

RestTemplate中提供的get请求的方法主要分为两类,一类是只返回请求体,一类是返回ResponseEntity对象,这个对象主要是包装了Http请求的响应状态status,响应头headers,和响应体body。后面我们会详细介绍。首先来看看getForObject方法。
返回业务对象类getForObject方法

getForObject方法的重载方法有如下三个:

/**
方法一,直接将参数添加到url上面。
* Retrieve a representation by doing a GET on the specified URL.
* The response (if any) is converted and returned.
*

URI Template variables are expanded using the given URI variables, if any.
* @param url the URL 请求地址
* @param responseType the type of the return value 响应体的类型
* @param uriVariables the variables to expand the template 传入的参数
* @return the converted object
/
@Nullable
T getForObject(String url, Class responseType, Object… uriVariables) throws RestClientException;
/
*
方法二,通过Map来提交参数。
* Retrieve a representation by doing a GET on the URI template.
* The response (if any) is converted and returned.
*

URI Template variables are expanded using the given map.
* @param url the URL
* @param responseType the type of the return value
* @param uriVariables the map containing variables for the URI template
* @return the converted object
*/
@Nullable
T getForObject(String url, Class responseType, Map<String, ?> uriVariables) throws RestClientException;

/**
   方法三,用URI来请求。
 * Retrieve a representation by doing a GET on the URL .
 * The response (if any) is converted and returned.
 * @param url the URL
 * @param responseType the type of the return value
 * @return the converted object
 */
@Nullable
<T> T getForObject(URI url, Class<T> responseType) throws RestClientException;

下面定义了一个接口,用来测试上面三个方法的使用,这个接口有两个参数,分别是userId和userName。
根据传入的userId和userName来查询用户,如果可以查询的到的话,则返回查询到的用户,如果查询不到的话,则返回找不到数据。
响应体是JSON格式的。

/**
* get请求获取用户
*
* @param userName 用户名
* @param userId 用户id
* @return
*/
@ResponseBody
@RequestMapping(value = “/getUser.do”)
public ResultData getUserByName(
@RequestParam(name = “userId”,required = false) Integer userId,
@RequestParam(name = “userName”,required = false) String userName) {
if (StringUtils.isAnyBlank(userName)) {
return new ResultData<>(HttpStatus.BAD_REQUEST.value(), null, “参数不能为空”);
}
List userList = new ArrayList<>();
for (int i = 1; i <= 2; i++) {
User user = new User();
user.setUserId(i);
user.setUserName(“张三” + i);
user.setAge(20 + i);
userList.add(user);
}
for (User user : userList) {
if (userName.equals(user.getUserName()) && userId.equals(user.getUserId())) {
return new ResultData(HttpStatus.OK.value(), user, “成功”);
}
}
return new ResultData<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), null, “找不到数据”);
}

下面我们就分别用那三个方法请求/getUser.do接口进行测试:

@Test
public void getForObjectTest() {
String baseUrl = “http://localhost:8081/testRestTemplateApp/getUser.do”;
//方法一: 直接拼接参数,推荐使用
String url =baseUrl+"?userName=张三1&userId=1";
ResultData resultData = restTemplate.getForObject(url, ResultData.class);
System.out.println("*****GET直接拼接参数查询返回结果={}" + JSON.toJSONString(resultData));
//方法一:传参替换,推荐使用
url = baseUrl+"?userName={?}&userId={?}";
resultData = restTemplate.getForObject(url, ResultData.class, “张三2”,2);
System.out.println("*****GET传参替换查询返回结果={}" + JSON.toJSONString(resultData));
//方法一:传参替换,使用String.format,推荐使用
url = baseUrl + String.format("?userName=%s&userId=%s", “张三2”,2);
resultData = restTemplate.getForObject(url, ResultData.class);
System.out.println("******GET使用String.format查询返回结果={}" + JSON.toJSONString(resultData));
//方法二:使用Map,不推荐使用
url = baseUrl + “?userName={userName}&userId={userId}”;
Map<String, Object> paramMap = new HashMap<>();
paramMap.put(“userName”, “张三1”);
paramMap.put(“userId”,1);
resultData = restTemplate.getForObject(url, ResultData.class, paramMap);
System.out.println("******GET使用Map查询返回结果={}" + JSON.toJSONString(resultData));
//方法三:使用URI,不推荐使用
URI uri = URI.create(baseUrl+"?userName=%E5%BC%A0%E4%B8%891&userId=1");
ResultData resultData1 = restTemplate.getForObject(uri, ResultData.class);
System.out.println("******GET使用URI查询返回结果={}" + JSON.toJSONString(resultData1));
}

运行结果如下:
在这里插入图片描述

需要注意的是:

 

。。。。。。。。。。。。。。。。。

版权原因,完整文章,请参考如下:

 Spring的RestTemplate的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值