为了方便使用,这里我封装成一个工具类来静态调用RestTemplate
以下代码是基于SpringBoot2.4.2版本写的案例
需要配置的application.yml如下
server:
port: 7024
servlet:
context-path: /demo
session:
timeout: 30m #默认会话过期时间30分钟
encoding:
enabled: true
charset: UTF-8
force: true
tomcat:
uri-encoding: UTF-8
spring:
servlet:
multipart:
max-file-size: 50MB #单个文件的最大上限
max-request-size: 200MB #单个请求的文件总大小限制
location: ${user.home}/.${spring.application.name}/tempDir
application:
name: demo
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
logging:
file:
#最终的存储路径是: 系统用户目录/.应用名称/logs/端口号/spring.log
path: ${user.home}/.${spring.application.name}/logs/${server.port}
logback:
rollingpolicy:
max-file-size: 1MB
max-history: 7
pattern:
console: "%date %clr(%level) [${PID}] [%thread] [%magenta(%X{traceId})] %cyan(%logger{10}) [%file : %line] %msg%n"
file: "%date %level [${PID}] [%thread] [%X{traceId}] %logger{10} [%file : %line] %msg%n"
package cn.test.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class RestTemplateUtil {
public RestTemplateUtil() {
}
private static RestTemplate template;
static {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//http 读超时5s
factory.setReadTimeout(5000);
//http 连接超时5s
factory.setConnectTimeout(5000);
template = new RestTemplate(factory);
List<ClientHttpRequestInterceptor> interceptorList = new ArrayList<>();
interceptorList.add(new RestTemplateLogging());
template.setInterceptors(interceptorList);
}
/**
* get请求-无参数
*
* @param url 请求url,如http://localhost:7024/demo/lic/getCheckInfo
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @return T 返回对象 如String/ Map /Resp/Result
*
* 例:
* String s = RestTemplateUtil.doHttpGet(
* "http://localhost:7024/demo/lic/getCheckInfo",
* String.class);
*/
public static <T> T doSimpleHttpGet(String url, Class<T> responseType, Map<String, String> reqHeaderMap) {
return doGetHttp(url, responseType, new HashMap<>(), reqHeaderMap);
}
/**
* get请求-可替换参数url
*
* @param replaceUrl 可替换参数url 如http://localhost:7024/demo/t2/{v1}/{v2}
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param urlPathVars 要替换的参数项 ,类型可以是字符串或数字
* @return T 返回对象 如String/ Map /Resp/Result
*
* 例:
* Map s1 = RestTemplateUtil.doGetHttpPathVar(
* "http://localhost:7024/demo/t2/{v1}/{v2}",
* Map.class,
* "v1wer", "v2r23r");
*/
public static <T> T doGetHttpPathVar(String replaceUrl,
Class<T> responseType,
Object... urlPathVars) {
return template.getForObject(replaceUrl, responseType, urlPathVars);
}
/**
* get请求-url为QueryString形式
*
* @param qsUrl 请求url,如 http://localhost:7024/demo/t3?a={a}&b={b}
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param queryStringMap {a=e12, b=r23r}
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doGetHttpQueryString(String qsUrl,
Class<T> responseType,
Map<String, String> queryStringMap,
Map<String, String> reqHeaderMap) {
if (queryStringMap == null) {
queryStringMap = new HashMap<>();
}
return doGetHttp(qsUrl, responseType, queryStringMap, reqHeaderMap);
}
private static <T> T doGetHttp(String qsUrl,
Class<T> responseType,
Map<String, String> queryStringMap,
Map<String, String> reqHeaderMap) {
HttpHeaders httpHeaders = new HttpHeaders();
if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) {
for (String s : reqHeaderMap.keySet()) {
httpHeaders.add(s, reqHeaderMap.get(s));
}
}
HttpEntity<String> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<T> tResponseEntity = template.exchange(
qsUrl,
HttpMethod.GET,
httpEntity,
responseType,
queryStringMap);
return tResponseEntity.getBody();
}
/**
* post-body-json 形式的请求
*
* @param url 请求url,如 http://localhost:7024/demo/t5
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param reqJson json字符串 如: {"macAddress":"8C:EC:4B:55:0E:EC","version":"v2123rt"}
* @param reqHeaderMap 可选的请求头
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doPostHttpJsonBody(String url,
Class<T> responseType,
String reqJson,
Map<String, String> reqHeaderMap) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) {
for (String s : reqHeaderMap.keySet()) {
httpHeaders.add(s, reqHeaderMap.get(s));
}
}
HttpEntity<String> httpEntity = new HttpEntity<>(reqJson, httpHeaders);
return template.postForObject(url, httpEntity, responseType);
}
/**
* post-formData 形式的请求
*
* @param url 请求url,如 http://localhost:7024/demo/t4
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param formDataMap {a=e12, b=r23r,c=123,d=true}
* @param reqHeaderMap 可选的请求头
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doPostHttpFormData(String url,
Class<T> responseType,
Map<String, Object> formDataMap,
Map<String, String> reqHeaderMap) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
//可选的请求头
if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) {
for (String s : reqHeaderMap.keySet()) {
httpHeaders.add(s, reqHeaderMap.get(s));
}
}
//构建填充formData
MultiValueMap<String, Object> formDataParam = new LinkedMultiValueMap<>();
if (formDataMap != null && !formDataMap.isEmpty()) {
for (String key : formDataMap.keySet()) {
formDataParam.add(key, formDataMap.get(key));
}
}
HttpEntity<MultiValueMap<String, Object>> httpEntity =
new HttpEntity<>(formDataParam, httpHeaders);
return template.postForObject(url, httpEntity, responseType);
}
/**
* post-上传MultipartFile文件
*
* @param url 请求url,如 http://localhost:7024/demo/t6
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param file java File 对象
* @param reqHeaderMap 可选的请求头
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doPostHttpUploadFile(String url,
Class<T> responseType,
File file,
Map<String, String> reqHeaderMap) {
Map<String, Object> formDataMap = new HashMap<>();
//支持传输 MultipartFile
formDataMap.put("file", new FileSystemResource(file));
return doPostHttpFormData(url, responseType, formDataMap, reqHeaderMap);
}
/**
* post-body-binary 二进制流 上传
* @param url 请求url,如 http://localhost:7024/demo/t62
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param file java File 对象
* @return T 返回对象 如String/ Map /Resp/Result
* @throws IOException
*/
public static <T> T doPostHttpBinaryStream(String url,
Class<T> responseType,
File file) throws IOException {
HttpHeaders httpHeaders = new HttpHeaders();
//固定请求头
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.add("Content-Disposition", file.getName());
//file转byte[] 字节流
String absolutePath = file.getAbsolutePath();
Path path = Paths.get(absolutePath);
byte[] bytes = Files.readAllBytes(path);
HttpEntity<byte[]> httpEntity = new HttpEntity<>(bytes, httpHeaders);
return template.postForObject(url, httpEntity, responseType);
}
/**
* put请求,常用于 更新(修改)已存在的数据
*
* @param url 请求url,如 http://localhost:7024/demo/t7
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param reqJson 实际开发中put请求一般传json参数,json里要有唯一键如id
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doSimplePutJson(String url,
Class<T> responseType,
String reqJson) {
return doPutJsonHttp(url, responseType, reqJson, null);
}
public static <T> T doPutJsonHttp(String url,
Class<T> responseType,
String reqJson,
Map<String, String> reqHeaderMap) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) {
for (String s : reqHeaderMap.keySet()) {
headers.add(s, reqHeaderMap.get(s));
}
}
ResponseEntity<T> tResponseEntity = template.exchange(
url,
HttpMethod.PUT,
new HttpEntity<>(reqJson, headers),
responseType,
new HashMap<>());
return tResponseEntity.getBody();
}
/**
* DELETE--单个删除请求
*
* @param url 可替换参数url 如http://localhost:7024/demo/t8/{id}
* @param oneUrlPathVar 对应id值
*/
public static void doDeleteHttpOnePathVar(String url, Object oneUrlPathVar) {
template.delete(url, oneUrlPathVar);
}
/**
* DELETE--动态条件删除请求
*
* @param url 请求url,如 http://localhost:7024/demo/t9?a={a}&b={b}
* @param queryStringMap {a=e12, b=r23r}
*/
public static void doDeleteWhereHttp(String url, Map<String, String> queryStringMap) {
template.delete(url, queryStringMap);
}
/**
* DELETE--批量删除请求
*
* @param url 请求url,如 http://localhost:7024/demo/t10
* @param responseType 返回类型 如String.class/ Map.class /Resp.class /Result.class
* @param reqJson 传json参数,json里要有唯一键数组如 {"ids":[1,2,3],"remark":"r23r","ts":1351311410}
* @param reqHeaderMap 可选的请求头
* @return T 返回对象 如String/ Map /Resp/Result
*/
public static <T> T doDeleteBatchByJson(String url,
Class<T> responseType,
String reqJson,
Map<String, String> reqHeaderMap) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
if (reqHeaderMap != null && !reqHeaderMap.isEmpty()) {
for (String s : reqHeaderMap.keySet()) {
headers.add(s, reqHeaderMap.get(s));
}
}
ResponseEntity<T> exchange = template.exchange(
url,
HttpMethod.DELETE,
new HttpEntity<>(reqJson, headers),
responseType,
new HashMap<>());
return exchange.getBody();
}
}
package cn.test.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Slf4j
public class RestTemplateLogging implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
log.info("req method:{},url:{}", request.getMethod(),request.getURI());
log.info("req headers:{}", request.getHeaders());
if (MediaType.APPLICATION_JSON.equals(request.getHeaders().getContentType())) {
log.info("req body:{}", new String(body, StandardCharsets.UTF_8));
}
ClientHttpResponse response = execution.execute(request, body);
log.info("resp statCode:{}", response.getStatusCode());
log.info("resp headers:{}", response.getHeaders());
return response;
}
}
package cn.test.web;
import cn.hutool.core.io.IoUtil;
import cn.test.lic.bean.CheckInfo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@RestController
public class TestController {
/**
* 含请求头参数的url ,必须用@RequestHeader 接收请求头
*
* @param upk
* @return
*/
@GetMapping("/t1")
public String t1(@RequestHeader("upk") String upk) {
System.err.println(upk);
return "ewr21r12r";
}
/**
* url路径变量 形式的http请求,必须用@PathVariable接收
*
* @param v1
* @param v2
* @return
*/
@GetMapping("/t2/{v1}/{v2}")
public TestResp t2(@PathVariable("v1") String v1,
@PathVariable("v2") String v2) {
TestResp build = TestResp.builder()
.v1(v1)
.v2(v2)
.build();
//{"v1":"re","v2":"r23r"}
return build;
}
/**
* queryString形式的get查询
* http://localhost:7024/demo/t3?a=e12&b=r23r
*
* @param a
* @param b
* @return
*/
@GetMapping("/t3")
public TestResp t3(@RequestParam String a,
@RequestParam String b) {
TestResp build = TestResp.builder()
.v1(a)
.v2(b)
.build();
return build;
}
/**
* post-formData 形式的请求
*
* @param a post-form参数
* @param b post-form参数
* @return
*/
@PostMapping("/t4")
public TestResp t4(@RequestParam String a,
@RequestParam String b,
int c,
boolean d) {
TestResp build = TestResp.builder()
.v1(a)
.v2(b).c(c).d(d)
.build();
return build;
}
/**
* post-body-json 形式的请求
*
* @param checkInfo post-body-json参数
* @return
*/
@PostMapping("/t5")
public CheckInfo t5(@RequestBody CheckInfo checkInfo) {
return checkInfo;
}
/**
* 文件上传------MultipartFile方式,本质还是formData 形式的请求
*
* @param file
* @param upk
* @return
* @throws IOException
*/
@PostMapping("/t6")
public String t6(@RequestPart("file") MultipartFile file,
@RequestHeader("upk") String upk) throws IOException {
System.out.println("upk:" + upk);
if (!file.isEmpty()) {
System.out.println(file.getName());
System.out.println(file.getOriginalFilename());
File file1 = new File("D:\\test7025\\" + file.getOriginalFilename());
file1.delete();
file.transferTo(file1);
}
return "ok!";
}
/**
* post-body-binary 二进制流 上传 ,需要请求方声明固定的ContentType=application/octet-stream
*
* @param request
* @param name
* @return
* @throws Exception
*/
@PostMapping("/t62")
public TestResp t62(HttpServletRequest request,
@RequestHeader("Content-Disposition") String name) throws Exception {
System.out.println(name);
ServletInputStream inputStream = request.getInputStream();
File file1 = new File("D:\\test7025\\" + name);
if (!file1.exists()) {
file1.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file1);
IoUtil.copy(inputStream, fos);
IoUtil.closeIfPosible(inputStream);
IoUtil.closeIfPosible(fos);
TestResp build = TestResp.builder()
.v1("f3rtf23t")
.v2("bsft23gf3g2")
.build();
return build;
}
/**
* put +传json 的请求, 常用于修改某个数据
*
* @param req TestReq ,一般要规定json里的唯一键必填,如id
* @return TestReq
*/
@PutMapping("/t7")
public TestReq t7(@RequestBody @Validated TestReq req) {
System.out.println(req);
return req;
}
/**
* Delete请求
* restful形式 删除单条数据,一般传数字id
*
* @param id
*/
@DeleteMapping("/t8/{id}")
public void t8(@PathVariable("id") Long id) {
System.err.println(id);
}
/**
* Delete请求
* 按多个条件删除数据,条件一般要必填
*
* @param a
* @param b
*/
@DeleteMapping("/t9")
public void t9(@RequestParam String a,
@RequestParam String b) {
System.err.println(a);
System.err.println(b);
}
/**
* Delete请求
* 批量删除数据,一般至少要提供ids数组
*
* @param req json里ids数组必填
* @return
*/
@DeleteMapping("/t10")
public Test2Req t10(@RequestBody Test2Req req) {
System.err.println(req);
return req;
}
}
package cn.test.web;
import lombok.Data;
@Data
public class Test2Req {
private Long[] ids;
private String remark;
}
package cn.test.web;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class TestReq {
@NotNull
private Long id;
private String name;
private String remark;
}
package cn.test.web;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TestResp {
private String v1;
private String v2;
private int c;
private boolean d;
}
package cn.test;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.test.lic.api.CheckInfoResp;
import cn.test.lic.api.ResultVO;
import cn.test.util.JacksonUtil;
import cn.test.util.RestTemplateUtil;
import cn.test.web.Test2Req;
import cn.test.web.TestReq;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@SpringBootTest
public class LicClientDemoAppTests {
@Test
void test1() throws IOException {
HashMap<String, String> reqHeaderMap = new HashMap<>();
reqHeaderMap.put("upk","ryju56u");
System.err.println("----=-=-=--------------===");
String s = RestTemplateUtil.doSimpleHttpGet(
"http://localhost:7024/demo/t1",
String.class,reqHeaderMap);
System.out.println(s);
System.err.println("----=-=-=--------------===");
ResultVO resultVO = RestTemplateUtil.doSimpleHttpGet(
"http://localhost:7024/demo/lic/getCheckInfo",
ResultVO.class,reqHeaderMap);
CheckInfoResp content = Convert.convert(CheckInfoResp.class,resultVO.getContent());
System.out.println(content);
System.err.println("----=-=-=--------------===");
Map s1 = RestTemplateUtil.doGetHttpPathVar(
"http://localhost:7024/demo/t2/{v1}/{v2}",
Map.class,
"v1wer", "v2r23r");
System.out.println(s1);
System.err.println("----=-=-=--------------===");
HashMap<String, String> sspMap = new HashMap<>();
sspMap.put("a","r23r");
sspMap.put("b","wer23r");
String m1 = RestTemplateUtil.doGetHttpQueryString(
"http://localhost:7024/demo/t3?a={a}&b={b}",
String.class,
sspMap,reqHeaderMap);
System.out.println(m1);
System.err.println("----=-=-=--------------===");
HashMap<String, Object> reqMap = new HashMap<>();
reqMap.put("version","v2123rt");
reqMap.put("macAddress","8C:EC:4B:55:0E:EC");
String json = JacksonUtil.obj2String(reqMap);
String t = RestTemplateUtil.doPostHttpJsonBody(
"http://localhost:7024/demo/t5",
String.class, json,null);
System.out.println(t);
System.err.println("----=-=-=--------------===");
HashMap<String, Object> formDataReq = new HashMap<>();
formDataReq.put("a","v2123rt");
formDataReq.put("b","8C:EC:4B:55:0E:EC");
formDataReq.put("c",123);
formDataReq.put("d",true);
String s2 = RestTemplateUtil.doPostHttpFormData(
"http://localhost:7024/demo/t4",
String.class,
formDataReq, null);
System.out.println(s2);
System.err.println("----=-=-=--------------===");
//formData文件上传
String s3 = RestTemplateUtil.doPostHttpUploadFile(
"http://localhost:7024/demo/t6",
String.class,
new File("E:\\lay2023\\vitevue2023-know-wiki-frontend.rar"),
reqHeaderMap);
System.out.println(s3);
System.err.println("----=-=-=--------------===");
//body-binary二进制流上传
String s325 = RestTemplateUtil.doPostHttpBinaryStream(
"http://localhost:7024/demo/t62",
String.class,
new File("E:\\lay2023\\vitevue2023-know-wiki-frontend.rar")
);
System.err.println(s325);
System.err.println("----=-=-=--------------===");
TestReq req = new TestReq();
req.setId(123L);
req.setName("ert23t");
req.setRemark("dhg3t4te");
String s4 = RestTemplateUtil.doSimplePutJson("http://localhost:7024/demo/t7",
String.class, JacksonUtil.obj2String(req));
System.err.println(s4);
System.err.println("----=-=-=--------------===");
RestTemplateUtil.doDeleteHttpOnePathVar(
"http://localhost:7024/demo/t8/{id}",
321);
System.err.println("----=-=-=--------------===");
RestTemplateUtil.doDeleteWhereHttp(
"http://localhost:7024/demo/t9?a={a}&b={b}",
sspMap);
System.err.println("----=-=-=--------------===");
Test2Req req2 = new Test2Req();
Long[] ids = {321L,341L};
req2.setIds(ids);
req2.setRemark("dhg3t4te");
String s5 = RestTemplateUtil.doDeleteBatchByJson(
"http://localhost:7024/demo/t10",
String.class,
JacksonUtil.obj2String(req2),
null);
System.out.println(s5);
}
}