RestTemplate 是一个 spring-web 提供的执行HTTP请求的同步阻塞式工具类。
RestTemplate默认是使用SimpleClientHttpRequestFactory,内部是调用jdk的HttpConnection,默认超时为-1
1. 添加 Maven 坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. RestTemplate 配置
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.TimeUnit;
@Configuration
public class RestTemplateConfig {
/**
* 没有实例化RestTemplate时,初始化RestTemplate
* RestTemplate默认是使用SimpleClientHttpRequestFactory,
* 内部是调用jdk的HttpConnection,默认超时为-1
* @return
*/
@ConditionalOnMissingBean(RestTemplate.class)
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
/**
* 使用HttpClient作为底层客户端
* @return
*/
// private ClientHttpRequestFactory getClientHttpRequestFactory() {
// int timeout = 5000;
// RequestConfig config = RequestConfig.custom()
// .setConnectTimeout(timeout)
// .setConnectionRequestTimeout(timeout)
// .setSocketTimeout(timeout)
// .build();
// CloseableHttpClient client = HttpClientBuilder
// .create()
// .setDefaultRequestConfig(config)
// .build();
// return new HttpComponentsClientHttpRequestFactory(client);
// }
/**
* 使用OkHttpClient作为底层客户端
* @return
*/
// private ClientHttpRequestFactory getClientHttpRequestFactory(){
// OkHttpClient okHttpClient = new OkHttpClient.Builder()
// .connectTimeout(5, TimeUnit.SECONDS)
// .writeTimeout(5, TimeUnit.SECONDS)
// .readTimeout(5, TimeUnit.SECONDS)
// .build();
// return new OkHttp3ClientHttpRequestFactory(okHttpClient);
// }
}
3. 请求测试接口 TestController,FileController
TestController
import com.alibaba.fastjson.JSON;
import com.example.demo.req.UserReq;
import com.example.demo.res.GlobalResult;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
public class TestController {
/**
* 无参get请求
* @return
*/
@RequestMapping(value = "testGet", method = RequestMethod.GET)
@ResponseBody
public GlobalResult testGet(){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg("success,method:testGet");
return result;
}
/**
* 带参的get请求
* @return
*/
@RequestMapping(value = "testGet2/{id}/{name}", method = RequestMethod.GET)
@ResponseBody
public GlobalResult testGetByRestFul(@PathVariable(value = "id") String id, @PathVariable(value = "name") String name){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg(String.format("success,method:testGet2,id:%s name:%s", id, name));
return result;
}
/**
* 带参的get请求
* 占位符号传参
* @return
*/
@RequestMapping(value = "testGetByParam", method = RequestMethod.GET)
@ResponseBody
public GlobalResult testGetByParam(@RequestParam("userName") String userName,
@RequestParam("userPwd") String userPwd){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg(String.format("success,method:testGetByParam,userName:%s,userPwd:%s", userName , userPwd));
return result;
}
/**
* post表单请求
* @return
*/
@RequestMapping(value = "testPostByForm", method = RequestMethod.POST)
@ResponseBody
public GlobalResult testPostByForm(@RequestParam("userName") String userName,
@RequestParam("userPwd") String userPwd){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg(String.format("success,method:testPostByForm,userName:%s,userPwd:%s", userName , userPwd));
return result;
}
/**
* post表单请求
* @param userReq
* @return
*/
@RequestMapping(value = "testPostByFormAndObj", method = RequestMethod.POST)
@ResponseBody
public GlobalResult testPostByForm(UserReq userReq){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg(String.format("success,method:testPostByFormAndObj,json:%s", JSON.toJSONString(userReq)));
return result;
}
/**
* post请求 JSON
* @param userReq
* @return
*/
@RequestMapping(value = "testPostByJson", method = RequestMethod.POST)
@ResponseBody
public GlobalResult testPostByJson(@RequestBody UserReq userReq){
GlobalResult result = new GlobalResult();
result.setCode("200");
result.setMsg(String.format("success,method:testPostByJson,json:%s", JSON.toJSONString(userReq)));
return result;
}
/**
* put请求 JSON
* @param userReq
* @return
*/
@RequestMapping(value = "testPutByJson", method = RequestMethod.PUT)
@ResponseBody
public void testPutByJson(@RequestBody UserReq userReq){
System.out.println(String.format("success,method:testPutByJson,param:%s", JSON.toJSONString(userReq)));
}
/**
* delete请求 JSON
* @return
*/
@RequestMapping(value = "testDeleteByJson", method = RequestMethod.DELETE)
@ResponseBody
public void testDeleteByJson(){
System.out.println("success,method:testDeleteByJson");
}
/**
* 重定向
* @param userReq
* @return
*/
@RequestMapping(value = "testPostByLocation", method = RequestMethod.POST)
public String testPostByLocation(@RequestBody UserReq userReq){
return "redirect:index.html";
}
}
FileController
import com.example.demo.res.GlobalResult;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.UUID;
@RestController
public class FileController {
private static final String UPLOAD_PATH = "/home/cms/file/";
/**
* 文件上传
* @param uploadFile
* @return
*/
@RequestMapping(value = "upload", method = RequestMethod.POST)
public GlobalResult upload(@RequestParam("uploadFile") MultipartFile uploadFile,
@RequestParam("userName") String userName) {
// 在 uploadPath 文件夹中通过用户名对上传的文件归类保存
File folder = new File(UPLOAD_PATH + userName);
if (!folder.isDirectory()) {
folder.mkdirs();
}
// 对上传的文件重命名,避免文件重名
String oldName = uploadFile.getOriginalFilename();
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
//定义返回视图
GlobalResult result = new GlobalResult();
try {
// 文件保存
uploadFile.transferTo(new File(folder, newName));
result.setCode("200");
result.setMsg("文件上传成功,方法:upload,文件名:" + newName);
} catch (IOException e) {
e.printStackTrace();
result.setCode("500");
result.setMsg("文件上传失败,方法:upload,请求文件:" + oldName);
}
return result;
}
/**
* 带参的get请求(restful风格)
* @return
*/
@RequestMapping(value = "downloadFile/{userName}/{fileName}", method = RequestMethod.GET)
public void downloadFile(@PathVariable(value = "userName") String userName,
@PathVariable(value = "fileName") String fileName,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
File file = new File(UPLOAD_PATH + userName + File.separator + fileName);
if (file.exists()) {
//获取文件流
FileInputStream fis = new FileInputStream(file);
//获取文件后缀(.png)
String extendFileName = fileName.substring(fileName.lastIndexOf('.'));
//动态设置响应类型,根据前台传递文件类型设置响应类型
response.setContentType(request.getSession().getServletContext().getMimeType(extendFileName));
//设置响应头,attachment表示以附件的形式下载,inline表示在线打开
response.setHeader("content-disposition","attachment;fileName=" + URLEncoder.encode(fileName,"UTF-8"));
//获取输出流对象(用于写文件)
OutputStream os = response.getOutputStream();
//下载文件,使用spring框架中的FileCopyUtils工具
FileCopyUtils.copy(fis,os);
}
}
}
用户请求参数对象 UserReq, 全局返回对象 GlobalResult
public class UserReq {
private String userName;
private String userPwd;
//GET and SET and toString()
}
public class GlobalResult {
private String code;
private String msg;
//GET and SET and toString()
}
4. RestTemplate使用示例
import com.example.demo.req.UserReq;
import com.example.demo.res.GlobalResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestTemplateTest {
@Autowired
private RestTemplate restTemplate;
/**
* 不带参的get请求
*/
@Test
public void testGet(){
String url = "http://localhost:8080/testGet";
//发起请求
GlobalResult responseBean = restTemplate.getForObject(url, GlobalResult.class);
System.out.println(responseBean.toString());
}
/**
* 带参的get请求
*/
@Test
public void testGet2(){
String url = "http://localhost:8080/testGet2/{1}/{2}";
//发起请求
GlobalResult responseBean = restTemplate.getForObject(url, GlobalResult.class, "001", "张三");
System.out.println(responseBean.toString());
}
/**
* 带参的get请求
*/
@Test
public void testGetByParam(){
String url = "http://localhost:8080/testGetByParam?userName={userName}&userPwd={userPwd}";
//请求参数
Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("userName", "张三");
uriVariables.put("userPwd", "123456");
//发起请求(带参数请求)
GlobalResult responseBean = restTemplate.getForObject(url, GlobalResult.class, uriVariables);
System.out.println(responseBean.toString());
}
/**
* Get全部信息
*/
@Test
public void testAllGet(){
String url = "http://localhost:8080/testGet";
//发起请求,返回全部信息
ResponseEntity<GlobalResult> response = restTemplate.getForEntity(url, GlobalResult.class);
// 获取响应体
System.out.println("HTTP 响应body:" + response.getBody().toString());
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);
}
/**
* post表单提交
*/
@Test
public void testPostByForm(){
String url = "http://localhost:8080/testPostByForm";
// 设置请求头,x-www-form-urlencoded格式的数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//设置提交参数
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("userName", "张三");
map.add("userPwd", "123456");
// 组装请求体
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
//发起请求
GlobalResult responseBean = restTemplate.postForObject(url, request, GlobalResult.class);
System.out.println(responseBean.toString());
}
/**
* post表单提交
*/
@Test
public void testPostByForm2(){
String url = "http://localhost:8080/testPostByFormAndObj";
// 设置请求头,x-www-form-urlencoded格式的数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//设置提交参数
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("userName", "张三");
map.add("userPwd", "123456");
// 组装请求体
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
//发起请求
GlobalResult responseBean = restTemplate.postForObject(url, request, GlobalResult.class);
System.out.println(responseBean.toString());
}
/**
* post请求JSON格式
*/
@Test
public void testPostByJson(){
String url = "http://localhost:8080/testPostByJson";
UserReq request = new UserReq();
request.setUserName("张三");
request.setUserPwd("123456");
//String类型接收响应结果JSON字符串
GlobalResult responseBean = restTemplate.postForObject(url, request, GlobalResult.class);
System.out.println(responseBean.toString());
}
/**
* put请求JSON格式
*/
@Test
public void testPutByJson(){
String url = "http://localhost:8080/testPutByJson";
UserReq userReq = new UserReq();
userReq.setUserName("张三");
userReq.setUserPwd("123456789");
//put请求
restTemplate.put(url, userReq);
}
/**
* delete请求
*/
@Test
public void testDeleteByJson(){
String url = "http://localhost:8080/testDeleteByJson";
//delete请求
restTemplate.delete(url);
}
/**
* 重定向,post请求
*/
@Test
public void testPostByLocation(){
String url = "http://localhost:8080/testPostByLocation";
UserReq request = new UserReq();
request.setUserName("张三");
request.setUserPwd("123456789");
//返回跳转url
String s = restTemplate.postForObject(url, request, String.class);
System.out.println(s);
URI uri = restTemplate.postForLocation(url, request);
System.out.println(uri.toString());
}
/**
* 文件上传,post请求
*/
@Test
public void upload(){
//需要上传的文件
String filePath = "/home/file/Downloads/test.jpg";
//请求地址
String url = "http://localhost:8080/upload";
// 设置请求头,multipart/form-data格式的数据
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//设置参数
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
param.add("uploadFile", new FileSystemResource(new File(filePath)));
//服务端如果接受额外参数,可以传递
param.add("userName", "张三");
// 请求体
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(param, headers);
//发起请求
GlobalResult responseBean = restTemplate.postForObject(url, request, GlobalResult.class);
System.out.println(responseBean.toString());
}
/**
* 小文件下载
* @throws IOException
*/
@Test
public void downloadFile() throws IOException {
String userName = "张三";
String fileName = "b4f9fabb-213f-4017-aaa0-9470de31864e.jpg";
//请求地址
String url = "http://localhost:8080/downloadFile/{1}/{2}";
//发起请求
ResponseEntity<byte[]> rsp = restTemplate.getForEntity(url, byte[].class, userName,fileName);
System.out.println("文件下载请求结果状态码:" + rsp.getStatusCode());
// 保存到本地
String targetPath = "/home/file/Downloads/" + fileName;
Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody(), "未获取到下载文件"));
}
/**
* 大文件下载
* @throws IOException
*/
@Test
public void downloadBigFile() throws IOException {
String userName = "张三";
String fileName = "b4f9fabb-213f-4017-aaa0-9470de31864e.jpg";
//请求地址
String url = "http://localhost:8080/downloadFile/{1}/{2}";
//定义请求头的接收类型
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
//对响应进行流式处理而不是将其全部加载到内存中
String targetPath = "/home/file/Downloads/" + fileName;
restTemplate.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
return null;
}, userName, fileName);
}
}