RestTemplate是spring提供的用于发送HTTP请求的的模板方法,其中spring提供了很多类似的模板方法,例如RedisTemplate、JdbcTemplate等等…这类模板方法其实是对一些原生API的抽象和封装,有助与我们方便的使用这些API,并且它的可定制性很强,很多功能我们可以按需进行定制和扩展。
下面为RestTemplate的官网介绍:
The RestTemplate provides a higher level API over HTTP client libraries. It makes it easy to invoke REST endpoints in a single line. It exposes the following groups of overloaded methods。
大致意思:RestTemplate在HTTP客户端库上提供了更高级别的API。使用它很容易调用其他的restful API
阅读本片博客你将掌握:
让我们开始把~
老规矩贴一下pom文件
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.syx</groupId>
<artifactId>syxweb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>syxweb</name>
<description>webApp</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- <dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
-->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.42.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom里有一些不用的依赖可以自行剔除
package com.syx.config;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
/**
* @author:whh
* @date: 2022-11-07 20:42
*
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
/**
* 使用客户端类API调用远程交易时必须设置相应的超时时间,如果远程交易有问题如长时间未响应,若未设置超时时间,则会耗尽客户端所在服务器的资源
*/
// 连接超时
requestFactory.setConnectTimeout(5000);
//读超时
requestFactory.setReadTimeout(10000);
//连接池获取连接超时时间
requestFactory.setConnectionRequestTimeout(5000);
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//Httpclient连接池的方式,同时支持netty,okHttp以及其他http框架
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// 最大连接数
connectionManager.setMaxTotal(200);
// 同路由并发数
connectionManager.setDefaultMaxPerRoute(50);
//配置连接池
httpClientBuilder.setConnectionManager(connectionManager);
// 最大连接数
connectionManager.setMaxTotal(500);
// 同路由并发数(每个主机的并发)
connectionManager.setDefaultMaxPerRoute(100);
httpClientBuilder.setConnectionManager(connectionManager);
requestFactory.setHttpClient(httpClientBuilder.build());
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
}
@Test
public void func4() {
//远程REST调用API
String uri = "http://localhost:8888/user/testGet";
//发送请求
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
//打印响应
System.out.println(response.getBody());
}
@Test
public void func5() {
String uri = "http://localhost:8888/user/testJson";
//请求头中设备传递的数据类型未json
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
User user = new User();
user.setId("1");
user.setUsername("zsda");
String s = JSON.toJSON(user).toString();
//将json数据及请求头封装到请求体中
HttpEntity<String> formEntity = new HttpEntity<String>(s, headers);
//发送请求
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, formEntity, String.class);
System.out.println(response.getBody());
}
服务端代码如下:其中必须指定@RequestBody注解,用于springmvc将请求的json数据转换为java bean
/**
* 接受JSON类型的数据
* @param user
*/
@RequestMapping(value = "/testJson",method = RequestMethod.POST)
public void queryForJson(@RequestBody User user){
System.out.println(user);
}
@Test
public void func2() {
HttpHeaders headers = new HttpHeaders();
//设置请求头为multipart/form-data类型数据
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//MultiValueMap用于存放MULTIPART_FORM_DATA数据(其实就是key,value类型的键值对)
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("id", "1");
form.add("name", "张三");
String uri = "http://localhost:8888/user/test";
HttpEntity< MultiValueMap<String, String>> entity = new HttpEntity<>(form,headers);
//发送请求
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
System.out.println(response.getBody());
}
服务端代码如下:
@RequestMapping(value = "/testPost",method = RequestMethod.POST)
public User queryForPost(String id,String name){
User user = new User();
user.setUsername(name);
return user;
}
文件上传其实就是上传multipart/form-data类型的数据
@Test
public void func6() {
FileSystemResource file = new FileSystemResource("C:\\Users\\xxx\\Desktop\\xxx.jpg");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
try {
headers.setContentLength(file.contentLength());
} catch (IOException e) {
e.printStackTrace();
}
MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
form.add("file", file);
String uri = "http://localhost:8888/user/upload";
HttpEntity< MultiValueMap<String, Object>> entity = new HttpEntity<>(form,headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
System.out.println(response.getBody());
}
服务端代码如下:
@RequestMapping(value = "/upload",method = RequestMethod.POST)
public void uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
System.out.println(file.getOriginalFilename());
file.transferTo(new File("C:\\Users\\xxx\\Desktop\\xxx-temp.jpg"));
}
原生的RestTemplate在发送get请求时,无法携带body数据,但是有时候咱们的业务场景需要这样做,所以我们可以对RestTemplate重新配置达到该目的。
package com.syx.config;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
/**
* @author:whh
* @date: 2022-11-07 20:42
*
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory() {
@Override
protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
if (httpMethod == HttpMethod.GET) {
return new HttpGetRequestWithEntity(uri);
}
return super.createHttpUriRequest(httpMethod, uri);
}
};
/**
* 使用客户端类API调用远程交易时必须设置相应的超时时间,如果远程交易有问题如长时间未响应,若未设置超时时间,则会耗尽客户端所在服务器的资源
*/
// 连接超时
requestFactory.setConnectTimeout(5000);
//读超时
requestFactory.setReadTimeout(10000);
//连接池获取连接超时时间
requestFactory.setConnectionRequestTimeout(5000);
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//Httpclient连接池的方式,同时支持netty,okHttp以及其他http框架
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// 最大连接数
connectionManager.setMaxTotal(200);
// 同路由并发数
connectionManager.setDefaultMaxPerRoute(50);
//配置连接池
httpClientBuilder.setConnectionManager(connectionManager);
// 最大连接数
connectionManager.setMaxTotal(500);
// 同路由并发数(每个主机的并发)
connectionManager.setDefaultMaxPerRoute(100);
httpClientBuilder.setConnectionManager(connectionManager);
requestFactory.setHttpClient(httpClientBuilder.build());
restTemplate.setRequestFactory(requestFactory);
return restTemplate;
}
private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
public HttpGetRequestWithEntity(final URI uri) {
super.setURI(uri);
}
@Override
public String getMethod() {
return HttpMethod.GET.name();
}
}
}
重写一下HttpComponentsClientHttpRequestFactory 的createHttpUriRequest方法在请求方式为get的时候使用我们自定义的HttpGetRequestWithEntity 类
@Test
public void func2() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("id", "1");
form.add("name", "张三");
form.add("sex","男");
String uri = "http://localhost:8888/user/test";
HttpEntity< MultiValueMap<String, String>> entity = new HttpEntity<>(form,headers);
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
System.out.println(response.getBody());
}
服务端代码:
@RequestMapping(value = "/test",method = RequestMethod.GET)
public User query(User user){
return user;
}
ok~咱们的RestTemplate的使用方式就讲完啦