暂时提交 三方接口
parent
0514bad75c
commit
caa4a24b53
|
|
@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,17 @@
|
|||
<groupId>com.agri</groupId>
|
||||
<artifactId>agri-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 通用工具-->
|
||||
<dependency>
|
||||
<groupId>com.agri</groupId>
|
||||
<artifactId>agri-generator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 JSON调用工具类(JDK 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 请求体(Java对象,自动转为JSON)
|
||||
* @param headers 请求头(如token、Content-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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求(无请求体,参数拼在URL后)
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,15 @@
|
|||
<artifactId>jackson-databind</artifactId>
|
||||
</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解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ public class BaseEntity implements Serializable
|
|||
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 String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
|
||||
private Date updateTime;
|
||||
|
||||
/** 备注 */
|
||||
|
|
|
|||
|
|
@ -51,13 +51,23 @@
|
|||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.20</version>
|
||||
<version>5.8.20</version> <!-- 该版本完全兼容JDK 8 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
|
||||
</project>
|
||||
|
|
@ -2,6 +2,7 @@ package com.agri.generator.controller;
|
|||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.agri.generator.dto.ApiConfigDTO;
|
||||
import com.agri.generator.util.CodeGenerator;
|
||||
|
|
@ -101,7 +102,7 @@ public class SysApiInfoController extends BaseController
|
|||
* 接收前端配置,生成接口相关代码
|
||||
*/
|
||||
@PostMapping("/code")
|
||||
public String generateCode(@RequestBody ApiConfigDTO apiConfig) {
|
||||
public String generateCode(@Valid @RequestBody ApiConfigDTO apiConfig) {
|
||||
try {
|
||||
codeGenerator.generateApiCode(apiConfig);
|
||||
return "代码生成成功,生成路径:" + System.getProperty("user.dir") + "/generated-code/";
|
||||
|
|
|
|||
|
|
@ -1,17 +1,25 @@
|
|||
package com.agri.generator.domain;
|
||||
|
||||
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.ToStringStyle;
|
||||
import com.agri.common.annotation.Excel;
|
||||
import com.agri.common.core.domain.BaseEntity;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 接口基础信息对象 sys_api_info
|
||||
*
|
||||
* @author agri
|
||||
* @date 2025-12-30
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class SysApiInfo extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
@ -35,81 +43,27 @@ public class SysApiInfo extends BaseEntity
|
|||
@Excel(name = "接口备注", readConverterExp = "对=应前端prop:apiRemark")
|
||||
private String apiRemark;
|
||||
|
||||
|
||||
/**
|
||||
* 是否生成实体(选填,默认false)
|
||||
*/
|
||||
@Excel(name = "是否生成入参实体", readConverterExp = "对=应前端prop:genRequestEntity")
|
||||
private Boolean isGenRequest = false;
|
||||
|
||||
/**
|
||||
* 是否生成实体(选填,默认false)
|
||||
*/
|
||||
@Excel(name = "是否生成出参实体", readConverterExp = "对=应前端prop:genResponseEntity")
|
||||
private Boolean isGenResponse = false;
|
||||
|
||||
|
||||
/** 逻辑删除标识(0-未删,1-已删) */
|
||||
private Integer isDeleted;
|
||||
|
||||
/** 接口参数信息 */
|
||||
@Setter
|
||||
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
|
||||
public String toString() {
|
||||
|
|
|
|||
|
|
@ -41,9 +41,6 @@ public class SysApiParam extends BaseEntity
|
|||
@Excel(name = "参数说明/注释", readConverterExp = "入=参:paramDesc,出参:paramComment")
|
||||
private String paramDesc;
|
||||
|
||||
/** 是否生成实体(入参:genRequestEntity,出参:genResponseEntity) */
|
||||
@Excel(name = "是否生成实体", readConverterExp = "入=参:genRequestEntity,出参:genResponseEntity")
|
||||
private Long genEntity;
|
||||
|
||||
/** 是否生成实体 */
|
||||
private Long isDeleted;
|
||||
|
|
@ -111,15 +108,7 @@ public class SysApiParam extends BaseEntity
|
|||
{
|
||||
return paramDesc;
|
||||
}
|
||||
public void setGenEntity(Long genEntity)
|
||||
{
|
||||
this.genEntity = genEntity;
|
||||
}
|
||||
|
||||
public Long getGenEntity()
|
||||
{
|
||||
return genEntity;
|
||||
}
|
||||
public void setIsDeleted(Long isDeleted)
|
||||
{
|
||||
this.isDeleted = isDeleted;
|
||||
|
|
@ -140,7 +129,6 @@ public class SysApiParam extends BaseEntity
|
|||
.append("required", getRequired())
|
||||
.append("paramDataType", getParamDataType())
|
||||
.append("paramDesc", getParamDesc())
|
||||
.append("genEntity", getGenEntity())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("isDeleted", getIsDeleted())
|
||||
|
|
|
|||
|
|
@ -1,40 +1,108 @@
|
|||
package com.agri.generator.dto;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 接口配置接收模型
|
||||
* 接口配置接收模型(含参数校验)
|
||||
*/
|
||||
@Data
|
||||
public class ApiConfigDTO {
|
||||
/** 请求路径 */
|
||||
/**
|
||||
* 请求路径(必填,格式以/开头,仅含字母、数字、/、_)
|
||||
*/
|
||||
@NotBlank(message = "请求路径不能为空")
|
||||
@Pattern(regexp = "^/[a-zA-Z0-9/_]+$", message = "请求路径格式错误,需以/开头,仅含字母、数字、/、_")
|
||||
@Length(max = 500, message = "请求路径长度不能超过500字符")
|
||||
private String requestPath;
|
||||
/** 接口类型(厂家) */
|
||||
|
||||
/**
|
||||
* 接口类型(厂家)(必填)
|
||||
*/
|
||||
@NotBlank(message = "接口类型(厂家)不能为空")
|
||||
@Length(max = 100, message = "接口类型(厂家)长度不能超过100字符")
|
||||
private String apiVendor;
|
||||
/** 接口说明 */
|
||||
|
||||
/**
|
||||
* 接口说明(必填)
|
||||
*/
|
||||
@NotBlank(message = "接口说明不能为空")
|
||||
@Length(max = 1000, message = "接口说明长度不能超过1000字符")
|
||||
private String apiDesc;
|
||||
/** 接口备注 */
|
||||
|
||||
/**
|
||||
* 接口备注(选填)
|
||||
*/
|
||||
@Length(max = 2000, message = "接口备注长度不能超过2000字符")
|
||||
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;
|
||||
/** 出参列表 */
|
||||
|
||||
/**
|
||||
* 出参列表(必填,至少一个)
|
||||
*/
|
||||
@NotEmpty(message = "出参列表不能为空")
|
||||
@Valid // 级联校验子对象
|
||||
private List<ApiParamDTO> responseParams;
|
||||
|
||||
/**
|
||||
* 参数子模型
|
||||
* 参数子模型(含级联校验)
|
||||
*/
|
||||
@Data
|
||||
public static class ApiParamDTO {
|
||||
/** 参数名 */
|
||||
/**
|
||||
* 参数名(必填)
|
||||
*/
|
||||
@NotBlank(message = "参数名不能为空")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "参数名格式错误,仅含字母、数字、_")
|
||||
@Length(max = 200, message = "参数名长度不能超过200字符")
|
||||
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;
|
||||
/** 参数说明/注释 */
|
||||
|
||||
/**
|
||||
* 参数说明/注释(必填)
|
||||
*/
|
||||
@NotBlank(message = "参数说明/注释不能为空")
|
||||
@Length(max = 500, message = "参数说明/注释长度不能超过500字符")
|
||||
private String paramDesc;
|
||||
/** 是否生成实体 */
|
||||
private Boolean genEntity;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -7,12 +7,15 @@ import com.agri.generator.dto.ApiConfigDTO;
|
|||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
|
@ -21,6 +24,7 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
@Component
|
||||
public class CodeGenerator {
|
||||
private final ConversionService conversionService;
|
||||
// Freemarker配置
|
||||
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 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
|
||||
public void init() {
|
||||
|
|
@ -46,6 +56,9 @@ public class CodeGenerator {
|
|||
* 生成接口相关代码(实体+接口方法+枚举)
|
||||
*/
|
||||
public void generateApiCode(ApiConfigDTO apiConfig) {
|
||||
if (apiConfig == null) {
|
||||
throw new IllegalArgumentException("接口配置参数不能为空");
|
||||
}
|
||||
try {
|
||||
// 1. 生成入参实体(仅生成标记为genEntity=true的参数)
|
||||
generateRequestEntity(apiConfig);
|
||||
|
|
@ -56,7 +69,7 @@ public class CodeGenerator {
|
|||
// 4. 生成枚举(需传入所有接口配置,此处示例传单个,实际可传列表)
|
||||
List<ApiConfigDTO> apiList = Collections.singletonList(apiConfig);
|
||||
generateApiEnum(apiList);
|
||||
} catch (Exception e) {
|
||||
} catch (IOException | TemplateException e) {
|
||||
throw new RuntimeException("代码生成失败", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -65,10 +78,11 @@ public class CodeGenerator {
|
|||
* 生成入参实体
|
||||
*/
|
||||
private void generateRequestEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException {
|
||||
// 过滤需要生成实体的入参
|
||||
List<ApiConfigDTO.ApiParamDTO> requestParams = apiConfig.getRequestParams().stream()
|
||||
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity)
|
||||
.collect(Collectors.toList());
|
||||
// 过滤需要生成实体的入参(JDK 8兼容写法)
|
||||
if (!apiConfig.getIsGenRequest()) {
|
||||
return;
|
||||
}
|
||||
List<ApiConfigDTO.ApiParamDTO> requestParams = apiConfig.getRequestParams();
|
||||
if (requestParams.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -79,10 +93,10 @@ public class CodeGenerator {
|
|||
Map<String, Object> dataModel = new HashMap<>();
|
||||
dataModel.put("packageName", BASE_PACKAGE + ".request");
|
||||
dataModel.put("className", className);
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark());
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
|
||||
dataModel.put("params", requestParams);
|
||||
dataModel.put("createTime", new Date());
|
||||
dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
// 生成文件
|
||||
Template template = freemarkerConfig.getTemplate("entity.ftl");
|
||||
|
|
@ -94,10 +108,11 @@ public class CodeGenerator {
|
|||
* 生成出参实体
|
||||
*/
|
||||
private void generateResponseEntity(ApiConfigDTO apiConfig) throws IOException, TemplateException {
|
||||
if (!apiConfig.getIsGenResponse()) {
|
||||
return;
|
||||
}
|
||||
// 过滤需要生成实体的出参
|
||||
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams().stream()
|
||||
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity)
|
||||
.collect(Collectors.toList());
|
||||
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams();
|
||||
if (responseParams.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -108,10 +123,10 @@ public class CodeGenerator {
|
|||
Map<String, Object> dataModel = new HashMap<>();
|
||||
dataModel.put("packageName", BASE_PACKAGE + ".response");
|
||||
dataModel.put("className", className);
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark());
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
|
||||
dataModel.put("params", responseParams);
|
||||
dataModel.put("createTime", new Date());
|
||||
dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
// 生成文件
|
||||
Template template = freemarkerConfig.getTemplate("entity.ftl");
|
||||
|
|
@ -129,9 +144,7 @@ public class CodeGenerator {
|
|||
String methodName = this.uncapitalize(getClassName(apiConfig.getRequestPath(), ""));
|
||||
// 出参实体名(默认用Response,若生成则用实际实体名)
|
||||
String responseEntityName = "Response";
|
||||
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams().stream()
|
||||
.filter(ApiConfigDTO.ApiParamDTO::getGenEntity)
|
||||
.collect(Collectors.toList());
|
||||
List<ApiConfigDTO.ApiParamDTO> responseParams = apiConfig.getResponseParams();
|
||||
if (!responseParams.isEmpty()) {
|
||||
responseEntityName = getClassName(apiConfig.getRequestPath(), "Response");
|
||||
}
|
||||
|
|
@ -142,13 +155,13 @@ public class CodeGenerator {
|
|||
dataModel.put("className", className);
|
||||
dataModel.put("methodName", methodName);
|
||||
dataModel.put("requestMethod", "Post"); // 默认POST,可根据实际需求调整
|
||||
dataModel.put("requestPath", apiConfig.getRequestPath());
|
||||
dataModel.put("apiVendor", apiConfig.getApiVendor());
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark());
|
||||
dataModel.put("requestPath", apiConfig.getRequestPath() == null ? "" : apiConfig.getRequestPath());
|
||||
dataModel.put("apiVendor", apiConfig.getApiVendor() == null ? "" : apiConfig.getApiVendor());
|
||||
dataModel.put("apiDesc", apiConfig.getApiDesc() == null ? "" : apiConfig.getApiDesc());
|
||||
dataModel.put("apiRemark", apiConfig.getApiRemark() == null ? "" : apiConfig.getApiRemark());
|
||||
dataModel.put("requestParams", apiConfig.getRequestParams());
|
||||
dataModel.put("responseEntityName", responseEntityName);
|
||||
dataModel.put("createTime", new Date());
|
||||
dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
// 生成文件
|
||||
Template template = freemarkerConfig.getTemplate("apiMethod.ftl");
|
||||
|
|
@ -163,10 +176,13 @@ public class CodeGenerator {
|
|||
// 处理枚举数据(路径转枚举名,如/api/user/login → USER_LOGIN)
|
||||
List<Map<String, String>> enumDataList = new ArrayList<>();
|
||||
for (ApiConfigDTO api : apiList) {
|
||||
if (api == null) {
|
||||
continue;
|
||||
}
|
||||
Map<String, String> enumData = new HashMap<>();
|
||||
enumData.put("enumName", getEnumName(api.getRequestPath()));
|
||||
enumData.put("requestPath", api.getRequestPath());
|
||||
enumData.put("apiDesc", api.getApiDesc());
|
||||
enumData.put("requestPath", api.getRequestPath() == null ? "" : api.getRequestPath());
|
||||
enumData.put("apiDesc", api.getApiDesc() == null ? "" : api.getApiDesc());
|
||||
enumDataList.add(enumData);
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +190,7 @@ public class CodeGenerator {
|
|||
Map<String, Object> dataModel = new HashMap<>();
|
||||
dataModel.put("packageName", BASE_PACKAGE + ".enums");
|
||||
dataModel.put("apiList", enumDataList);
|
||||
dataModel.put("createTime", new Date());
|
||||
dataModel.put("createTime", LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
// 生成文件
|
||||
Template template = freemarkerConfig.getTemplate("enum.ftl");
|
||||
|
|
@ -186,11 +202,20 @@ public class CodeGenerator {
|
|||
* 路径转类名(如/api/user/login → UserLogin + suffix)
|
||||
*/
|
||||
private String getClassName(String path, String suffix) {
|
||||
// 去除前缀/,按/分割,转驼峰
|
||||
String[] parts = StrUtil.removePrefix(path, "/").split("/");
|
||||
if (isBlank(path)) {
|
||||
return "Default" + suffix;
|
||||
}
|
||||
// 去除前缀/,按/分割,转驼峰(纯JDK实现)
|
||||
String[] parts = path.split("\\.");
|
||||
StringBuilder className = new StringBuilder();
|
||||
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;
|
||||
}
|
||||
|
|
@ -199,7 +224,10 @@ public class CodeGenerator {
|
|||
* 路径转枚举名(如/api/user/login → USER_LOGIN)
|
||||
*/
|
||||
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();
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
enumName.append(parts[i].toUpperCase());
|
||||
|
|
@ -207,16 +235,21 @@ public class CodeGenerator {
|
|||
enumName.append("_");
|
||||
}
|
||||
}
|
||||
// 兜底处理空枚举名
|
||||
if (enumName.length() == 0) {
|
||||
enumName.append("DEFAULT_PATH");
|
||||
}
|
||||
return enumName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入文件
|
||||
* 写入文件(修复IO异常编译错误:明确分离IO异常和Template异常)
|
||||
*/
|
||||
private void writeFile(Template template, Map<String, Object> dataModel, String filePath) throws IOException, TemplateException {
|
||||
File file = new File(filePath);
|
||||
FileUtil.mkParentDirs(file); // 创建父目录
|
||||
try (Writer writer = new FileWriter(file, false)) {
|
||||
// 渲染模板并写入文件
|
||||
template.process(dataModel, writer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="apiRemark" column="api_remark" />
|
||||
<result property="createTime" column="create_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" />
|
||||
</resultMap>
|
||||
|
||||
|
|
@ -27,14 +29,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<result property="required" column="required" />
|
||||
<result property="paramDataType" column="param_data_type" />
|
||||
<result property="paramDesc" column="param_desc" />
|
||||
<result property="genEntity" column="gen_entity" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="isDeleted" column="is_deleted" />
|
||||
</resultMap>
|
||||
|
||||
<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>
|
||||
|
||||
<select id="selectSysApiInfoList" parameterType="SysApiInfo" resultMap="SysApiInfoResult">
|
||||
|
|
@ -49,7 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
</select>
|
||||
|
||||
<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
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
|
@ -121,7 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<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
|
||||
<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>
|
||||
</insert>
|
||||
</mapper>
|
||||
|
|
@ -32,7 +32,8 @@ public class ${className} {
|
|||
</#list>
|
||||
</#if>
|
||||
) {
|
||||
// 接口业务逻辑(需手动实现)
|
||||
return new ${responseEntityName}();
|
||||
|
||||
// 接口业务逻辑
|
||||
return AjaxResult. ${responseEntityName}();
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ public enum ApiPathEnum {
|
|||
/**
|
||||
* ${api.apiDesc}
|
||||
*/
|
||||
${api.enumName}("${api.requestPath}", "${api.apiDesc}")
|
||||
${api.enumName}("${api.requestPath}", "${api.enumName}")
|
||||
<#if api_has_next>,</#if>
|
||||
</#list>;
|
||||
|
||||
|
|
|
|||
|
|
@ -540,7 +540,11 @@ export default {
|
|||
})
|
||||
} else {
|
||||
add${BusinessName}(this.form).then(response => {
|
||||
this.#[[$modal]]#.msgSuccess("新增成功")
|
||||
if (response.code==='200') {
|
||||
this.#[[$modal]]#.msgSuccess("新增成功")
|
||||
} else {
|
||||
this.#[[$modal]]#.msgError("新增失败")
|
||||
}
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public class SysDtuData extends BaseEntity
|
|||
private Long 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")
|
||||
private Date time;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue