RestTemplate
spring cloud
# 使用
# 上传文件
- 从请求头获取文件数据
private MultiValueMap<String, Object> parseMultipartRequest(HttpServletRequest request) {
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
if (request instanceof MultipartRequest) {
MultipartRequest multipartRequest = (MultipartRequest) request;
for (Map.Entry<String, List<MultipartFile>> entry : multipartRequest.getMultiFileMap().entrySet()) {
for (MultipartFile file : entry.getValue()) {
multiValueMap.add(entry.getKey(), file.getResource());
}
}
}
return CollectionUtils.isEmpty(multiValueMap) ? null : multiValueMap;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- RestTemplate请求通用类
@Slf4j
@Component
public class RestTemplateHelper {
private static final Pattern FORM_FEED_PATTERN = Pattern.compile("\f");
private static final Pattern COLON_PATTERN = Pattern.compile(":");
@Autowired
private ObjectMapper objectMapper;
@Resource(name = "domainFunctionRestTemplate")
private RestTemplate restTemplate;
/**
* http请求
*
* @param uriString 请求路径
* @param httpMethod 请求方法类型
* @param headerMultiValueMap 请求头
* @param paramMultiValueMap 请求参数
* @param contentLength HTTP消息实体的传输长度(请求头Content-Length)
* @param contentType 数据类型(请求头Content-Type)
* @param body 请求体
* @param <T> 请求体类型
* @return 响应结果的封装类
*/
public <T> ResponseEntity<byte[]> request(
String uriString, HttpMethod httpMethod, MultiValueMap<String, String> headerMultiValueMap,
MultiValueMap<String, String> paramMultiValueMap, Long contentLength, MediaType contentType, T body) {
// 拼接请求参数到url上
URI uri = buildUriWithQueryParam(uriString, paramMultiValueMap);
RequestEntity.BodyBuilder requestEntityBuilder = RequestEntity.method(httpMethod, uri);
// 将用户传的请求头进行透传
if (!CollectionUtils.isEmpty(headerMultiValueMap)) {
for (Map.Entry<String, List<String>> entry : headerMultiValueMap.entrySet()) {
requestEntityBuilder.header(entry.getKey(), entry.getValue().toArray(new String[0]));
}
}
RequestEntity<?> requestEntity = requestEntityBuilder.build();
// 如果请求是POST、PUT、DELETE、PATCH支持请求体的,则将Content-Length、Content-Type、请求体进行透传
if (HttpMethod.POST.equals(httpMethod) || HttpMethod.PUT.equals(httpMethod) ||
HttpMethod.DELETE.equals(httpMethod) || HttpMethod.PATCH.equals(httpMethod)) {
if (contentLength != null) {
requestEntityBuilder.contentLength(contentLength);
}
if (contentType != null) {
requestEntityBuilder.contentType(contentType);
}
if (body != null) {
requestEntity = requestEntityBuilder.body(body);
}
}
// 记录请求日志
logRequestInfo(requestEntity);
// http请求
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<byte[]>() {
});
// 记录响应日志
logResponseInfo(responseEntity);
return responseEntity;
}
/**
* 参考org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper#getQueryString
*/
private URI buildUriWithQueryParam(String uri, MultiValueMap<String, String> paramsMultiValueMap) {
if (CollectionUtils.isEmpty(paramsMultiValueMap)) {
return UriComponentsBuilder.fromUriString(uri).build().toUri();
}
// 创建字符串拼接器,字符串以&进行拼接,拼接后字符串前缀为?,无后缀
StringJoiner paramPlaceholder = new StringJoiner("&", "?", "");
Map<String, Object> paramsMap = new HashMap<>(paramsMultiValueMap.size());
for (Map.Entry<String, List<String>> entry : paramsMultiValueMap.entrySet()) {
String paramName = entry.getKey();
int i = 0;
for (String paramValue : entry.getValue()) {
StringBuilder keyPair = new StringBuilder(paramName);
if (!Strings.isNullOrEmpty(paramValue)) {
String key = paramName;
if (key.contains("\f")) {
key = (FORM_FEED_PATTERN.matcher(key).replaceAll("\f\f"));
}
if (key.contains(":")) {
key = COLON_PATTERN.matcher(key).replaceAll("\f");
}
key = key + i;
paramsMap.put(key, paramValue);
keyPair.append("={");
keyPair.append(key);
keyPair.append("}");
}
paramPlaceholder.add(keyPair);
i++;
}
}
return UriComponentsBuilder.fromUriString(uri + paramPlaceholder).build(paramsMap);
}
private void logRequestInfo(RequestEntity<?> requestEntity) {
log.info("请求方法:{}", requestEntity.getMethod());
log.info("请求url:{}", requestEntity.getUrl());
log.info("请求头:{}", requestEntity.getHeaders());
if (requestEntity.hasBody()) {
byte[] body = new byte[]{};
if (requestEntity.getBody() instanceof byte[]) {
body = (byte[]) requestEntity.getBody();
} else {
try {
body = objectMapper.writeValueAsBytes(requestEntity.getBody());
} catch (JsonProcessingException e) {
log.error("数据转换异常: {}", requestEntity.getBody(), e);
}
}
log.info("请求体:{}", new String(body, StandardCharsets.UTF_8));
}
}
private void logResponseInfo(ResponseEntity<byte[]> responseEntity) {
log.info("响应码:{}", responseEntity.getStatusCodeValue());
log.info("响应头:{}", responseEntity.getHeaders());
if (responseEntity.getBody() != null) {
log.info("响应体:{}", new String(responseEntity.getBody(), StandardCharsets.UTF_8));
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
- 调用
ResponseEntity<byte[]> responseEntity = restTemplateHelper.request(
请求路径, 请求方法, 请求头, 请求参数, HTTP消息实体的传输长度, 数据类型, parseMultipartRequest(request)
);
1
2
3
2
3
参考:
https://www.baeldung.com/spring-rest-template-multipart-upload (opens new window)
https://stackoverflow.com/questions/26964688/multipart-file-upload-using-spring-rest-template-spring-web-mvc (opens new window)
# 下载文件如何获取数据
- 响应数据类型使用字节数组进行接收byte[]
# 处理HTTP状态码为400、500等错误码时,如何获取到其响应结果内容
/**
* 设置自定义异常处理器,RestTemplate默认对于4**或5**的状态码会认为异常
*/
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// 自定义ResponseErrorHandler
ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() {
@Override
public boolean hasError(@NonNull ClientHttpResponse clientHttpResponse) {
// 返回false,没有错误,不抛异常
return false;
}
@Override
public void handleError(@NonNull ClientHttpResponse clientHttpResponse) {
// hasError方法返回false,即没有异常,所以无需处理
}
};
return builder.errorHandler(responseErrorHandler).build();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
参考:
https://blog.csdn.net/Staba/article/details/124405234 (opens new window)