From caa4a24b53f7050f53e2f88a8b65800268df4bb2 Mon Sep 17 00:00:00 2001 From: lld <15027638633@163.com> Date: Thu, 1 Jan 2026 12:27:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E6=97=B6=E6=8F=90=E4=BA=A4=20=20?= =?UTF-8?q?=E4=B8=89=E6=96=B9=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/tool/TestController.java | 1 + agri-api/pom.xml | 11 ++ .../agri/api/controller/TestController.java | 33 ++++ .../java/com/agri/api/domain/ApiMain.java | 12 ++ .../java/com/agri/api/util/HttpJsonUtil.java | 163 ++++++++++++++++++ agri-common/pom.xml | 9 + .../agri/common/core/domain/BaseEntity.java | 4 +- agri-generator/pom.xml | 12 +- .../controller/SysApiInfoController.java | 3 +- .../com/agri/generator/domain/SysApiInfo.java | 92 +++------- .../agri/generator/domain/SysApiParam.java | 12 -- .../com/agri/generator/dto/ApiConfigDTO.java | 98 +++++++++-- .../agri/generator/util/CodeGenerator.java | 93 ++++++---- .../mapper/tool/SysApiInfoMapper.xml | 9 +- .../main/resources/templates/apiMethod.ftl | 5 +- .../src/main/resources/templates/enum.ftl | 2 +- .../src/main/resources/vm/vue/index.vue.vm | 6 +- .../com/agri/system/domain/SysDtuData.java | 2 +- 18 files changed, 428 insertions(+), 139 deletions(-) create mode 100644 agri-api/src/main/java/com/agri/api/controller/TestController.java create mode 100644 agri-api/src/main/java/com/agri/api/domain/ApiMain.java create mode 100644 agri-api/src/main/java/com/agri/api/util/HttpJsonUtil.java diff --git a/agri-admin/src/main/java/com/agri/web/controller/tool/TestController.java b/agri-admin/src/main/java/com/agri/web/controller/tool/TestController.java index 4ded100..b2b6d96 100644 --- a/agri-admin/src/main/java/com/agri/web/controller/tool/TestController.java +++ b/agri-admin/src/main/java/com/agri/web/controller/tool/TestController.java @@ -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; diff --git a/agri-api/pom.xml b/agri-api/pom.xml index ba5e754..56df8f3 100644 --- a/agri-api/pom.xml +++ b/agri-api/pom.xml @@ -19,6 +19,17 @@ com.agri agri-common + + + + com.agri + agri-generator + + + org.projectlombok + lombok + provided + diff --git a/agri-api/src/main/java/com/agri/api/controller/TestController.java b/agri-api/src/main/java/com/agri/api/controller/TestController.java new file mode 100644 index 0000000..c5ebbbf --- /dev/null +++ b/agri-api/src/main/java/com/agri/api/controller/TestController.java @@ -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(); + } + } +} diff --git a/agri-api/src/main/java/com/agri/api/domain/ApiMain.java b/agri-api/src/main/java/com/agri/api/domain/ApiMain.java new file mode 100644 index 0000000..743cc87 --- /dev/null +++ b/agri-api/src/main/java/com/agri/api/domain/ApiMain.java @@ -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; +} diff --git a/agri-api/src/main/java/com/agri/api/util/HttpJsonUtil.java b/agri-api/src/main/java/com/agri/api/util/HttpJsonUtil.java new file mode 100644 index 0000000..bfa67c1 --- /dev/null +++ b/agri-api/src/main/java/com/agri/api/util/HttpJsonUtil.java @@ -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 doPostJson(String url, Object requestBody, Map headers, Class 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 doGet(String url, Map headers, Class 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 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 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 getResponse(HttpURLConnection conn, Class 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 doPostJson(String url, Object requestBody, Class responseType) { + return doPostJson(url, requestBody, null, responseType); + } + + // 重载方法:无自定义请求头的GET + public static T doGet(String url, Class responseType) { + return doGet(url, null, responseType); + } +} \ No newline at end of file diff --git a/agri-common/pom.xml b/agri-common/pom.xml index 6925586..b84f9f0 100644 --- a/agri-common/pom.xml +++ b/agri-common/pom.xml @@ -63,6 +63,15 @@ com.fasterxml.jackson.core jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + diff --git a/agri-common/src/main/java/com/agri/common/core/domain/BaseEntity.java b/agri-common/src/main/java/com/agri/common/core/domain/BaseEntity.java index 4b7b5b6..0fd795e 100644 --- a/agri-common/src/main/java/com/agri/common/core/domain/BaseEntity.java +++ b/agri-common/src/main/java/com/agri/common/core/domain/BaseEntity.java @@ -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; /** 备注 */ diff --git a/agri-generator/pom.xml b/agri-generator/pom.xml index 802f2b5..72c94c4 100644 --- a/agri-generator/pom.xml +++ b/agri-generator/pom.xml @@ -51,13 +51,23 @@ cn.hutool hutool-all - 5.8.20 + 5.8.20 org.projectlombok lombok provided + + + + javax.validation + validation-api + + + org.hibernate.validator + hibernate-validator + \ No newline at end of file diff --git a/agri-generator/src/main/java/com/agri/generator/controller/SysApiInfoController.java b/agri-generator/src/main/java/com/agri/generator/controller/SysApiInfoController.java index 90cbaab..b50fee6 100644 --- a/agri-generator/src/main/java/com/agri/generator/controller/SysApiInfoController.java +++ b/agri-generator/src/main/java/com/agri/generator/controller/SysApiInfoController.java @@ -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/"; diff --git a/agri-generator/src/main/java/com/agri/generator/domain/SysApiInfo.java b/agri-generator/src/main/java/com/agri/generator/domain/SysApiInfo.java index 23fc5fc..2def74a 100644 --- a/agri-generator/src/main/java/com/agri/generator/domain/SysApiInfo.java +++ b/agri-generator/src/main/java/com/agri/generator/domain/SysApiInfo.java @@ -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 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 getSysApiParamList() - { - return sysApiParamList; - } - - public void setSysApiParamList(List sysApiParamList) - { - this.sysApiParamList = sysApiParamList; - } @Override public String toString() { diff --git a/agri-generator/src/main/java/com/agri/generator/domain/SysApiParam.java b/agri-generator/src/main/java/com/agri/generator/domain/SysApiParam.java index bd531ad..b85dc0e 100644 --- a/agri-generator/src/main/java/com/agri/generator/domain/SysApiParam.java +++ b/agri-generator/src/main/java/com/agri/generator/domain/SysApiParam.java @@ -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()) diff --git a/agri-generator/src/main/java/com/agri/generator/dto/ApiConfigDTO.java b/agri-generator/src/main/java/com/agri/generator/dto/ApiConfigDTO.java index b393a93..2db3afc 100644 --- a/agri-generator/src/main/java/com/agri/generator/dto/ApiConfigDTO.java +++ b/agri-generator/src/main/java/com/agri/generator/dto/ApiConfigDTO.java @@ -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 requestParams; - /** 出参列表 */ + + /** + * 出参列表(必填,至少一个) + */ + @NotEmpty(message = "出参列表不能为空") + @Valid // 级联校验子对象 private List 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; + } } \ No newline at end of file diff --git a/agri-generator/src/main/java/com/agri/generator/util/CodeGenerator.java b/agri-generator/src/main/java/com/agri/generator/util/CodeGenerator.java index 37f8370..54cc35d 100644 --- a/agri-generator/src/main/java/com/agri/generator/util/CodeGenerator.java +++ b/agri-generator/src/main/java/com/agri/generator/util/CodeGenerator.java @@ -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 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 requestParams = apiConfig.getRequestParams().stream() - .filter(ApiConfigDTO.ApiParamDTO::getGenEntity) - .collect(Collectors.toList()); + // 过滤需要生成实体的入参(JDK 8兼容写法) + if (!apiConfig.getIsGenRequest()) { + return; + } + List requestParams = apiConfig.getRequestParams(); if (requestParams.isEmpty()) { return; } @@ -79,10 +93,10 @@ public class CodeGenerator { Map 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 responseParams = apiConfig.getResponseParams().stream() - .filter(ApiConfigDTO.ApiParamDTO::getGenEntity) - .collect(Collectors.toList()); + List responseParams = apiConfig.getResponseParams(); if (responseParams.isEmpty()) { return; } @@ -108,10 +123,10 @@ public class CodeGenerator { Map 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 responseParams = apiConfig.getResponseParams().stream() - .filter(ApiConfigDTO.ApiParamDTO::getGenEntity) - .collect(Collectors.toList()); + List 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> enumDataList = new ArrayList<>(); for (ApiConfigDTO api : apiList) { + if (api == null) { + continue; + } Map 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 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 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); } } diff --git a/agri-generator/src/main/resources/mapper/tool/SysApiInfoMapper.xml b/agri-generator/src/main/resources/mapper/tool/SysApiInfoMapper.xml index 24cdbe7..c42b64a 100644 --- a/agri-generator/src/main/resources/mapper/tool/SysApiInfoMapper.xml +++ b/agri-generator/src/main/resources/mapper/tool/SysApiInfoMapper.xml @@ -12,6 +12,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -27,14 +29,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - 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 @@ -121,7 +122,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 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 - ( #{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}) \ No newline at end of file diff --git a/agri-generator/src/main/resources/templates/apiMethod.ftl b/agri-generator/src/main/resources/templates/apiMethod.ftl index b8b5c8c..ad5c6f7 100644 --- a/agri-generator/src/main/resources/templates/apiMethod.ftl +++ b/agri-generator/src/main/resources/templates/apiMethod.ftl @@ -32,7 +32,8 @@ public class ${className} { ) { - // 接口业务逻辑(需手动实现) - return new ${responseEntityName}(); + + // 接口业务逻辑 + return AjaxResult. ${responseEntityName}(); } } \ No newline at end of file diff --git a/agri-generator/src/main/resources/templates/enum.ftl b/agri-generator/src/main/resources/templates/enum.ftl index c5b7335..bf8d837 100644 --- a/agri-generator/src/main/resources/templates/enum.ftl +++ b/agri-generator/src/main/resources/templates/enum.ftl @@ -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>, ; diff --git a/agri-generator/src/main/resources/vm/vue/index.vue.vm b/agri-generator/src/main/resources/vm/vue/index.vue.vm index 205d888..0019995 100644 --- a/agri-generator/src/main/resources/vm/vue/index.vue.vm +++ b/agri-generator/src/main/resources/vm/vue/index.vue.vm @@ -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() }) diff --git a/agri-system/src/main/java/com/agri/system/domain/SysDtuData.java b/agri-system/src/main/java/com/agri/system/domain/SysDtuData.java index 053a084..f92afb1 100644 --- a/agri-system/src/main/java/com/agri/system/domain/SysDtuData.java +++ b/agri-system/src/main/java/com/agri/system/domain/SysDtuData.java @@ -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;