Spring RestTemplate使用方法总结

1. 引入依赖

首先,需要确认项目中是否直接或者间接引入过spring-web依赖,如果没有引入过,需要在pom.xml中添加以下代码引入依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.24.RELEASE</version>
</dependency>

2. 发送GET请求

使用RestTemplate发送GET请求主要有getForObject()getForEntity()2个方法,每个方法分别提供了3种不同的重载。

2.1 使用getForObject发送GET请求(无参数)

使用getForObject()实现:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getCurrentEnv";
String response = restTemplate.getForObject(url, String.class);
System.out.println(response);

假设以上接口返回的报文为:

json 复制代码
{
    "serverAddress": "www.example.dev.com",
    "env": "dev"
}

也可以直接解析为自定义的类型:

java 复制代码
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class EnvInfo {
    private String serverAddress;

    private String env;
}
java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getCurrentEnv";
EnvInfo response = restTemplate.getForObject(url, EnvInfo.class);
System.out.println(JSON.toJSONString(response));

2.2 使用getForEntity发送GET请求(无参数)

也可以使用getForEntity()实现和2.1同样的功能,代码如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getCurrentEnv";
ResponseEntity<EnvInfo> responseEntity = restTemplate.getForEntity(url, EnvInfo.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
    EnvInfo response = responseEntity.getBody();
    System.out.println(JSON.toJSONString(response));
}

2.3 使用getForObject发送GET请求(带参数)

第一种方法是直接在url上拼接上参数,如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getDataList?pageIndex=1&pageSize=20";
EnvInfo response = restTemplate.getForObject(url, EnvInfo.class);
System.out.println(JSON.toJSONString(response));

第二种方法是使用占位符添加参数,如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getDataList?pageIndex={1}&pageSize={2}";
EnvInfo response = restTemplate.getForObject(url, EnvInfo.class, 1, 20);
System.out.println(JSON.toJSONString(response));

以上代码也可以替换为:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String url = "https://www.example.com/getDataList?pageIndex={pageIndex}&pageSize={pageSize}";
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("pageIndex", "1");
uriVariables.put("pageSize", "20");
EnvInfo response = restTemplate.getForObject(url, EnvInfo.class, uriVariables);
System.out.println(JSON.toJSONString(response));

注意事项:

uriVariables中的key必须和url中的占位符名称一致,否则会抛出异常:

java.lang.IllegalArgumentException: Map has no value for 'pageIndex'

第三种方法是使用UriComponentsBuilder添加参数,该种方法相比于前两种方法更加灵活,可以实现动态添加参数,代码如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String httpUrl = "https://www.example.com/getDataList";
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(httpUrl);
uriComponentsBuilder.queryParam("pageIndex", 1);
uriComponentsBuilder.queryParam("pageSize", 20);

String url = uriComponentsBuilder.toUriString();
EnvInfo response = restTemplate.getForObject(url, EnvInfo.class);
System.out.println(JSON.toJSONString(response));

2.4 使用getForEntity发送GET请求(带参数)

也可以使用getForEntity()实现和2.3同样的功能,代码如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String httpUrl = "https://www.example.com/getDataList";
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(httpUrl);
uriComponentsBuilder.queryParam("pageIndex", 1);
uriComponentsBuilder.queryParam("pageSize", 20);

String url = uriComponentsBuilder.toUriString();
ResponseEntity<EnvInfo> responseEntity = restTemplate.getForEntity(url, EnvInfo.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
    EnvInfo response = responseEntity.getBody();
    System.out.println(JSON.toJSONString(response));
}

2.5 getForObject与getForEntity的区别

getForEntity()getForObject()相比,返回值用了ResponseEntity进行封装,可以多获取到以下2种信息:

  1. HTTP状态码
  2. Response Headers

代码示例:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String httpUrl = "https://www.example.com/getDataList";
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(httpUrl);
uriComponentsBuilder.queryParam("pageIndex", 1);
uriComponentsBuilder.queryParam("pageSize", 20);

String url = uriComponentsBuilder.toUriString();
ResponseEntity<EnvInfo> responseEntity = restTemplate.getForEntity(url, EnvInfo.class);
System.out.println("statusCode: " + responseEntity.getStatusCode().toString());
System.out.println("statusCodeValue: " + responseEntity.getStatusCodeValue());
responseEntity.getHeaders().forEach((key, values) -> {
    System.out.println(key + ": " + values);
});

输出结果:

statusCode: 200 statusCodeValue: 200 Server: [openresty] Date: [Thu, 10 Apr 2025 05:39:02 GMT] Content-Type: [application/json] Transfer-Encoding: [chunked] Connection: [keep-alive]

其中Response Headers输出部分和Chrome浏览器Network中的Response Headers是一致的:

2.6 发送GET请求(带参数及请求头)

一般情况下,请求第三方接口都需要签名、时间戳等请求头,但getForObject()getForEntity()都不支持,

此时需要使用exchange()方法,代码如下所示:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

String httpUrl = "https://www.example.com/getDataList";
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(httpUrl);
uriComponentsBuilder.queryParam("pageIndex", 1);
uriComponentsBuilder.queryParam("pageSize", 20);

HttpHeaders headers = new HttpHeaders();
headers.set("signature", "3045022100875efcef9eb54626bb0168a6baa7c61265d0001d49243f");
headers.set("timestamp", String.valueOf(System.currentTimeMillis()));

String url = uriComponentsBuilder.toUriString();
ResponseEntity<EnvInfo> responseEntity = restTemplate.exchange(url,
        HttpMethod.GET,
        new HttpEntity<>(headers),
        EnvInfo.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
    EnvInfo response = responseEntity.getBody();
    System.out.println(JSON.toJSONString(response));
}

3. 发送POST请求

使用RestTemplate发送POST请求主要有postForObject()postForEntity()2个方法,每个方法分别提供了3种不同的重载。

3.1 发送POST请求(带参数、json方式)

使用postForObject()实现:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

LoginParams loginParams = new LoginParams();
loginParams.setUsername("zhangsan");
loginParams.setPassword("123456");

HttpEntity<LoginParams> request = new HttpEntity<>(loginParams, headers);

String url = "https://www.example.com/login";
String response = restTemplate.postForObject(url, request, String.class);
System.out.println(response);

LoginParams的定义如下所示:

java 复制代码
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class LoginParams {
    private String username;

    private String password;
}

假设以上接口返回的报文为:

json 复制代码
{
    "code": 200,
    "expire": "2025-04-11 14:42:22",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDQzNTM3NDIsImlkZW50aXR5"
}

也可以直接解析为自定义的类型:

java 复制代码
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class LoginResponse {
    private Integer code;

    private String expire;

    private String token;
}
java 复制代码
RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

LoginParams loginParams = new LoginParams();
loginParams.setUsername("zhangsan");
loginParams.setPassword("123456");

HttpEntity<LoginParams> request = new HttpEntity<>(loginParams, headers);

String url = "https://www.example.com/login";
LoginResponse response = restTemplate.postForObject(url, request, LoginResponse.class);
System.out.println(JSON.toJSONString(response));

也可以使用postForEntity()实现同样的功能,代码如下所示:

java 复制代码
ResponseEntity<LoginResponse> responseEntity = restTemplate.postForEntity(url, request, LoginResponse.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
    LoginResponse response = responseEntity.getBody();
    System.out.println(JSON.toJSONString(response));
}

3.2 发送POST请求(带参数、form表单方式)

使用postForObject()实现:

java 复制代码
RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", "zhangsan");
map.add("password", "123456");

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

String url = "https://www.example.com/login";
LoginResponse response = restTemplate.postForObject(url, request, LoginResponse.class);
System.out.println(JSON.toJSONString(response));

也可以使用postForEntity()实现同样的功能,代码如下所示:

java 复制代码
ResponseEntity<LoginResponse> responseEntity = restTemplate.postForEntity(url, request, LoginResponse.class);
if (responseEntity.getStatusCode() == HttpStatus.OK) {
    LoginResponse response = responseEntity.getBody();
    System.out.println(JSON.toJSONString(response));
}

3.3 postForObject与postForEntity的区别

postForObject()postForEntity()的区别,与getForEntity()getForObject()的区别一样,

返回值用了ResponseEntity进行封装。

4. 超时时间设置

如果需要自定义HTTP请求的连接超时时间和数据传输超时时间,代码如下所示:

java 复制代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Value("${restTemplate.connectTimeout:5000}")
    private int connectTimeout;

    @Value("${restTemplate.readTimeout:10000}")
    private int readTimeout;

    @Bean
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        simpleClientHttpRequestFactory.setConnectTimeout(connectTimeout);
        simpleClientHttpRequestFactory.setReadTimeout(readTimeout);

        return new RestTemplate(simpleClientHttpRequestFactory);
    }
}
相关推荐
qq_485015216 分钟前
Java网络编程干货
java·网络·php
努力的搬砖人.15 分钟前
java爬虫案例
java·经验分享·后端
Miraitowa_cheems24 分钟前
JAVA SE 自我总结
java·开发语言·javase
老马啸西风25 分钟前
java 开源中文的繁简体转换 opencc4j-03-简体还是繁体,你说了算!
java
老马啸西风28 分钟前
java 开源中文的繁简体转换 opencc4j-02-一个汉字竟然对应两个 char?
java
都叫我大帅哥30 分钟前
遍历世界的通行证:迭代器模式的导航艺术
java·后端·设计模式
_沉浮_31 分钟前
Spring AI使用tool Calling和MCP
java·人工智能·spring
Alt.938 分钟前
SpringMVC基础三(json)
java·开发语言
刘大猫261 小时前
Arthas profiler(使用async-profiler对应用采样,生成火焰图)
java·人工智能·后端
滴水可藏海1 小时前
EasyExcel系列:读取空数据行的问题
java