暂时提交 三方接口

feasure
lld 2026-01-01 12:27:52 +08:00
parent 0514bad75c
commit caa4a24b53
18 changed files with 428 additions and 139 deletions

View File

@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;

View File

@ -19,6 +19,17 @@
<groupId>com.agri</groupId> <groupId>com.agri</groupId>
<artifactId>agri-common</artifactId> <artifactId>agri-common</artifactId>
</dependency> </dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.agri</groupId>
<artifactId>agri-generator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,33 @@
package com.agri.api.controller;
import com.agri.api.util.HttpJsonUtil;
import com.agri.generator.dto.ApiConfigDTO;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
public class TestController {
/**
*
*/
@PostMapping("/test-third-api")
public String testThirdApi(@Valid @RequestBody ApiConfigDTO apiConfig) {
try {
// 调用三方GET接口示例
// String result = HttpJsonUtil.doGet("http://third-party-api.com/api/test?name=test", String.class);
// 调用三方POST JSON接口示例
String result = HttpJsonUtil.doPostJson(
"https://api.wl1688.net/iotc/getway",
apiConfig,
String.class
);
return "调用三方接口成功,响应:" + result;
} catch (Exception e) {
return "调用三方接口失败:" + e.getMessage();
}
}
}

View File

@ -0,0 +1,12 @@
package com.agri.api.domain;
import lombok.Data;
@Data
public class ApiMain {
private Integer code;
private Object data;
private String msg;
}

View File

@ -0,0 +1,163 @@
package com.agri.api.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* HTTP JSONJDK 8
*/
public class HttpJsonUtil {
private static final Logger log = LoggerFactory.getLogger(HttpJsonUtil.class);
// JSON序列化/反序列化工具需引入jackson依赖
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
// 默认超时时间(毫秒)
private static final int DEFAULT_CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
private static final int DEFAULT_READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
/**
* POST JSON
* @param url
* @param requestBody JavaJSON
* @param headers tokenContent-Type
* @param responseType
* @return
*/
public static <T> T doPostJson(String url, Object requestBody, Map<String, String> headers, Class<T> responseType) {
try {
// 1. 构建连接
HttpURLConnection conn = getHttpURLConnection(url, "POST");
// 2. 设置请求头
setHeaders(conn, headers);
// 3. 写入JSON请求体
writeRequestBody(conn, requestBody);
// 4. 获取响应
return getResponse(conn, responseType);
} catch (Exception e) {
log.error("POST JSON请求失败url={}", url, e);
throw new RuntimeException("调用三方接口失败:" + e.getMessage());
}
}
/**
* GETURL
* @param url http://xxx/api?name=test
* @param headers
* @param responseType
* @return
*/
public static <T> T doGet(String url, Map<String, String> headers, Class<T> responseType) {
try {
// 1. 构建连接
HttpURLConnection conn = getHttpURLConnection(url, "GET");
// 2. 设置请求头
setHeaders(conn, headers);
// 3. 获取响应
return getResponse(conn, responseType);
} catch (Exception e) {
log.error("GET请求失败url={}", url, e);
throw new RuntimeException("调用三方接口失败:" + e.getMessage());
}
}
/**
* HTTP
*/
private static HttpURLConnection getHttpURLConnection(String url, String method) throws IOException {
URL apiUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
// 设置请求方法
conn.setRequestMethod(method);
// 允许输入输出POST需要
conn.setDoInput(true);
conn.setDoOutput(true);
// 设置超时
conn.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
conn.setReadTimeout(DEFAULT_READ_TIMEOUT);
// 禁用缓存
conn.setUseCaches(false);
return conn;
}
/**
*
*/
private static void setHeaders(HttpURLConnection conn, Map<String, String> headers) {
// 默认Content-Type
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Accept", "application/json");
// 自定义请求头
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
/**
* JSON
*/
private static void writeRequestBody(HttpURLConnection conn, Object requestBody) throws IOException {
if (requestBody == null) {
return;
}
try (OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8)) {
// 将Java对象转为JSON字符串
String jsonBody = OBJECT_MAPPER.writeValueAsString(requestBody);
log.debug("HTTP请求体{}", jsonBody);
writer.write(jsonBody);
writer.flush();
}
}
/**
*
*/
private static <T> T getResponse(HttpURLConnection conn, Class<T> responseType) throws IOException {
int responseCode = conn.getResponseCode();
// 处理成功响应200-299
if (responseCode >= 200 && responseCode < 300) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder responseStr = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
responseStr.append(line);
}
log.debug("HTTP响应结果{}", responseStr);
// 将JSON字符串转为Java对象
return OBJECT_MAPPER.readValue(responseStr.toString(), responseType);
}
} else {
// 处理错误响应
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8))) {
StringBuilder errorStr = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
errorStr.append(line);
}
log.error("HTTP请求错误响应码={},错误信息={}", responseCode, errorStr);
throw new RuntimeException("三方接口返回错误:响应码=" + responseCode + ",信息=" + errorStr);
}
}
}
// 重载方法无自定义请求头的POST
public static <T> T doPostJson(String url, Object requestBody, Class<T> responseType) {
return doPostJson(url, requestBody, null, responseType);
}
// 重载方法无自定义请求头的GET
public static <T> T doGet(String url, Class<T> responseType) {
return doGet(url, null, responseType);
}
}

View File

@ -63,6 +63,15 @@
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<!-- 阿里JSON解析器 --> <!-- 阿里JSON解析器 -->
<dependency> <dependency>

View File

@ -25,14 +25,14 @@ public class BaseEntity implements Serializable
private String createBy; private String createBy;
/** 创建时间 */ /** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createTime; private Date createTime;
/** 更新者 */ /** 更新者 */
private String updateBy; private String updateBy;
/** 更新时间 */ /** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date updateTime; private Date updateTime;
/** 备注 */ /** 备注 */

View File

@ -51,13 +51,23 @@
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
<version>5.8.20</version> <version>5.8.20</version> <!-- 该版本完全兼容JDK 8 -->
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- 参数校验核心依赖JDK 8兼容 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,6 +2,7 @@ package com.agri.generator.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import com.agri.generator.dto.ApiConfigDTO; import com.agri.generator.dto.ApiConfigDTO;
import com.agri.generator.util.CodeGenerator; import com.agri.generator.util.CodeGenerator;
@ -101,7 +102,7 @@ public class SysApiInfoController extends BaseController
* *
*/ */
@PostMapping("/code") @PostMapping("/code")
public String generateCode(@RequestBody ApiConfigDTO apiConfig) { public String generateCode(@Valid @RequestBody ApiConfigDTO apiConfig) {
try { try {
codeGenerator.generateApiCode(apiConfig); codeGenerator.generateApiCode(apiConfig);
return "代码生成成功,生成路径:" + System.getProperty("user.dir") + "/generated-code/"; return "代码生成成功,生成路径:" + System.getProperty("user.dir") + "/generated-code/";

View File

@ -1,17 +1,25 @@
package com.agri.generator.domain; package com.agri.generator.domain;
import java.util.List; import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import com.agri.common.annotation.Excel; import com.agri.common.annotation.Excel;
import com.agri.common.core.domain.BaseEntity; import com.agri.common.core.domain.BaseEntity;
import javax.validation.constraints.NotNull;
/** /**
* sys_api_info * sys_api_info
* *
* @author agri * @author agri
* @date 2025-12-30 * @date 2025-12-30
*/ */
@EqualsAndHashCode(callSuper = true)
@Data
public class SysApiInfo extends BaseEntity public class SysApiInfo extends BaseEntity
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -35,81 +43,27 @@ public class SysApiInfo extends BaseEntity
@Excel(name = "接口备注", readConverterExp = "对=应前端propapiRemark") @Excel(name = "接口备注", readConverterExp = "对=应前端propapiRemark")
private String apiRemark; private String apiRemark;
/**
* false
*/
@Excel(name = "是否生成入参实体", readConverterExp = "对=应前端propgenRequestEntity")
private Boolean isGenRequest = false;
/**
* false
*/
@Excel(name = "是否生成出参实体", readConverterExp = "对=应前端propgenResponseEntity")
private Boolean isGenResponse = false;
/** 逻辑删除标识0-未删1-已删) */ /** 逻辑删除标识0-未删1-已删) */
private Integer isDeleted; private Integer isDeleted;
/** 接口参数信息 */ /** 接口参数信息 */
@Setter
private List<SysApiParam> sysApiParamList; private List<SysApiParam> sysApiParamList;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setRequestPath(String requestPath)
{
this.requestPath = requestPath;
}
public String getRequestPath()
{
return requestPath;
}
public void setApiVendor(Long apiVendor)
{
this.apiVendor = apiVendor;
}
public Long getApiVendor()
{
return apiVendor;
}
public void setApiDesc(String apiDesc)
{
this.apiDesc = apiDesc;
}
public String getApiDesc()
{
return apiDesc;
}
public void setApiRemark(String apiRemark)
{
this.apiRemark = apiRemark;
}
public String getApiRemark()
{
return apiRemark;
}
public void setIsDeleted(Integer isDeleted)
{
this.isDeleted = isDeleted;
}
public Integer getIsDeleted()
{
return isDeleted;
}
public List<SysApiParam> getSysApiParamList()
{
return sysApiParamList;
}
public void setSysApiParamList(List<SysApiParam> sysApiParamList)
{
this.sysApiParamList = sysApiParamList;
}
@Override @Override
public String toString() { public String toString() {

View File

@ -41,9 +41,6 @@ public class SysApiParam extends BaseEntity
@Excel(name = "参数说明/注释", readConverterExp = "入=参paramDesc出参paramComment") @Excel(name = "参数说明/注释", readConverterExp = "入=参paramDesc出参paramComment")
private String paramDesc; private String paramDesc;
/** 是否生成实体入参genRequestEntity出参genResponseEntity */
@Excel(name = "是否生成实体", readConverterExp = "入=参genRequestEntity出参genResponseEntity")
private Long genEntity;
/** 是否生成实体 */ /** 是否生成实体 */
private Long isDeleted; private Long isDeleted;
@ -111,15 +108,7 @@ public class SysApiParam extends BaseEntity
{ {
return paramDesc; return paramDesc;
} }
public void setGenEntity(Long genEntity)
{
this.genEntity = genEntity;
}
public Long getGenEntity()
{
return genEntity;
}
public void setIsDeleted(Long isDeleted) public void setIsDeleted(Long isDeleted)
{ {
this.isDeleted = isDeleted; this.isDeleted = isDeleted;
@ -140,7 +129,6 @@ public class SysApiParam extends BaseEntity
.append("required", getRequired()) .append("required", getRequired())
.append("paramDataType", getParamDataType()) .append("paramDataType", getParamDataType())
.append("paramDesc", getParamDesc()) .append("paramDesc", getParamDesc())
.append("genEntity", getGenEntity())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.append("isDeleted", getIsDeleted()) .append("isDeleted", getIsDeleted())

View File

@ -1,40 +1,108 @@
package com.agri.generator.dto; package com.agri.generator.dto;
import lombok.Data; import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.List; import java.util.List;
/** /**
* *
*/ */
@Data @Data
public class ApiConfigDTO { public class ApiConfigDTO {
/** 请求路径 */ /**
* //_
*/
@NotBlank(message = "请求路径不能为空")
@Pattern(regexp = "^/[a-zA-Z0-9/_]+$", message = "请求路径格式错误,需以/开头,仅含字母、数字、/、_")
@Length(max = 500, message = "请求路径长度不能超过500字符")
private String requestPath; private String requestPath;
/** 接口类型(厂家) */
/**
*
*/
@NotBlank(message = "接口类型(厂家)不能为空")
@Length(max = 100, message = "接口类型厂家长度不能超过100字符")
private String apiVendor; private String apiVendor;
/** 接口说明 */
/**
*
*/
@NotBlank(message = "接口说明不能为空")
@Length(max = 1000, message = "接口说明长度不能超过1000字符")
private String apiDesc; private String apiDesc;
/** 接口备注 */
/**
*
*/
@Length(max = 2000, message = "接口备注长度不能超过2000字符")
private String apiRemark; private String apiRemark;
/** 入参列表 */
/**
* false
*/
@NotNull(message = "是否生成实体不能为空") // 确保传值true/false
private Boolean isGenRequest = false;
/**
* false
*/
@NotNull(message = "是否生成实体不能为空") // 确保传值true/false
private Boolean isGenResponse = false;
/**
*
*/
@NotEmpty(message = "入参列表不能为空")
@Valid // 级联校验子对象
private List<ApiParamDTO> requestParams; private List<ApiParamDTO> requestParams;
/** 出参列表 */
/**
*
*/
@NotEmpty(message = "出参列表不能为空")
@Valid // 级联校验子对象
private List<ApiParamDTO> responseParams; private List<ApiParamDTO> responseParams;
/** /**
* *
*/ */
@Data @Data
public static class ApiParamDTO { public static class ApiParamDTO {
/** 参数名 */ /**
*
*/
@NotBlank(message = "参数名不能为空")
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "参数名格式错误仅含字母、数字、_")
@Length(max = 200, message = "参数名长度不能超过200字符")
private String paramName; private String paramName;
/** 是否必选(仅入参) */
private Boolean required; /**
/** 参数类型String/Integer等 */ * false
*/
private Boolean required = false;
/**
*
*/
@NotBlank(message = "参数类型不能为空")
@Pattern(regexp = "^(String|Integer|Long|Boolean|Double|Date)$",
message = "参数类型仅支持String、Integer、Long、Boolean、Double、Date")
private String paramType; private String paramType;
/** 参数说明/注释 */
/**
* /
*/
@NotBlank(message = "参数说明/注释不能为空")
@Length(max = 500, message = "参数说明/注释长度不能超过500字符")
private String paramDesc; private String paramDesc;
/** 是否生成实体 */
private Boolean genEntity;
} }
} }

View File

@ -7,12 +7,15 @@ import com.agri.generator.dto.ApiConfigDTO;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -21,6 +24,7 @@ import java.util.stream.Collectors;
*/ */
@Component @Component
public class CodeGenerator { public class CodeGenerator {
private final ConversionService conversionService;
// Freemarker配置 // Freemarker配置
private Configuration freemarkerConfig; private Configuration freemarkerConfig;
@ -28,6 +32,12 @@ public class CodeGenerator {
private static final String CODE_ROOT_PATH = System.getProperty("user.dir") + "/generated-code/"; private static final String CODE_ROOT_PATH = System.getProperty("user.dir") + "/generated-code/";
// 基础包名 // 基础包名
private static final String BASE_PACKAGE = "com.example.api"; private static final String BASE_PACKAGE = "com.example.api";
// 日期格式化器
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public CodeGenerator(ConversionService conversionService) {
this.conversionService = conversionService;
}
@PostConstruct @PostConstruct
public void init() { public void init() {
@ -46,6 +56,9 @@ public class CodeGenerator {
* ++ * ++
*/ */
public void generateApiCode(ApiConfigDTO apiConfig) { public void generateApiCode(ApiConfigDTO apiConfig) {
if (apiConfig == null) {
throw new IllegalArgumentException("接口配置参数不能为空");
}
try { try {
// 1. 生成入参实体仅生成标记为genEntity=true的参数 // 1. 生成入参实体仅生成标记为genEntity=true的参数
generateRequestEntity(apiConfig); generateRequestEntity(apiConfig);
@ -56,7 +69,7 @@ public class CodeGenerator {
// 4. 生成枚举(需传入所有接口配置,此处示例传单个,实际可传列表) // 4. 生成枚举(需传入所有接口配置,此处示例传单个,实际可传列表)
List<ApiConfigDTO> apiList = Collections.singletonList(apiConfig); List<ApiConfigDTO> apiList = Collections.singletonList(apiConfig);
generateApiEnum(apiList); generateApiEnum(apiList);
} catch (Exception e) { } catch (IOException | TemplateException e) {
throw new RuntimeException("代码生成失败", e); throw new RuntimeException("代码生成失败", e);
} }
} }
@ -65,10 +78,11 @@ public class CodeGenerator {
* *
*/ */
private void generateRequestEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException { private void generateRequestEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException {
// 过滤需要生成实体的入参 // 过滤需要生成实体的入参JDK 8兼容写法
List<ApiConfigDTO.ApiParamDTO> requestParams = apiConfig.getRequestParams().stream() if (!apiConfig.getIsGenRequest()) {
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity) return;
.collect(Collectors.toList()); }
List<ApiConfigDTO.ApiParamDTO> requestParams = apiConfig.getRequestParams();
if (requestParams.isEmpty()) { if (requestParams.isEmpty()) {
return; return;
} }
@ -79,10 +93,10 @@ public class CodeGenerator {
Map<String, Object> dataModel = new HashMap<>(); Map<String, Object> dataModel = new HashMap<>();
dataModel.put("packageName", BASE_PACKAGE + ".request"); dataModel.put("packageName", BASE_PACKAGE + ".request");
dataModel.put("className", className); dataModel.put("className", className);
dataModel.put("apiDesc", apiConfig.getApiDesc()); dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
dataModel.put("apiRemark", apiConfig.getApiRemark()); dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
dataModel.put("params", requestParams); dataModel.put("params", requestParams);
dataModel.put("createTime", new Date()); dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
// 生成文件 // 生成文件
Template template = freemarkerConfig.getTemplate("entity.ftl"); Template template = freemarkerConfig.getTemplate("entity.ftl");
@ -94,10 +108,11 @@ public class CodeGenerator {
* *
*/ */
private void generateResponseEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException { private void generateResponseEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException {
if (!apiConfig.getIsGenResponse()) {
return;
}
// 过滤需要生成实体的出参 // 过滤需要生成实体的出参
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams().stream() List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams();
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity)
.collect(Collectors.toList());
if (responseParams.isEmpty()) { if (responseParams.isEmpty()) {
return; return;
} }
@ -108,10 +123,10 @@ public class CodeGenerator {
Map<String, Object> dataModel = new HashMap<>(); Map<String, Object> dataModel = new HashMap<>();
dataModel.put("packageName", BASE_PACKAGE + ".response"); dataModel.put("packageName", BASE_PACKAGE + ".response");
dataModel.put("className", className); dataModel.put("className", className);
dataModel.put("apiDesc", apiConfig.getApiDesc()); dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
dataModel.put("apiRemark", apiConfig.getApiRemark()); dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
dataModel.put("params", responseParams); dataModel.put("params", responseParams);
dataModel.put("createTime", new Date()); dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
// 生成文件 // 生成文件
Template template = freemarkerConfig.getTemplate("entity.ftl"); Template template = freemarkerConfig.getTemplate("entity.ftl");
@ -129,9 +144,7 @@ public class CodeGenerator {
String methodName = this.uncapitalize(getClassName(apiConfig.getRequestPath(), "")); String methodName = this.uncapitalize(getClassName(apiConfig.getRequestPath(), ""));
// 出参实体名默认用Response若生成则用实际实体名 // 出参实体名默认用Response若生成则用实际实体名
String responseEntityName = "Response"; String responseEntityName = "Response";
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams().stream() List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams();
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity)
.collect(Collectors.toList());
if (!responseParams.isEmpty()) { if (!responseParams.isEmpty()) {
responseEntityName = getClassName(apiConfig.getRequestPath(), "Response"); responseEntityName = getClassName(apiConfig.getRequestPath(), "Response");
} }
@ -142,13 +155,13 @@ public class CodeGenerator {
dataModel.put("className", className); dataModel.put("className", className);
dataModel.put("methodName", methodName); dataModel.put("methodName", methodName);
dataModel.put("requestMethod", "Post"); // 默认POST可根据实际需求调整 dataModel.put("requestMethod", "Post"); // 默认POST可根据实际需求调整
dataModel.put("requestPath", apiConfig.getRequestPath()); dataModel.put("requestPath", apiConfig.getRequestPath() == null ? "" : apiConfig.getRequestPath());
dataModel.put("apiVendor", apiConfig.getApiVendor()); dataModel.put("apiVendor", apiConfig.getApiVendor() == null ? "" : apiConfig.getApiVendor());
dataModel.put("apiDesc", apiConfig.getApiDesc()); dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
dataModel.put("apiRemark", apiConfig.getApiRemark()); dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
dataModel.put("requestParams", apiConfig.getRequestParams()); dataModel.put("requestParams", apiConfig.getRequestParams());
dataModel.put("responseEntityName", responseEntityName); dataModel.put("responseEntityName", responseEntityName);
dataModel.put("createTime", new Date()); dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
// 生成文件 // 生成文件
Template template = freemarkerConfig.getTemplate("apiMethod.ftl"); Template template = freemarkerConfig.getTemplate("apiMethod.ftl");
@ -163,10 +176,13 @@ public class CodeGenerator {
// 处理枚举数据(路径转枚举名,如/api/user/login → USER_LOGIN // 处理枚举数据(路径转枚举名,如/api/user/login → USER_LOGIN
List<Map<String, String>> enumDataList = new ArrayList<>(); List<Map<String, String>> enumDataList = new ArrayList<>();
for (ApiConfigDTO api : apiList) { for (ApiConfigDTO api : apiList) {
if (api == null) {
continue;
}
Map<String, String> enumData = new HashMap<>(); Map<String, String> enumData = new HashMap<>();
enumData.put("enumName", getEnumName(api.getRequestPath())); enumData.put("enumName", getEnumName(api.getRequestPath()));
enumData.put("requestPath", api.getRequestPath()); enumData.put("requestPath", api.getRequestPath() == null ? "" : api.getRequestPath());
enumData.put("apiDesc", api.getApiDesc()); enumData.put("apiDesc", api.getApiDesc() == null ? "" : api.getApiDesc());
enumDataList.add(enumData); enumDataList.add(enumData);
} }
@ -174,7 +190,7 @@ public class CodeGenerator {
Map<String, Object> dataModel = new HashMap<>(); Map<String, Object> dataModel = new HashMap<>();
dataModel.put("packageName", BASE_PACKAGE + ".enums"); dataModel.put("packageName", BASE_PACKAGE + ".enums");
dataModel.put("apiList", enumDataList); dataModel.put("apiList", enumDataList);
dataModel.put("createTime", new Date()); dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
// 生成文件 // 生成文件
Template template = freemarkerConfig.getTemplate("enum.ftl"); Template template = freemarkerConfig.getTemplate("enum.ftl");
@ -186,11 +202,20 @@ public class CodeGenerator {
* /api/user/login UserLogin + suffix * /api/user/login UserLogin + suffix
*/ */
private String getClassName(String path, String suffix) { private String getClassName(String path, String suffix) {
// 去除前缀/,按/分割,转驼峰 if (isBlank(path)) {
String[] parts = StrUtil.removePrefix(path, "/").split("/"); return "Default" + suffix;
}
// 去除前缀/,按/分割转驼峰纯JDK实现
String[] parts = path.split("\\.");
StringBuilder className = new StringBuilder(); StringBuilder className = new StringBuilder();
for (String part : parts) { for (String part : parts) {
className.append(StrUtil.upperFirst(part)); if (!Objects.equals(part, "api") && !Objects.equals(part, "v2")) {
className.append(StrUtil.upperFirst(part));
}
}
// 兜底处理空类名
if (className.length() == 0) {
className.append("Default");
} }
return className + suffix; return className + suffix;
} }
@ -199,7 +224,10 @@ public class CodeGenerator {
* /api/user/login USER_LOGIN * /api/user/login USER_LOGIN
*/ */
private String getEnumName(String path) { private String getEnumName(String path) {
String[] parts = StrUtil.removePrefix(path, "/").split("/"); if (isBlank(path)) {
return "DEFAULT_PATH";
}
String[] parts = path.split("\\.");
StringBuilder enumName = new StringBuilder(); StringBuilder enumName = new StringBuilder();
for (int i = 0; i < parts.length; i++) { for (int i = 0; i < parts.length; i++) {
enumName.append(parts[i].toUpperCase()); enumName.append(parts[i].toUpperCase());
@ -207,16 +235,21 @@ public class CodeGenerator {
enumName.append("_"); enumName.append("_");
} }
} }
// 兜底处理空枚举名
if (enumName.length() == 0) {
enumName.append("DEFAULT_PATH");
}
return enumName.toString(); return enumName.toString();
} }
/** /**
* * IOIOTemplate
*/ */
private void writeFile(Template template, Map<String, Object> dataModel, String filePath) throws IOException, TemplateException { private void writeFile(Template template, Map<String, Object> dataModel, String filePath) throws IOException, TemplateException {
File file = new File(filePath); File file = new File(filePath);
FileUtil.mkParentDirs(file); // 创建父目录 FileUtil.mkParentDirs(file); // 创建父目录
try (Writer writer = new FileWriter(file, false)) { try (Writer writer = new FileWriter(file, false)) {
// 渲染模板并写入文件
template.process(dataModel, writer); template.process(dataModel, writer);
} }
} }

View File

@ -12,6 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="apiRemark" column="api_remark" /> <result property="apiRemark" column="api_remark" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="isGenRequest" column="is_gen_request" />
<result property="isGenResponse" column="is_gen_response" />
<result property="isDeleted" column="is_deleted" /> <result property="isDeleted" column="is_deleted" />
</resultMap> </resultMap>
@ -27,14 +29,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="required" column="required" /> <result property="required" column="required" />
<result property="paramDataType" column="param_data_type" /> <result property="paramDataType" column="param_data_type" />
<result property="paramDesc" column="param_desc" /> <result property="paramDesc" column="param_desc" />
<result property="genEntity" column="gen_entity" />
<result property="createTime" column="create_time" /> <result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="isDeleted" column="is_deleted" /> <result property="isDeleted" column="is_deleted" />
</resultMap> </resultMap>
<sql id="selectSysApiInfoVo"> <sql id="selectSysApiInfoVo">
select id, request_path, api_vendor, api_desc, api_remark, create_time, update_time, is_deleted from sys_api_info select id, request_path, api_vendor, api_desc, api_remark, create_time, update_time,is_gen_request, is_gen_response, is_deleted from sys_api_info
</sql> </sql>
<select id="selectSysApiInfoList" parameterType="SysApiInfo" resultMap="SysApiInfoResult"> <select id="selectSysApiInfoList" parameterType="SysApiInfo" resultMap="SysApiInfoResult">
@ -49,7 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="selectSysApiInfoById" parameterType="Long" resultMap="SysApiInfoSysApiParamResult"> <select id="selectSysApiInfoById" parameterType="Long" resultMap="SysApiInfoSysApiParamResult">
select id, request_path, api_vendor, api_desc, api_remark, create_time, update_time, is_deleted select id, request_path, api_vendor, api_desc, api_remark, create_time, update_time, is_gen_request, is_gen_response, is_deleted
from sys_api_info from sys_api_info
where id = #{id} where id = #{id}
</select> </select>
@ -121,7 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="batchSysApiParam"> <insert id="batchSysApiParam">
insert into sys_api_param( id, api_id, param_type, param_name, required, param_data_type, param_desc, gen_entity, create_time, update_time, is_deleted) values insert into sys_api_param( id, api_id, param_type, param_name, required, param_data_type, param_desc, gen_entity, create_time, update_time, is_deleted) values
<foreach item="item" index="index" collection="list" separator=","> <foreach item="item" index="index" collection="list" separator=",">
( #{item.id}, #{item.apiId}, #{item.paramType}, #{item.paramName}, #{item.required}, #{item.paramDataType}, #{item.paramDesc}, #{item.genEntity}, #{item.createTime}, #{item.updateTime}, #{item.isDeleted}) ( #{item.id}, #{item.apiId}, #{item.paramType}, #{item.paramName}, #{item.required}, #{item.paramDataType}, #{item.paramDesc}, #{item.createTime}, #{item.updateTime}, #{item.isDeleted})
</foreach> </foreach>
</insert> </insert>
</mapper> </mapper>

View File

@ -32,7 +32,8 @@ public class ${className} {
</#list> </#list>
</#if> </#if>
) { ) {
// 接口业务逻辑(需手动实现)
return new ${responseEntityName}(); // 接口业务逻辑
return AjaxResult. ${responseEntityName}();
} }
} }

View File

@ -10,7 +10,7 @@ public enum ApiPathEnum {
/** /**
* ${api.apiDesc} * ${api.apiDesc}
*/ */
${api.enumName}("${api.requestPath}", "${api.apiDesc}") ${api.enumName}("${api.requestPath}", "${api.enumName}")
<#if api_has_next>,</#if> <#if api_has_next>,</#if>
</#list>; </#list>;

View File

@ -540,7 +540,11 @@ export default {
}) })
} else { } else {
add${BusinessName}(this.form).then(response => { add${BusinessName}(this.form).then(response => {
this.#[[$modal]]#.msgSuccess("新增成功") if (response.code==='200') {
this.#[[$modal]]#.msgSuccess("新增成功")
} else {
this.#[[$modal]]#.msgError("新增失败")
}
this.open = false this.open = false
this.getList() this.getList()
}) })

View File

@ -30,7 +30,7 @@ public class SysDtuData extends BaseEntity
private Long ts; private Long ts;
/** ts转换后的正常时间(由服务端转换入库) */ /** ts转换后的正常时间(由服务端转换入库) */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@Excel(name = "ts转换后的正常时间(由服务端转换入库)", width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "ts转换后的正常时间(由服务端转换入库)", width = 30, dateFormat = "yyyy-MM-dd")
private Date time; private Date time;