From 7168e60fddc4210691a4f93651b2f0c9c081b1f3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 3 Feb 2025 18:33:43 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E5=AE=9E=E7=8E=B0=20IotRuleSceneDataBridg?= =?UTF-8?q?eAction=20=E7=9A=84=20http=20=E9=83=A8=E5=88=86=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/http/HttpUtils.java | 14 ++- .../common/util/servlet/ServletUtils.java | 4 + .../framework/excel/core/util/ExcelUtils.java | 5 +- .../file/core/utils/FileTypeUtils.java | 4 +- .../dal/mysql/rule/IotDataBridgeMapper.java | 9 ++ .../service/rule/IotDataBridgeService.java | 20 ++++ .../rule/IotDataBridgeServiceImpl.java | 45 +++++++++ .../service/rule/IotRuleSceneServiceImpl.java | 8 +- .../action/IotRuleSceneDataBridgeAction.java | 99 ++++++++++++++++++- .../sms/core/client/impl/AliyunSmsClient.java | 2 +- .../sms/core/client/impl/HuaweiSmsClient.java | 8 +- .../server/controller/DefaultController.java | 32 ++++-- 12 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataBridgeMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java index 9e75113d0a..e1e0ac08e7 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java @@ -7,13 +7,15 @@ import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import jakarta.servlet.http.HttpServletRequest; import java.net.URI; +import java.net.URLEncoder; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; /** @@ -23,6 +25,16 @@ import java.util.Map; */ public class HttpUtils { + /** + * 编码 URL 参数 + * + * @param value 参数 + * @return 编码后的参数 + */ + public static String encodeUtf8(String value) { + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } + @SuppressWarnings("unchecked") public static String replaceUrlQuery(String url, String key, String value) { UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset()); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index 12731edad6..905f5d5416 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -98,4 +98,8 @@ public class ServletUtils { return JakartaServletUtil.getParamMap(request); } + public static Map getHeaderMap(HttpServletRequest request) { + return JakartaServletUtil.getHeaderMap(request); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index f5c4b83139..eb037d9e17 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.excel.core.util; +import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.converters.longconverter.LongStringConverter; @@ -8,8 +9,6 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -40,7 +39,7 @@ public class ExcelUtils { .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 .sheet(sheetName).doWrite(data); // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name())); + response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename)); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java index 8970c004cf..b25870fe82 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.infra.framework.file.core.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import com.alibaba.ttl.TransmittableThreadLocal; import jakarta.servlet.http.HttpServletResponse; import lombok.SneakyThrows; import org.apache.tika.Tika; import java.io.IOException; -import java.net.URLEncoder; /** * 文件类型 Utils @@ -60,7 +60,7 @@ public class FileTypeUtils { */ public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { // 设置 header 和 contentType - response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.setHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename)); String contentType = getMineType(content, filename); response.setContentType(contentType); // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataBridgeMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataBridgeMapper.java new file mode 100644 index 0000000000..076b341f00 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataBridgeMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.rule; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface IotDataBridgeMapper extends BaseMapperX { +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java new file mode 100644 index 0000000000..cbf0b36c23 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.iot.service.rule; + +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; + +/** + * IoT 数据桥梁的 Service 接口 + * + * @author 芋道源码 + */ +public interface IotDataBridgeService { + + /** + * 获得指定数据桥梁 + * + * @param id 数据桥梁编号 + * @return 数据桥梁 + */ + IotDataBridgeDO getIotDataBridge(Long id); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java new file mode 100644 index 0000000000..7814fd9bbc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.iot.service.rule; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; +import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataBridgeMapper; +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Objects; + +/** + * IoT 数据桥梁的 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class IotDataBridgeServiceImpl implements IotDataBridgeService { + + @Resource + private IotDataBridgeMapper dataBridgeMapper; + + // TODO @芋艿:临时测试 + @Override + public IotDataBridgeDO getIotDataBridge(Long id) { + if (Objects.equals(id, 1L)) { + IotDataBridgeDO.HttpConfig config = new IotDataBridgeDO.HttpConfig() + .setUrl("http://127.0.0.1:48080/test") +// .setMethod("POST") + .setMethod("GET") + .setQuery(MapUtil.of("aaa", "bbb")) + .setHeaders(MapUtil.of("ccc", "ddd")) + .setBody(JsonUtils.toJsonString(MapUtil.of("eee", "fff"))); + return IotDataBridgeDO.builder().id(1L).name("芋道").description("芋道源码").status(0).direction(1) + .type(IotDataBridgTypeEnum.HTTP.getType()).config(config).build(); + } + return dataBridgeMapper.selectById(id); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java index e58821ea75..fe9cd636b0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java @@ -139,6 +139,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { ruleScene01.getTriggers().add(trigger01); // 动作 ruleScene01.setActions(CollUtil.newArrayList()); + // 设备控制 IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig(); action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType()); IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl(); @@ -151,7 +152,12 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { .put("color", "red") .build()); action01.setDeviceControl(actionDeviceControl01); - ruleScene01.getActions().add(action01); +// ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了 + // 数据桥接(http) + IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig(); + action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType()); + action02.setDataBridgeId(1L); + ruleScene01.getActions().add(action02); return ListUtil.toList(ruleScene01); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java index 7f77ef3f43..7774368d28 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java @@ -1,9 +1,28 @@ package cn.iocoder.yudao.module.iot.service.rule.action; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.http.HttpUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; +import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import java.util.HashMap; +import java.util.Map; + +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; /** * IoT 数据桥梁的 {@link IotRuleSceneAction} 实现类 @@ -11,11 +30,38 @@ import org.springframework.stereotype.Component; * @author 芋道源码 */ @Component +@Slf4j public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { + @Resource + private RestTemplate restTemplate; + + @Resource + private IotDataBridgeService dataBridgeService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + @Override public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) { - // TODO @芋艿:http + // 1. 获得数据桥梁 + Assert.notNull(config.getDataBridgeId(), "数据桥梁编号不能为空"); + IotDataBridgeDO dataBridge = dataBridgeService.getIotDataBridge(config.getDataBridgeId()); + if (dataBridge == null || dataBridge.getConfig() == null) { + log.error("[execute][message({}) config({}) 对应的数据桥梁不存在]", message, config); + return; + } + if (CommonStatusEnum.isDisable(dataBridge.getStatus())) { + log.info("[execute][message({}) config({}) 对应的数据桥梁({}) 状态为禁用]", message, config, dataBridge); + return; + } + + // 2.1 执行 HTTP 请求 + // TODO @芋艿:groovy 或者 javascript 实现数据的转换;可以考虑基于 hutool 的 ScriptUtil 做 + if (IotDataBridgTypeEnum.HTTP.getType().equals(dataBridge.getType())) { + executeHttp(message, (IotDataBridgeDO.HttpConfig) dataBridge.getConfig()); + return; + } + // TODO @芋艿:mq-redis // TODO @芋艿:mq-数据库 // TODO @芋艿:kafka @@ -23,6 +69,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { // TODO @芋艿:rabbitmq // TODO @芋艿:mqtt // TODO @芋艿:tcp + // TODO @芋艿:websocket } @Override @@ -30,4 +77,54 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { return IotRuleSceneActionTypeEnum.DATA_BRIDGE; } + @SuppressWarnings({"unchecked", "deprecation"}) + private void executeHttp(IotDeviceMessage message, IotDataBridgeDO.HttpConfig config) { + String url = null; + HttpMethod method = HttpMethod.valueOf(config.getMethod().toUpperCase()); + HttpEntity requestEntity = null; + ResponseEntity responseEntity = null; + try { + // 1.1 构建 Header + HttpHeaders headers = new HttpHeaders(); + if (CollUtil.isNotEmpty(config.getHeaders())) { + config.getHeaders().putAll(config.getHeaders()); + } + headers.add(HEADER_TENANT_ID, message.getTenantId().toString()); + // 1.2 构建 URL + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(config.getUrl()); + if (CollUtil.isNotEmpty(config.getQuery())) { + config.getQuery().forEach(uriBuilder::queryParam); + } + // 1.3 构建请求体 + if (method == HttpMethod.GET) { + uriBuilder.queryParam("message", HttpUtils.encodeUtf8(JsonUtils.toJsonString(message))); + url = uriBuilder.build().toUriString(); + requestEntity = new HttpEntity<>(headers); + } else { + url = uriBuilder.build().toUriString(); + Map requestBody = JsonUtils.parseObject(config.getBody(), Map.class); + if (requestBody == null) { + requestBody = new HashMap<>(); + } + requestBody.put("message", message); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); + requestEntity = new HttpEntity<>(JsonUtils.toJsonString(requestBody), headers); + } + + // 2.1 发送请求 + responseEntity = restTemplate.exchange(url, method, requestEntity, String.class); + // 2.2 记录日志 + if (responseEntity.getStatusCode().is2xxSuccessful()) { + log.info("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求成功({})]", + message, config, url, method, requestEntity, responseEntity); + } else { + log.error("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求失败({})]", + message, config, url, method, requestEntity, responseEntity); + } + } catch (Exception e) { + log.error("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求异常({})]", + message, config, url, method, requestEntity, responseEntity, e); + } + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java index 558dbdef27..3dd12491a9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java @@ -184,7 +184,7 @@ public class AliyunSmsClient extends AbstractSmsClient { @SneakyThrows private static String percentCode(String str) { Assert.notNull(str, "str 不能为空"); - return URLEncoder.encode(str, StandardCharsets.UTF_8.name()) + return HttpUtils.encodeUtf8(str) .replace("+", "%20") // 加号 "+" 被替换为 "%20" .replace("*", "%2A") // 星号 "*" 被替换为 "%2A" .replace("%7E", "~"); // 波浪号 "%7E" 被替换为 "~" diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java index 82f55395e8..622f8ac1b9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.http.HttpUtil; @@ -19,8 +18,6 @@ import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditS import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.time.LocalDateTime; @@ -156,10 +153,9 @@ public class HuaweiSmsClient extends AbstractSmsClient { .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(null); } - @SuppressWarnings("CharsetObjectCanBeUsed") - private static void appendToBody(StringBuilder body, String key, String value) throws UnsupportedEncodingException { + private static void appendToBody(StringBuilder body, String key, String value) { if (StrUtil.isNotEmpty(value)) { - body.append(key).append(URLEncoder.encode(value, CharsetUtil.CHARSET_UTF_8.name())); + body.append(key).append(HttpUtils.encodeUtf8(value)); } } diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java index 2bf6e52775..f0e3878334 100644 --- a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.server.controller; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import jakarta.annotation.security.PermitAll; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,6 +17,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC * @author 芋道源码 */ @RestController +@Slf4j public class DefaultController { @RequestMapping("/admin-api/bpm/**") @@ -27,9 +32,9 @@ public class DefaultController { "[微信公众号 yudao-module-mp - 已禁用][参考 https://doc.iocoder.cn/mp/build/ 开启]"); } - @RequestMapping(value = {"/admin-api/product/**", // 商品中心 + @RequestMapping(value = { "/admin-api/product/**", // 商品中心 "/admin-api/trade/**", // 交易中心 - "/admin-api/promotion/**"}) // 营销中心 + "/admin-api/promotion/**" }) // 营销中心 public CommonResult mall404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); @@ -47,28 +52,43 @@ public class DefaultController { "[CRM 模块 yudao-module-crm - 已禁用][参考 https://doc.iocoder.cn/crm/build/ 开启]"); } - @RequestMapping(value = {"/admin-api/report/**"}) + @RequestMapping(value = { "/admin-api/report/**"}) public CommonResult report404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[报表模块 yudao-module-report - 已禁用][参考 https://doc.iocoder.cn/report/ 开启]"); } - @RequestMapping(value = {"/admin-api/pay/**"}) + @RequestMapping(value = { "/admin-api/pay/**"}) public CommonResult pay404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[支付模块 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]"); } - @RequestMapping(value = {"/admin-api/ai/**"}) + @RequestMapping(value = { "/admin-api/ai/**"}) public CommonResult ai404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]"); } - @RequestMapping(value = {"/admin-api/iot/**"}) + @RequestMapping(value = { "/admin-api/iot/**"}) public CommonResult iot404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]"); } + /** + * 测试接口:打印 query、header、body + */ + @RequestMapping(value = { "/test" }) + @PermitAll + public CommonResult test(HttpServletRequest request) { + // 打印查询参数 + log.info("Query: {}", ServletUtils.getParamMap(request)); + // 打印请求头 + log.info("Header: {}", ServletUtils.getHeaderMap(request)); + // 打印请求体 + log.info("Body: {}", ServletUtils.getBody(request)); + return CommonResult.success(true); + } + }