Spring之RestTemplate简单使用


前言

什么是RestTemplate:

RestTemplate是一个执行HTTP请求的同步阻塞式工具类,它仅仅只是在 HTTP 客户端库(例如 JDK HttpURLConnection,Apache HttpComponents,okHttp 等)基础上,封装了更加简单易用的模板方法 API,方便程序员利用已提供的模板方法发起网络请求和处理,能很大程度上提升我们的开发效率。它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。

本文仅介绍简单的使用方法。


一、环境配置

如果当前项目是SpringBoot,添加如下依赖接口!

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

二、API 实践

1.常用get请求方法

通过RestTemplate发送HTTP GET协议请求,经常使用到的方法有两个:

  • getForObject():返回值是HTTP协议的响应体
  • getForEntity():返回的是ResponseEntity,ResponseEntity是对HTTP响应的封装,除了包含响应体,还包含HTTP状态码、contentType、contentLength、Header等信息

1.1 getForObject()请求示例

  • 不带参数:

(uri, String.class) 这两个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型

String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
  • 携带参数:

如果是get请求,又想要把参数封装到map里面进行传递的话,Map需要使用HashMap,且uri需要使用占位符
(uri, String.class, paramMap) 这三个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型,请求参数

String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();
// 封装参数,这里是HashMap
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");
String result = restTemplate.getForObject(uri, String.class, paramMap);

1.2 getForEntity()请求示例

上面的所有的getForObject请求传参方法,getForEntity都可以使用,使用方法上也几乎是一致的,只是在返回结果接收的时候略有差别
getForEntity使用 ResponseEntity<T> responseEntity 来接收响应结果。用responseEntity.getBody()获取响应体

  • 不带参数:
    (uri, String.class) 这两个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型
String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate .getForEntity(uri, String.class);
// 获取响应体
System.out.println("HTTP 响应body:" + response.getBody().toString());

// 以下是getForEntity比getForObject多出来的内容
HttpStatus statusCode = response.getStatusCode();
int statusCodeValue = response.getStatusCodeValue();
HttpHeaders headers = response.getHeaders();

System.out.println("HTTP 响应状态:" + statusCode);
System.out.println("HTTP 响应状态码:" + statusCodeValue);
System.out.println("HTTP Headers信息:" + headers);
  • 携带参数:
    如果是get请求,又想要把参数封装到map里面进行传递的话,Map需要使用HashMap,且uri需要使用占位符
    (uri, String.class, paramMap) 这三个参数分别代表 请求地址、HTTP响应转换被转换成的对象类型,请求参数
String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();
// 封装参数,这里是HashMap
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");
ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class, paramMap);

2.常用post请求方法

POST请求方法和GET请求方法上大同小异,RestTemplate的POST请求也包含两个主要方法:

  • postForObject():返回body对象
  • postForEntity():返回全部的信息

postForObject和postForEntity方法的区别主要在于可以在postForEntity方法中设置header的属性,当需要指定header的属性值的时候,使用postForEntity方法。

1、网上都说需要使用MultiValueMap传递参数,但是经过自己测试,发现 MultiValueMap 传递参数请求失败(JSON parse error),改为HashMap反而成功

请求示例

String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();

// 使用MultiValueMap调用失败,改用HashMap
// MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
// paramMap.add("name", "张三");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "张三");

// 1、使用postForObject请求接口
String result = restTemplate.postForObject(uri, paramMap, String.class);

// 2、使用postForEntity请求接口
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");

// 使用MultiValueMap调用失败,改用HashMap
// HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers);
String body = JSONUtil.toJsonStr(paramMap);
HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, httpEntity, String.class);

2、使用这二种方法传递参数,还可以通过JSONObject或者实体类传递参数

请求示例

String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();

User user = new User ();
user .setName("张三")

// 1、使用postForObject请求接口
String result = restTemplate.postForObject(uri, user, String.class);

// 2、使用postForEntity请求接口
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");

HttpEntity<String> httpEntity = new HttpEntity<String>(JSONUtil.toJsonStr(user),headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, httpEntity, String.class);

3.通用exchange请求方法

在RestTemplate工具类里面,还有一个exchange通用协议请求方法,exchange方法和postForEntity类似,但是更灵活,它可以发送GET、POST、DELETE、PUT、OPTIONS、PATCH等等HTTP方法请求

RestTemplate.exchange()方法的使用:

方法名称:exchange(String url, HttpMethod method,@Nullable HttpEntity<?> requestEntity, Class responseType, Map uriVariables)
说明:1)url: 请求地址;
     2)method: 请求类型(如:POST,PUT,DELETE,GET)3)requestEntity: 请求实体,封装请求头,请求内容
     4)responseType: 响应类型,根据服务接口的返回类型决定
     5)uriVariables: url中参数变量值

3.1 get请求示例

以下演示传递header和参数的情况,不需要可以传null或不传

String uri = "http://localhost:8080/springTest/template?name={name}&age={age}";
RestTemplate restTemplate = new RestTemplate();

Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("name", "张三");
paramMap.put("age", "18");

HttpHeaders headers = new HttpHeaders();
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");
HttpEntity<String> httpEntity = new HttpEntity<>(null, headers);

ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, String.class,paramMap);

//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
        new Response(500, "返回空数据") :
        JSONObject.toJavaObject(jsonObject, Response.class);

3.2 post请求示例

1、网上都说需要使用MultiValueMap传递参数,但是经过自己测试,发现 MultiValueMap 传递参数请求失败(JSON parse error),改为HashMap反而成功

请求示例:

String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();

// 使用MultiValueMap调用失败,改用HashMap
// MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
// paramMap.add("name", "张三");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "张三");

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");

// 使用MultiValueMap调用失败,改用HashMap
// HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(paramMap,headers);
String body = JSONUtil.toJsonStr(paramMap);
HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);

//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
        new Response(500, "返回空数据") :
        JSONObject.toJavaObject(jsonObject, Response.class);

2、使用这种方法传递参数,和postForEntity类似,还可以通过JSONObject传递参数

String uri = "http://localhost:8080/springTest/template";
RestTemplate restTemplate = new RestTemplate();

User user = new User ();
user .setName("张三")

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("token", "Bearer eyJ0eXAiOiJqd3QiLC.....");

HttpEntity<String> httpEntity = new HttpEntity<String>(JSONUtil.toJsonStr(user),headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);

//返回数据处理,实体接收
String responseStr = response.getBody();
JSONObject jsonObject = JSON.parseObject(responseStr);
// 返回数据
return StringUtil.isBlank(responseStr) ?
        new Response(500, "返回空数据") :
        JSONObject.toJavaObject(jsonObject, Response.class);

三、https 请求

某些情况下需要进行https请求,需要特殊处理,下面以通用exchange请求方法为例

1.添加依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

2.添加配置

package com.demo.config;

import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.ssl.SSLContexts;
import org.springframework.http.client.SimpleClientHttpRequestFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.KeyStore;

public class HttpsClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        try {
            if (connection instanceof HttpsURLConnection) {// https协议,修改协议版本
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                // 信任任何链接,忽略对证书的校验
                TrustStrategy anyTrustStrategy = (x509Certificates, s) -> true;
                //自定义SSLContext
                SSLContext ctx = SSLContexts.custom().loadTrustMaterial(trustStore, anyTrustStrategy).build();
                // ssl问题
                ((HttpsURLConnection) connection).setSSLSocketFactory(ctx.getSocketFactory());
                //解决No subject alternative names matching IP address xxx.xxx.xxx.xxx found问题
                ((HttpsURLConnection) connection).setHostnameVerifier((s, sslSession) -> true);
                HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
                super.prepareConnection(httpsConnection, httpMethod);
            } else { // http协议
                super.prepareConnection(connection, httpMethod);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.请求实例

3.1 get请求示例

private Response getApi(String url) {
    try {
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        // 发送请求
        RestTemplate client = new RestTemplate();
        if (url.contains("https")){
            client = new RestTemplateBuilder()
                    .requestFactory(HttpsClientHttpRequestFactory::new)
                    //basic认证
                    .basicAuthentication("username", "password")
                    .build();
        }
        ResponseEntity<String> response = client.exchange(url, HttpMethod.GET, requestEntity, String.class);
        String responseStr = response.getBody();
        JSONObject jsonObject = JSON.parseObject(responseStr);
        // 返回数据
        return StringUtil.isBlank(responseStr) ?
                new Response(500, "返回空数据") :
                JSONObject.toJavaObject(jsonObject, Response.class);
    } catch (Exception e) {
        log.error("response error:{}", e);
        return new Response(500, e.toString());
    }
}

3.2 post请求示例

private Response postApi(String url, Map<String, Object> paramMap) {
    try {
        // 请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // 参数信息
        String body = JSONUtil.toJsonStr(paramMap);
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        // 发送请求
        RestTemplate client = new RestTemplate();
        if (url.contains("https")){
            client = new RestTemplateBuilder()
                    .requestFactory(HttpsClientHttpRequestFactory::new)
                    //basic认证
                    .basicAuthentication("username", "password")
                    .build();
        }
        ResponseEntity<String> response = client.exchange(url, HttpMethod.POST, requestEntity, String.class);
        String responseStr = response.getBody();
        JSONObject jsonObject = JSON.parseObject(responseStr);
        // 返回数据
        return StringUtil.isBlank(responseStr) ?
                new Response(500, "返回空数据") :
                JSONObject.toJavaObject(jsonObject, Response.class);
    } catch (Exception e) {
        log.error("response error:{}", e);
        return new Response(500, e.toString());
    }
}

总结

本文仅仅简单介绍了RestTemplate的使用,而RestTemplate提供了大量能使我们快速便捷地处理Http请求的方法。

### 如何在 Spring MVC 中使用 RestTemplate 进行 HTTP 请求操作 `RestTemplate` 是 Spring 提供的一个同步客户端,用于执行 HTTP 请求。它可以轻松地发送 GET、POST、PUT 和 DELETE 等类型的请求,并处理响应数据。 以下是关于 `RestTemplate` 的基本使用方法以及一个完整的示例: #### 导入依赖 为了在项目中使用 `RestTemplate`,需要确保项目的构建文件(如 Maven 或 Gradle)已包含必要的 Spring Web 依赖项[^2]。 对于 Maven 用户: ```xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.10</version> </dependency> ``` 对于 Gradle 用户: ```gradle implementation 'org.springframework:spring-web:5.3.10' ``` --- #### 创建并配置 RestTemplate 实例 可以通过直接实例化 `RestTemplate` 来创建对象,或者将其声明为 Spring Bean 并注入到其他组件中。 ```java import org.springframework.web.client.RestTemplate; public class RestClient { private final RestTemplate restTemplate = new RestTemplate(); public String fetchUserDetails(String userId) { String url = "https://api.example.com/users/{userId}"; return restTemplate.getForObject(url, String.class, userId); } } ``` 在此代码片段中,`getForObject()` 方法被用来发起一个带有路径参数的 GET 请求[^2]。 --- #### 处理复杂场景下的请求 当涉及到更复杂的 HTTP 请求时,可以利用以下功能来增强灵活性: ##### 发送 POST 请求 如果需要向服务器提交 JSON 数据,则可以使用 `postForEntity()` 方法。 ```java import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; public class PostRequestExample { private static final RestTemplate restTemplate = new RestTemplate(); public ResponseEntity<String> createUser(User user) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<User> request = new HttpEntity<>(user, headers); String url = "https://api.example.com/users"; return restTemplate.postForEntity(url, request, String.class); } // 假设 User 类已经定义好 public static class User { private String name; private int age; // Getters and Setters omitted for brevity } } ``` 此代码展示了如何通过设置自定义头信息和传递实体体内容完成 POST 请求的操作[^2]。 --- #### 配置超时和其他高级选项 默认情况下,`RestTemplate` 不会自动应用连接或读取超时时间。这可能会影响应用程序性能,尤其是在网络状况不佳的情况下。因此建议显式指定这些属性。 ```java import java.time.Duration; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; public class CustomizedRestTemplateConfig { public RestTemplate createCustomizedRestTemplate() { CloseableHttpClient httpClient = HttpClients.custom() .setConnectionTimeToLive(Duration.ofSeconds(30)) .build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); factory.setConnectTimeout(5000); // 设置连接超时时间为 5 秒钟 factory.setReadTimeout(10000); // 设置读取超时时间为 10 秒钟 return new RestTemplate(factory); } } ``` 以上实现方式基于 Apache HttpClient 构建了一个具有特定行为特性的 `RestTemplate` 实例[^2]。 --- #### 测试 REST API 调用逻辑 借助于之前提到过的 **Spring MVC Test Framework**[^1],可以在单元测试阶段验证控制器的行为是否符合预期,而无需实际部署整个应用环境。 假设我们有一个简单的 Controller 接口如下所示: ```java @RestController @RequestMapping("/users") public class UserController { @GetMapping("/{id}") public String getUserById(@PathVariable String id) { return "User with ID: " + id; } } ``` 那么对应的 MockMvc 单元测试可能是这样的形式: ```java @WebMvcTest(UserController.class) class UserControllerTests { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; // 如果存在服务层的话也需要模拟出来 @Test void testGetUserById() throws Exception { this.mockMvc.perform(get("/users/1")) .andExpect(status().isOk()) .andExpect(content().string("User with ID: 1")); } } ``` 这里运用到了 Spring Boot Testing 功能的一部分[^3]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值