2026-03-02 09:59:10 +08:00
|
|
|
|
package com.ruoyi.lsfx.util;
|
|
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
import com.ruoyi.lsfx.exception.LsfxApiException;
|
2026-03-04 16:20:07 +08:00
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
2026-03-03 14:51:46 +08:00
|
|
|
|
import jakarta.annotation.Resource;
|
2026-03-04 16:20:07 +08:00
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
2026-03-02 09:59:10 +08:00
|
|
|
|
import org.springframework.http.*;
|
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import org.springframework.util.LinkedMultiValueMap;
|
|
|
|
|
|
import org.springframework.util.MultiValueMap;
|
2026-03-03 09:35:27 +08:00
|
|
|
|
import org.springframework.web.client.RestClientException;
|
2026-03-02 09:59:10 +08:00
|
|
|
|
import org.springframework.web.client.RestTemplate;
|
2026-03-04 16:20:07 +08:00
|
|
|
|
import org.springframework.web.util.UriComponentsBuilder;
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* HTTP请求工具类
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Component
|
|
|
|
|
|
public class HttpUtil {
|
|
|
|
|
|
|
2026-03-04 16:20:07 +08:00
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
|
|
|
|
|
|
|
2026-03-02 09:59:10 +08:00
|
|
|
|
@Resource
|
|
|
|
|
|
private RestTemplate restTemplate;
|
|
|
|
|
|
|
2026-03-04 16:20:07 +08:00
|
|
|
|
@Resource
|
|
|
|
|
|
private ObjectMapper objectMapper;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送GET请求(带查询参数和请求头)
|
|
|
|
|
|
* @param url 请求URL
|
|
|
|
|
|
* @param params 查询参数
|
|
|
|
|
|
* @param headers 请求头
|
|
|
|
|
|
* @param responseType 响应类型
|
|
|
|
|
|
* @return 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public <T> T get(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 构建URL with查询参数
|
|
|
|
|
|
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
|
|
|
|
|
|
if (params != null && !params.isEmpty()) {
|
|
|
|
|
|
params.forEach((key, value) -> {
|
|
|
|
|
|
if (value != null) {
|
|
|
|
|
|
builder.queryParam(key, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String fullUrl = builder.toUriString();
|
|
|
|
|
|
log.debug("【HTTP GET】请求URL: {}", fullUrl);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建请求头
|
|
|
|
|
|
HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
|
|
|
if (headers != null) {
|
|
|
|
|
|
headers.forEach(httpHeaders::add);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构建请求实体
|
|
|
|
|
|
HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
|
|
|
|
|
|
|
|
|
|
|
|
// 执行GET请求
|
|
|
|
|
|
ResponseEntity<String> response = restTemplate.exchange(
|
|
|
|
|
|
fullUrl,
|
|
|
|
|
|
HttpMethod.GET,
|
|
|
|
|
|
entity,
|
|
|
|
|
|
String.class
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
log.debug("【HTTP GET】响应状态: {}", response.getStatusCode());
|
|
|
|
|
|
log.debug("【HTTP GET】响应内容: {}", response.getBody());
|
|
|
|
|
|
|
|
|
|
|
|
// 解析响应
|
|
|
|
|
|
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
|
|
|
|
|
|
return objectMapper.readValue(response.getBody(), responseType);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new LsfxApiException("GET请求失败: " + response.getStatusCode());
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
log.error("【HTTP GET】请求异常: url={}, error={}", url, e.getMessage(), e);
|
|
|
|
|
|
throw new LsfxApiException("GET请求异常: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-02 09:59:10 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 发送GET请求(带请求头)
|
|
|
|
|
|
* @param url 请求URL
|
|
|
|
|
|
* @param headers 请求头
|
|
|
|
|
|
* @param responseType 响应类型
|
|
|
|
|
|
* @return 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public <T> T get(String url, Map<String, String> headers, Class<T> responseType) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
try {
|
|
|
|
|
|
HttpHeaders httpHeaders = createHeaders(headers);
|
|
|
|
|
|
HttpEntity<Void> requestEntity = new HttpEntity<>(httpHeaders);
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
ResponseEntity<T> response = restTemplate.exchange(
|
|
|
|
|
|
url, HttpMethod.GET, requestEntity, responseType
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.getStatusCode().is2xxSuccessful()) {
|
|
|
|
|
|
throw new LsfxApiException("API调用失败,HTTP状态码: " + response.getStatusCode());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
T body = response.getBody();
|
|
|
|
|
|
if (body == null) {
|
|
|
|
|
|
throw new LsfxApiException("API返回数据为空");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return body;
|
|
|
|
|
|
} catch (RestClientException e) {
|
|
|
|
|
|
throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 09:59:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送POST请求(JSON格式,带请求头)
|
|
|
|
|
|
* @param url 请求URL
|
|
|
|
|
|
* @param request 请求对象
|
|
|
|
|
|
* @param headers 请求头
|
|
|
|
|
|
* @param responseType 响应类型
|
|
|
|
|
|
* @return 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public <T> T postJson(String url, Object request, Map<String, String> headers, Class<T> responseType) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
try {
|
|
|
|
|
|
HttpHeaders httpHeaders = createHeaders(headers);
|
|
|
|
|
|
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
|
|
|
|
|
|
|
|
|
|
|
HttpEntity<Object> requestEntity = new HttpEntity<>(request, httpHeaders);
|
|
|
|
|
|
|
|
|
|
|
|
ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.getStatusCode().is2xxSuccessful()) {
|
|
|
|
|
|
throw new LsfxApiException("API调用失败,HTTP状态码: " + response.getStatusCode());
|
|
|
|
|
|
}
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
T body = response.getBody();
|
|
|
|
|
|
if (body == null) {
|
|
|
|
|
|
throw new LsfxApiException("API返回数据为空");
|
|
|
|
|
|
}
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
return body;
|
|
|
|
|
|
} catch (RestClientException e) {
|
|
|
|
|
|
throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 09:59:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 14:51:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 发送POST请求(multipart/form-data格式,带请求头)
|
|
|
|
|
|
* 用于提交表单数据(非文件上传场景)
|
|
|
|
|
|
* @param url 请求URL
|
|
|
|
|
|
* @param params 表单参数
|
|
|
|
|
|
* @param headers 请求头
|
|
|
|
|
|
* @param responseType 响应类型
|
|
|
|
|
|
* @return 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public <T> T postFormData(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
HttpHeaders httpHeaders = createHeaders(headers);
|
|
|
|
|
|
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
|
|
|
|
|
|
|
|
|
|
|
|
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
|
|
|
|
|
if (params != null) {
|
|
|
|
|
|
params.forEach(body::add);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, httpHeaders);
|
|
|
|
|
|
|
|
|
|
|
|
ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.getStatusCode().is2xxSuccessful()) {
|
|
|
|
|
|
throw new LsfxApiException("API调用失败,HTTP状态码: " + response.getStatusCode());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
T responseBody = response.getBody();
|
|
|
|
|
|
if (responseBody == null) {
|
|
|
|
|
|
throw new LsfxApiException("API返回数据为空");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return responseBody;
|
|
|
|
|
|
} catch (RestClientException e) {
|
|
|
|
|
|
throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-02 09:59:10 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 上传文件(Multipart格式)
|
|
|
|
|
|
* @param url 请求URL
|
|
|
|
|
|
* @param params 参数(包含文件)
|
|
|
|
|
|
* @param headers 请求头
|
|
|
|
|
|
* @param responseType 响应类型
|
|
|
|
|
|
* @return 响应对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public <T> T uploadFile(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
|
2026-03-03 09:35:27 +08:00
|
|
|
|
try {
|
|
|
|
|
|
HttpHeaders httpHeaders = createHeaders(headers);
|
|
|
|
|
|
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
|
|
|
|
|
if (params != null) {
|
|
|
|
|
|
params.forEach(body::add);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, httpHeaders);
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);
|
2026-03-02 09:59:10 +08:00
|
|
|
|
|
2026-03-03 09:35:27 +08:00
|
|
|
|
if (!response.getStatusCode().is2xxSuccessful()) {
|
|
|
|
|
|
throw new LsfxApiException("文件上传失败,HTTP状态码: " + response.getStatusCode());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
T responseBody = response.getBody();
|
|
|
|
|
|
if (responseBody == null) {
|
|
|
|
|
|
throw new LsfxApiException("文件上传返回数据为空");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return responseBody;
|
|
|
|
|
|
} catch (RestClientException e) {
|
|
|
|
|
|
throw new LsfxApiException("文件上传请求失败: " + e.getMessage(), e);
|
|
|
|
|
|
}
|
2026-03-02 09:59:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建请求头
|
|
|
|
|
|
* @param headers 请求头Map
|
|
|
|
|
|
* @return HttpHeaders对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
private HttpHeaders createHeaders(Map<String, String> headers) {
|
|
|
|
|
|
HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
|
|
|
if (headers != null && !headers.isEmpty()) {
|
|
|
|
|
|
headers.forEach(httpHeaders::set);
|
|
|
|
|
|
}
|
|
|
|
|
|
return httpHeaders;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|