新增 txw-common 公共模块
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
04d32e93df
commit
f96d815796
38
txw-common/.gitignore
vendored
Normal file
38
txw-common/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
1
txw-common/README.md
Normal file
1
txw-common/README.md
Normal file
@ -0,0 +1 @@
|
||||
test
|
||||
78
txw-common/pom.xml
Normal file
78
txw-common/pom.xml
Normal file
@ -0,0 +1,78 @@
|
||||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-dependencies</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>txw-common</artifactId>
|
||||
<groupId>com.css.txw</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>txw-common</description>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<!--必须与 settings.xml 的 id 一致-->
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.css.ggzc</groupId>
|
||||
<artifactId>ggzc-framework-starter-cache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
61
txw-common/settings.xml
Normal file
61
txw-common/settings.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<!--<localRepository>[本地maven库目录]</localRepository>-->
|
||||
<!-- omitted xml -->
|
||||
<!-- 请妥善保管好您的配置,不要随意分享给他人 -->
|
||||
<servers>
|
||||
<server>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<username>coding-user</username>
|
||||
<password>coding-pwd</password>
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
<!-- omitted xml -->
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>Repository Proxy</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<!--必须与 settings.xml 的 id 一致-->
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<mirrors>
|
||||
<mirror>
|
||||
<id>codingcorp-qyd_repo-mvn_public</id>
|
||||
<!-- 此配置避免了本仓库制品的拉取流量被切换到腾讯云镜像源,保证您在使用镜像加速的同时可以从本仓库拉取制品 -->
|
||||
<mirrorOf>central</mirrorOf>
|
||||
<name>mvn_public</name>
|
||||
<url>http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/</url>
|
||||
</mirror>
|
||||
</mirrors>
|
||||
</settings>
|
||||
@ -0,0 +1,30 @@
|
||||
package com.css.txw.common.configuration;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @Description: 短信配置
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
@Data
|
||||
@RefreshScope
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "css.txw.sms")
|
||||
public class SMSConfig {
|
||||
|
||||
private String host;
|
||||
|
||||
//app:请求应用的唯一标识,例如:OA
|
||||
private String app;
|
||||
|
||||
//key:双方系统约定的密钥
|
||||
private String key;
|
||||
|
||||
//短信内容模版
|
||||
private String template;
|
||||
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.css.txw.common.configuration;
|
||||
|
||||
/**
|
||||
* @Description: 短信服务相关
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
public class SMSConstant {
|
||||
public static final String SEND_SM_URI = "/nbsgd/messageApi/smsmessage/send";
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.css.txw.common.configuration;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@AutoConfiguration
|
||||
@ComponentScan("com.css.txw.common")
|
||||
public class TxwCommonConfiguration {
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package com.css.txw.common.net;
|
||||
|
||||
import cn.hutool.http.Header;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class HttpHutoolImpl implements IHttpService {
|
||||
|
||||
public final static String CONTENT_TYPE_JSON = "application/json";
|
||||
public final static String CONTENT_TYPE_FORM = "multipart/form-data;";
|
||||
public final static String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36";
|
||||
public final static String ACCEPT = "application/json, text/plain, */*";
|
||||
|
||||
public HttpResponse get(String url) {
|
||||
HttpRequest request = HttpUtil.createGet(url);
|
||||
return this.executeReq(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse get(String url, Map<String, Object> params) {
|
||||
HttpRequest request = HttpUtil.createGet(url);
|
||||
request.form(params);
|
||||
return this.executeReq(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse postForm(String url, Map<String, Object> form) {
|
||||
HttpRequest request = HttpUtil.createPost(url);
|
||||
request.form(form);
|
||||
return this.executeReq(request, CONTENT_TYPE_FORM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse postForm(String url, Map<String, Object> form, Map<String, File> files) {
|
||||
HttpRequest request = HttpUtil.createPost(url);
|
||||
request.form(form);
|
||||
if (null != files) {
|
||||
for (String key : files.keySet()) {
|
||||
request.form(key, files.get(key), files.get(key).getName());
|
||||
}
|
||||
request.timeout(1000 * 60);
|
||||
}
|
||||
return this.executeReq(request, CONTENT_TYPE_FORM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T postJson(String url, String body, Class<T> resType) {
|
||||
HttpRequest request = HttpUtil.createPost(url);
|
||||
if (StringUtils.isNotBlank(body)) {
|
||||
request.body(body);
|
||||
}
|
||||
try {
|
||||
HttpResponse response = this.executeReq(request);
|
||||
if (response.isOk()) {
|
||||
String resBody = response.body();
|
||||
log.info("Hutool http response body: {}", resBody);
|
||||
return new Gson().fromJson(resBody, resType);
|
||||
} else {
|
||||
log.info("请求失败,状态码:{}", response.getStatus());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("error:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private HttpResponse executeReq(HttpRequest request) {
|
||||
return this.executeReq(request, CONTENT_TYPE_JSON);
|
||||
}
|
||||
|
||||
private HttpResponse executeReq(HttpRequest request,String contentType) {
|
||||
request.contentType(contentType).header(Header.USER_AGENT, USER_AGENT).header(Header.ACCEPT, ACCEPT);
|
||||
return request.execute();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.css.txw.common.net;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IHttpService {
|
||||
|
||||
HttpResponse get(String url, Map<String, Object> params);
|
||||
|
||||
HttpResponse postForm(String url, Map<String, Object> form);
|
||||
|
||||
HttpResponse postForm(String url, Map<String, Object> form, Map<String, File> files);
|
||||
|
||||
<T> T postJson(String url, String body, Class<T> resType);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.css.txw.common.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ExcelVerifyInfo {
|
||||
private String errorMsg;
|
||||
private Integer rowNum;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.css.txw.common.pojo.dto.sms;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 发送短信验证码,根据配置模版格式发送验证码
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
@Data
|
||||
public class SMCaptchaDTO {
|
||||
//接收手机号码 "1311111111,1352222222"
|
||||
private String receiveMobile;
|
||||
//验证码
|
||||
private String captcha;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.css.txw.common.pojo.dto.sms;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 短信发送报文
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
@Data
|
||||
public class SMSReqDTO {
|
||||
//接收手机号码 "1311111111,1352222222"
|
||||
private String receiveMobile;
|
||||
//短信内容
|
||||
private String content;
|
||||
//发送时间, 自定义发送时间,空或小于当前时间立即发送
|
||||
private String sendTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.css.txw.common.pojo.dto.sms;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description: 短信服务响应报文
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
@Data
|
||||
public class SMSResDTO<T> {
|
||||
private String code;//返回代码值
|
||||
private String type;//枚举型,包括:success、error
|
||||
private String token;//请求服务时传递的唯一标识UUID
|
||||
private String message;//返回消息
|
||||
private T data;//返回数据内容
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.css.txw.common.service;
|
||||
|
||||
import com.css.txw.common.pojo.dto.sms.SMCaptchaDTO;
|
||||
import com.css.txw.common.pojo.dto.sms.SMSResDTO;
|
||||
|
||||
public interface ISMService {
|
||||
|
||||
SMSResDTO sendCaptcha(String phone, String code);
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.css.txw.common.service.impl;
|
||||
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.css.txw.common.configuration.SMSConfig;
|
||||
import com.css.txw.common.configuration.SMSConstant;
|
||||
import com.css.txw.common.net.IHttpService;
|
||||
import com.css.txw.common.pojo.dto.sms.SMSReqDTO;
|
||||
import com.css.txw.common.pojo.dto.sms.SMSResDTO;
|
||||
import com.css.txw.common.service.ISMService;
|
||||
import com.css.txw.common.util.TxwHttpUtils;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 短信服务
|
||||
* @Autor wujy
|
||||
* @Date 2025/11/21
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SMServiceImpl implements ISMService {
|
||||
|
||||
@Resource
|
||||
private SMSConfig config;
|
||||
@Resource
|
||||
private IHttpService httpService;
|
||||
|
||||
//发送短信验证码
|
||||
@Override
|
||||
public SMSResDTO sendCaptcha(String phone, String code) {
|
||||
//时间戳,如:1611472667681
|
||||
long timestamp = new Date().getTime();
|
||||
String app = config.getApp();
|
||||
//请求唯一标识,使用UUID
|
||||
String token = GyUtils.getUuid();
|
||||
//校验码,使用timestamp+app+token+key进行MD5加密后的字符再进行性一次加密最后形成校验码
|
||||
String vcode = DigestUtil.md5Hex(DigestUtil.md5Hex(timestamp + app + token + config.getKey()));
|
||||
String url = config.getHost() + SMSConstant.SEND_SM_URI + "?timestamp=" + timestamp + "&token=" + token +
|
||||
"&app=" + app + "&vcode=" + vcode;
|
||||
//构建报文
|
||||
String content = String.format(config.getTemplate(), code);
|
||||
SMSReqDTO smReqDTO = new SMSReqDTO();
|
||||
smReqDTO.setReceiveMobile(phone);
|
||||
smReqDTO.setContent(content);
|
||||
//发送
|
||||
SMSResDTO res = httpService.postJson(url, new Gson().toJson(smReqDTO), SMSResDTO.class);
|
||||
log.info("短信发送 Response {}, code:{} message:{}", res.getType(),res.getCode(), res.getMessage());
|
||||
return res;
|
||||
}
|
||||
|
||||
// 发送其他短信
|
||||
public String sendMsg(SMSReqDTO reqDTO) {
|
||||
// to do something
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,289 @@
|
||||
package com.css.txw.common.util;
|
||||
|
||||
import com.css.ggzc.framework.cache.utils.XtcsUtils;
|
||||
import com.css.ggzc.framework.common.util.gy.GyUtils;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.net.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 基于Spring Cloud Alibaba的HTTP工具类
|
||||
* 支持GET、POST、PUT、DELETE请求,兼容HTTP/HTTPS协议
|
||||
* 支持Nacos服务发现和负载均衡
|
||||
* 版本:Spring Cloud Alibaba 2021.0.6.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TxwHttpUtils {
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.info("SpringCloudAlibabaHttpUtil initialized successfully with Spring Cloud Alibaba 2021.0.6.0");
|
||||
}
|
||||
|
||||
// ========== GET请求方法 ==========
|
||||
|
||||
/**
|
||||
* GET请求 - 直接URL调用
|
||||
*/
|
||||
public <T> T get(String url, Class<T> responseType) {
|
||||
return get(url, null, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T get(String url, Map<String, Object> params, Class<T> responseType) {
|
||||
return get(url, params, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T get(String url, Map<String, Object> params, Class<T> responseType,
|
||||
Map<String, String> headers) {
|
||||
try {
|
||||
HttpEntity<?> entity = createHttpEntity(null, headers);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
buildUrlWithParams(url, params),
|
||||
HttpMethod.GET,
|
||||
entity,
|
||||
responseType
|
||||
);
|
||||
return handleResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("GET请求失败, url: {}", url, e);
|
||||
throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== POST请求方法 ==========
|
||||
|
||||
/**
|
||||
* POST请求 - 直接URL调用
|
||||
*/
|
||||
public <T> T post(String url, Object requestBody, Class<T> responseType) {
|
||||
return post(url, requestBody, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T post(String url, Object requestBody, Class<T> responseType,
|
||||
Map<String, String> headers) {
|
||||
try {
|
||||
HttpEntity<?> entity = createHttpEntity(requestBody, headers);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
entity,
|
||||
responseType
|
||||
);
|
||||
return handleResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("POST请求失败, url: {}", url, e);
|
||||
throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== PUT请求方法 ==========
|
||||
|
||||
/**
|
||||
* PUT请求 - 直接URL调用
|
||||
*/
|
||||
public <T> T put(String url, Object requestBody, Class<T> responseType) {
|
||||
return put(url, requestBody, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T put(String url, Object requestBody, Class<T> responseType,
|
||||
Map<String, String> headers) {
|
||||
try {
|
||||
HttpEntity<?> entity = createHttpEntity(requestBody, headers);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
entity,
|
||||
responseType
|
||||
);
|
||||
return handleResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("PUT请求失败, url: {}", url, e);
|
||||
throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== DELETE请求方法 ==========
|
||||
|
||||
/**
|
||||
* DELETE请求 - 直接URL调用
|
||||
*/
|
||||
public <T> T delete(String url, Class<T> responseType) {
|
||||
return delete(url, null, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T delete(String url, Map<String, Object> params, Class<T> responseType) {
|
||||
return delete(url, params, responseType, null);
|
||||
}
|
||||
|
||||
public <T> T delete(String url, Map<String, Object> params, Class<T> responseType,
|
||||
Map<String, String> headers) {
|
||||
try {
|
||||
HttpEntity<?> entity = createHttpEntity(null, headers);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
buildUrlWithParams(url, params),
|
||||
HttpMethod.DELETE,
|
||||
entity,
|
||||
responseType
|
||||
);
|
||||
return handleResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("DELETE请求失败, url: {}", url, e);
|
||||
throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 通用请求方法 ==========
|
||||
|
||||
/**
|
||||
* 通用请求方法
|
||||
*/
|
||||
public <T> T exchange(String url, HttpMethod method, Object requestBody,
|
||||
Map<String, String> headers, Class<T> responseType) {
|
||||
try {
|
||||
ResponseEntity<T> response;
|
||||
RestTemplate restTemplateWithProxy = createRestTemplateWithProxy();
|
||||
HttpEntity<?> entity = createHttpEntity(requestBody, headers);
|
||||
if (GyUtils.isNotNull(restTemplateWithProxy)) {
|
||||
response = restTemplateWithProxy.exchange(url, method, entity, responseType);
|
||||
} else {
|
||||
response = restTemplate.exchange(url, method, entity, responseType);
|
||||
}
|
||||
return handleResponse(response);
|
||||
} catch (Exception e) {
|
||||
log.error("{}请求失败, url: {}", method.name(), url, e);
|
||||
throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 辅助方法 ==========
|
||||
|
||||
/**
|
||||
* 构建带参数的URL
|
||||
*/
|
||||
private String buildUrlWithParams(String url, Map<String, Object> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return url;
|
||||
}
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder(url);
|
||||
boolean hasQuery = url.contains("?");
|
||||
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
if (entry.getValue() == null) continue;
|
||||
|
||||
if (!hasQuery) {
|
||||
urlBuilder.append("?");
|
||||
hasQuery = true;
|
||||
} else {
|
||||
urlBuilder.append("&");
|
||||
}
|
||||
|
||||
urlBuilder.append(entry.getKey())
|
||||
.append("=")
|
||||
.append(encodeParam(entry.getValue().toString()));
|
||||
}
|
||||
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数编码
|
||||
*/
|
||||
private String encodeParam(String param) {
|
||||
try {
|
||||
return java.net.URLEncoder.encode(param, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
log.warn("参数编码失败: {}", param, e);
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建HTTP实体
|
||||
*/
|
||||
private HttpEntity<?> createHttpEntity(Object requestBody, Map<String, String> headers) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
|
||||
// 设置默认头
|
||||
if (requestBody instanceof MultiValueMap) {
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
} else if (requestBody != null) {
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
// 添加自定义头
|
||||
if (headers != null) {
|
||||
headers.forEach(httpHeaders::add);
|
||||
}
|
||||
|
||||
return new HttpEntity<>(requestBody, httpHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理响应
|
||||
*/
|
||||
private <T> T handleResponse(ResponseEntity<T> response) {
|
||||
if (response.getStatusCode().is2xxSuccessful()) {
|
||||
return response.getBody();
|
||||
} else {
|
||||
String errorMsg = String.format("HTTP请求失败, 状态码: %d, 响应: %s",
|
||||
response.getStatusCodeValue(), response.getBody());
|
||||
log.error(errorMsg);
|
||||
throw new RuntimeException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为MultiValueMap(用于表单提交)
|
||||
*/
|
||||
public MultiValueMap<String, String> convertToFormData(Object obj) {
|
||||
try {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
Map<String, Object> map = objectMapper.convertValue(obj, new TypeReference<Map<String, Object>>() {});
|
||||
|
||||
map.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
formData.add(key, value.toString());
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
} catch (Exception e) {
|
||||
log.error("对象转换表单数据失败", e);
|
||||
throw new RuntimeException("对象转换失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
public RestTemplate createRestTemplateWithProxy() {
|
||||
// 设置代理
|
||||
Proxy proxy = XtcsUtils.getSystemHttpProxy();
|
||||
if (GyUtils.isNotNull(proxy)) {
|
||||
SimpleClientHttpRequestFactory requestFactory =
|
||||
new SimpleClientHttpRequestFactory();
|
||||
// 设置超时时间
|
||||
requestFactory.setConnectTimeout(5000);
|
||||
requestFactory.setReadTimeout(10000);
|
||||
requestFactory.setProxy(proxy);
|
||||
return new RestTemplate(requestFactory);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
com.css.txw.common.configuration.TxwCommonConfiguration
|
||||
@ -0,0 +1,37 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "css.txw.sms",
|
||||
"type": "com.css.txw.common.configuration.SMSConfig",
|
||||
"sourceType": "com.css.txw.common.configuration.SMSConfig"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "css.txw.sms.host",
|
||||
"type": "java.lang.String",
|
||||
"description": "short message service host",
|
||||
"sourceType": "com.css.txw.common.configuration.SMSConfig"
|
||||
},
|
||||
{
|
||||
"name": "css.txw.sms.app",
|
||||
"type": "java.lang.String",
|
||||
"description": "app name",
|
||||
"sourceType": "com.css.txw.common.configuration.SMSConfig"
|
||||
},
|
||||
{
|
||||
"name": "css.txw.sms.key",
|
||||
"type": "java.lang.String",
|
||||
"description": "app key",
|
||||
"sourceType": "com.css.txw.common.configuration.SMSConfig"
|
||||
},
|
||||
{
|
||||
"name": "css.txw.sms.template",
|
||||
"type": "java.lang.String",
|
||||
"description": "short message content template",
|
||||
"sourceType": "com.css.txw.common.configuration.SMSConfig"
|
||||
}
|
||||
],
|
||||
"hints": [
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user