新增 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