diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/adapter/impl/WeworkChannelAdapter.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/adapter/impl/WeworkChannelAdapter.java index 7e3db327..5db78dad 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/adapter/impl/WeworkChannelAdapter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/adapter/impl/WeworkChannelAdapter.java @@ -1,9 +1,9 @@ package com.qqchen.deploy.backend.notification.adapter.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import com.qqchen.deploy.backend.framework.utils.JsonUtils; import com.qqchen.deploy.backend.notification.adapter.INotificationChannelAdapter; import com.qqchen.deploy.backend.notification.dto.WeworkSendNotificationRequest; +import com.qqchen.deploy.backend.notification.dto.wework.WeworkWebhookRequest; import com.qqchen.deploy.backend.notification.entity.config.WeworkNotificationConfig; import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum; @@ -11,20 +11,15 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.io.File; - -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -40,7 +35,6 @@ public class WeworkChannelAdapter implements INotificationChannelAdapter markdownContent = new HashMap<>(); - markdownContent.put("content", request.getContent()); - messageBody.put("markdown", markdownContent); - } else { - // 纯文本消息 - Map textContent = new HashMap<>(); - textContent.put("content", request.getContent()); - - // 添加@人列表 - if (!CollectionUtils.isEmpty(request.getMentionedUserList())) { - textContent.put("mentioned_list", request.getMentionedUserList()); - } - - if (!CollectionUtils.isEmpty(request.getMentionedMobileList())) { - textContent.put("mentioned_mobile_list", request.getMentionedMobileList()); - } - - messageBody.put("text", textContent); - } + log.info("发送企业微信通知 - URL: {}, 类型: {}, 消息: {}", + webhookUrl, request.getMessageType().getApiType(), request.getContent()); - // 发送请求 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - - String jsonBody = objectMapper.writeValueAsString(messageBody); - HttpEntity entity = new HttpEntity<>(jsonBody, headers); - - log.info("发送企业微信通知 - URL: {}, 类型: {}, 消息: {}", webhookUrl, msgType, request.getContent()); - - String response = restTemplate.exchange( - webhookUrl, - HttpMethod.POST, - entity, - String.class - ).getBody(); + // RestTemplate 自动序列化对象为JSON + String response = restTemplate.postForObject(webhookUrl, webhookRequest, String.class); log.info("企业微信通知发送成功 - 响应: {}", response); } @@ -112,7 +71,7 @@ public class WeworkChannelAdapter implements INotificationChannelAdapter entity = new HttpEntity<>(jsonBody, headers); - - log.info("发送企业微信文件消息 - 文件: {}", request.getFileName()); - - String response = restTemplate.exchange( - sendUrl, - HttpMethod.POST, - entity, - String.class - ).getBody(); + // RestTemplate 自动序列化对象为JSON + String response = restTemplate.postForObject(sendUrl, webhookRequest, String.class); log.info("企业微信文件消息发送成功 - 响应: {}", response); } @@ -168,24 +117,17 @@ public class WeworkChannelAdapter implements INotificationChannelAdapter textContent = new HashMap<>(); - textContent.put("content", "【测试消息】\n这是一条来自 Deploy Ease Platform 的测试消息,您的企业微信通知渠道配置正常!"); - messageBody.put("text", textContent); - - // 3. 发送测试请求 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - - String jsonBody = objectMapper.writeValueAsString(messageBody); - HttpEntity entity = new HttpEntity<>(jsonBody, headers); + // 3. 构建测试消息 + WeworkWebhookRequest testRequest = WeworkWebhookRequest.builder() + .msgtype("text") + .text(WeworkWebhookRequest.TextContent.builder() + .content("【测试消息】\n这是一条来自 Deploy Ease Platform 的测试消息,您的企业微信通知渠道配置正常!") + .build()) + .build(); log.info("测试企业微信连接 - URL: {}", webhookUrl); - String response = restTemplate.exchange( - webhookUrl, - HttpMethod.POST, - entity, - String.class - ).getBody(); + // 4. 发送测试请求(RestTemplate 自动序列化对象为JSON) + String response = restTemplate.postForObject(webhookUrl, testRequest, String.class); log.info("企业微信连接测试成功 - 响应: {}", response); - // 4. 检查响应 + // 5. 检查响应 if (response != null && response.contains("\"errcode\":0")) { log.info("企业微信通知渠道测试成功"); } else { @@ -322,18 +253,6 @@ public class WeworkChannelAdapter implements INotificationChannelAdapter buildFileMessage(String mediaId) { - Map message = new HashMap<>(); - message.put("msgtype", "file"); - - Map file = new HashMap<>(); - file.put("media_id", mediaId); - - message.put("file", file); - return message; - } + } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationChannelConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationChannelConverter.java index 4a1e47da..8a0a2c4d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationChannelConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationChannelConverter.java @@ -9,7 +9,6 @@ import com.qqchen.deploy.backend.notification.entity.config.EmailNotificationCon import com.qqchen.deploy.backend.notification.entity.config.WeworkNotificationConfig; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.springframework.beans.factory.annotation.Autowired; import java.util.Map; @@ -22,24 +21,17 @@ import java.util.Map; @Mapper(config = BaseConverter.class) public abstract class NotificationChannelConverter implements BaseConverter { - protected NotificationConfigConverter notificationConfigConverter; - - @Autowired - public void setNotificationConfigConverter(NotificationConfigConverter notificationConfigConverter) { - this.notificationConfigConverter = notificationConfigConverter; - } - /** * Entity -> DTO - * config: Map -> BaseNotificationConfigDTO + * config: Map -> BaseNotificationConfig */ @Override - @Mapping(target = "config", expression = "java(mapToConfigDTO(entity))") + @Mapping(target = "config", expression = "java(mapToConfig(entity))") public abstract NotificationChannelDTO toDto(NotificationChannel entity); /** * DTO -> Entity - * config: BaseNotificationConfigDTO -> Map + * config: BaseNotificationConfig -> Map */ @Override @Mapping(target = "config", expression = "java(mapToConfigMap(dto))") @@ -47,7 +39,7 @@ public abstract class NotificationChannelConverter implements BaseConverter Map + * config: BaseNotificationConfig -> Map */ @Override public void updateEntity(NotificationChannel entity, NotificationChannelDTO dto) { @@ -66,37 +58,31 @@ public abstract class NotificationChannelConverter implements BaseConverter BaseNotificationConfig Entity - BaseNotificationConfig configEntity = switch (entity.getChannelType()) { + // Map -> BaseNotificationConfig(根据渠道类型自动识别) + return switch (entity.getChannelType()) { case WEWORK -> JsonUtils.fromMap(entity.getConfig(), WeworkNotificationConfig.class); case EMAIL -> JsonUtils.fromMap(entity.getConfig(), EmailNotificationConfig.class); default -> throw new IllegalArgumentException("不支持的渠道类型: " + entity.getChannelType()); }; - - // 2. BaseNotificationConfig Entity -> BaseNotificationConfigDTO - return notificationConfigConverter.toDto(configEntity); } /** - * 将DTO配置转换为Entity的Map + * 将Config对象转换为Entity的Map */ protected Map mapToConfigMap(NotificationChannelDTO dto) { if (dto == null || dto.getConfig() == null) { return null; } - // 1. BaseNotificationConfigDTO -> BaseNotificationConfig Entity - BaseNotificationConfig configEntity = notificationConfigConverter.toEntity(dto.getConfig()); - - // 2. BaseNotificationConfig Entity -> Map - return JsonUtils.toMap(configEntity); + // BaseNotificationConfig -> Map + return JsonUtils.toMap(dto.getConfig()); } } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationConfigConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationConfigConverter.java deleted file mode 100644 index f31dadc8..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/converter/NotificationConfigConverter.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.qqchen.deploy.backend.notification.converter; - -import com.qqchen.deploy.backend.notification.dto.*; -import com.qqchen.deploy.backend.notification.entity.config.BaseNotificationConfig; -import com.qqchen.deploy.backend.notification.entity.config.EmailNotificationConfig; -import com.qqchen.deploy.backend.notification.entity.config.WeworkNotificationConfig; -import org.mapstruct.Mapper; - -/** - * 通知配置转换器 - * 负责Entity配置和DTO配置之间的转换 - * - * @author qqchen - * @since 2025-11-12 - */ -@Mapper(componentModel = "spring") -public interface NotificationConfigConverter { - - // Entity -> DTO - WeworkNotificationConfigDTO toDto(WeworkNotificationConfig entity); - EmailNotificationConfigDTO toDto(EmailNotificationConfig entity); - - // DTO -> Entity - WeworkNotificationConfig toEntity(WeworkNotificationConfigDTO dto); - EmailNotificationConfig toEntity(EmailNotificationConfigDTO dto); - - /** - * 根据类型自动转换 Entity -> DTO - */ - default BaseNotificationConfigDTO toDto(BaseNotificationConfig entity) { - if (entity == null) { - return null; - } - - if (entity instanceof WeworkNotificationConfig) { - return toDto((WeworkNotificationConfig) entity); - } else if (entity instanceof EmailNotificationConfig) { - return toDto((EmailNotificationConfig) entity); - } - - throw new IllegalArgumentException("不支持的配置类型: " + entity.getClass().getName()); - } - - /** - * 根据类型自动转换 DTO -> Entity - */ - default BaseNotificationConfig toEntity(BaseNotificationConfigDTO dto) { - if (dto == null) { - return null; - } - - if (dto instanceof WeworkNotificationConfigDTO) { - return toEntity((WeworkNotificationConfigDTO) dto); - } else if (dto instanceof EmailNotificationConfigDTO) { - return toEntity((EmailNotificationConfigDTO) dto); - } - - throw new IllegalArgumentException("不支持的配置类型: " + dto.getClass().getName()); - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/BaseNotificationConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/BaseNotificationConfigDTO.java deleted file mode 100644 index eaa546d7..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/BaseNotificationConfigDTO.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.qqchen.deploy.backend.notification.dto; - -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; -import lombok.Data; - -/** - * 通知配置DTO基类 - * 用于数据传输层,与Entity层的BaseNotificationConfig对应 - * - * 使用 EXISTING_PROPERTY 方式,利用外层 NotificationChannelDTO 的 channelType 字段 - * 进行多态反序列化,无需在 config 内部添加额外的 type 字段 - * - * @author qqchen - * @since 2025-11-12 - */ -@Data -@JsonTypeInfo( - use = JsonTypeInfo.Id.NAME, - include = JsonTypeInfo.As.PROPERTY, - property = "channelType" -) -@JsonSubTypes({ - @JsonSubTypes.Type(value = WeworkNotificationConfigDTO.class, name = "WEWORK"), - @JsonSubTypes.Type(value = EmailNotificationConfigDTO.class, name = "EMAIL") -}) -public abstract class BaseNotificationConfigDTO { - - /** - * 获取渠道类型(与外层 NotificationChannelDTO.channelType 保持一致) - */ - public abstract NotificationChannelTypeEnum getChannelType(); -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/EmailNotificationConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/EmailNotificationConfigDTO.java deleted file mode 100644 index 549803d8..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/EmailNotificationConfigDTO.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.qqchen.deploy.backend.notification.dto; - -import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 邮件通知配置DTO - * - * @author qqchen - * @since 2025-11-12 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class EmailNotificationConfigDTO extends BaseNotificationConfigDTO { - - /** - * 渠道类型(用于Jackson反序列化,与外层保持一致) - */ - private final NotificationChannelTypeEnum channelType = NotificationChannelTypeEnum.EMAIL; - - /** - * SMTP服务器地址(必填) - */ - private String smtpHost; - - /** - * SMTP服务器端口(必填) - */ - private Integer smtpPort; - - /** - * SMTP用户名(必填) - */ - private String username; - - /** - * SMTP密码(必填) - */ - private String password; - - /** - * 发件人邮箱(必填) - */ - private String from; - - /** - * 发件人名称(可选) - */ - private String fromName; - - /** - * 是否使用SSL(可选,默认true) - */ - private Boolean useSsl = true; - - @Override - public NotificationChannelTypeEnum getChannelType() { - return NotificationChannelTypeEnum.EMAIL; - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationChannelDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationChannelDTO.java index ef94190c..33c1edb9 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationChannelDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/NotificationChannelDTO.java @@ -1,6 +1,7 @@ package com.qqchen.deploy.backend.notification.dto; import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import com.qqchen.deploy.backend.notification.entity.config.BaseNotificationConfig; import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -29,7 +30,7 @@ public class NotificationChannelDTO extends BaseDTO { @Schema(description = "渠道配置(根据渠道类型不同而不同)") @NotNull(message = "渠道配置不能为空") - private BaseNotificationConfigDTO config; + private BaseNotificationConfig config; @Schema(description = "是否启用", example = "true") private Boolean enabled; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkNotificationConfigDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkNotificationConfigDTO.java deleted file mode 100644 index 2b096dbb..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkNotificationConfigDTO.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.qqchen.deploy.backend.notification.dto; - -import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 企业微信通知配置DTO - * - * @author qqchen - * @since 2025-11-12 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class WeworkNotificationConfigDTO extends BaseNotificationConfigDTO { - - /** - * 渠道类型(用于Jackson反序列化,与外层保持一致) - */ - private final NotificationChannelTypeEnum channelType = NotificationChannelTypeEnum.WEWORK; - - /** - * 企业微信机器人 Webhook Key(必填) - * 完整URL格式: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key} - */ - private String key; - - @Override - public NotificationChannelTypeEnum getChannelType() { - return NotificationChannelTypeEnum.WEWORK; - } -} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkSendNotificationRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkSendNotificationRequest.java index 88a0af3a..1f44ea99 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkSendNotificationRequest.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/dto/WeworkSendNotificationRequest.java @@ -1,5 +1,6 @@ package com.qqchen.deploy.backend.notification.dto; +import com.qqchen.deploy.backend.notification.dto.wework.WeworkWebhookRequest; import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; import com.qqchen.deploy.backend.notification.enums.WeworkMessageTypeEnum; import lombok.Data; @@ -56,4 +57,71 @@ public class WeworkSendNotificationRequest extends BaseSendNotificationRequest { public NotificationChannelTypeEnum getChannelType() { return NotificationChannelTypeEnum.WEWORK; } + + /** + * 转换为企微 Webhook API 请求格式 + * + * @return 企微API标准格式的请求对象 + * @throws UnsupportedOperationException 当消息类型为FILE时抛出,需使用 toWebhookRequest(String mediaId) + */ + public WeworkWebhookRequest toWebhookRequest() { + return switch (messageType) { + case TEXT -> buildTextRequest(); + case MARKDOWN -> buildMarkdownRequest(); + case FILE -> throw new UnsupportedOperationException( + "文件消息需要先上传获取media_id,请使用 toWebhookRequest(String mediaId)"); + }; + } + + /** + * 转换为文件消息格式(需要提供已上传的media_id) + * + * @param mediaId 企业微信文件上传后返回的media_id + * @return 企微API标准格式的请求对象 + * @throws IllegalStateException 当消息类型不是FILE时抛出 + */ + public WeworkWebhookRequest toWebhookRequest(String mediaId) { + if (messageType != WeworkMessageTypeEnum.FILE) { + throw new IllegalStateException("只有FILE类型消息才能使用此方法"); + } + return buildFileRequest(mediaId); + } + + /** + * 构建文本消息请求 + */ + private WeworkWebhookRequest buildTextRequest() { + return WeworkWebhookRequest.builder() + .msgtype(WeworkMessageTypeEnum.TEXT.getApiType()) + .text(WeworkWebhookRequest.TextContent.builder() + .content(getContent()) + .mentionedList(mentionedUserList) + .mentionedMobileList(mentionedMobileList) + .build()) + .build(); + } + + /** + * 构建Markdown消息请求 + */ + private WeworkWebhookRequest buildMarkdownRequest() { + return WeworkWebhookRequest.builder() + .msgtype(WeworkMessageTypeEnum.MARKDOWN.getApiType()) + .markdown(WeworkWebhookRequest.MarkdownContent.builder() + .content(getContent()) + .build()) + .build(); + } + + /** + * 构建文件消息请求 + */ + private WeworkWebhookRequest buildFileRequest(String mediaId) { + return WeworkWebhookRequest.builder() + .msgtype(WeworkMessageTypeEnum.FILE.getApiType()) + .file(WeworkWebhookRequest.FileContent.builder() + .mediaId(mediaId) + .build()) + .build(); + } } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseNotificationConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseNotificationConfig.java index 61d48d31..515692bc 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseNotificationConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/entity/config/BaseNotificationConfig.java @@ -1,16 +1,30 @@ package com.qqchen.deploy.backend.notification.entity.config; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.qqchen.deploy.backend.notification.enums.NotificationChannelTypeEnum; import lombok.Data; /** * 通知配置基类 * 提取各渠道配置的共用字段 + * + * 支持 Jackson 多态反序列化: + * 利用外层 NotificationChannelDTO 的 channelType 字段进行类型识别 * * @author qqchen * @since 2025-11-12 */ @Data +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.PROPERTY, + property = "channelType" +) +@JsonSubTypes({ + @JsonSubTypes.Type(value = WeworkNotificationConfig.class, name = "WEWORK"), + @JsonSubTypes.Type(value = EmailNotificationConfig.class, name = "EMAIL") +}) public abstract class BaseNotificationConfig { /** diff --git a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationChannelServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationChannelServiceImpl.java index 75b444fa..7251302c 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationChannelServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/notification/service/impl/NotificationChannelServiceImpl.java @@ -110,53 +110,6 @@ public class NotificationChannelServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.NOTIFICATION_CHANNEL_NOT_FOUND)); - - // 3. 校验渠道状态 - if (!channel.getEnabled()) { - throw new BusinessException(ResponseCode.NOTIFICATION_CHANNEL_DISABLED); - } - - // 4. 获取对应的适配器 - INotificationChannelAdapter adapter; - try { - adapter = adapterFactory.getAdapter(channel.getChannelType()); - } catch (IllegalArgumentException e) { - log.error("获取通知渠道适配器失败: {}", e.getMessage()); - throw new BusinessException(ResponseCode.ERROR); - } - - // 5. 转换配置 - BaseNotificationConfig config = convertConfig(channel); - - // 6. 发送通知 - try { - log.info("发送通知 - 渠道ID: {}, 渠道类型: {}, 内容: {}", channel.getId(), channel.getChannelType(), request.getContent()); - - adapter.send(config, request); - - log.info("通知发送成功 - 渠道ID: {}", channel.getId()); - } catch (IllegalArgumentException e) { - // 配置错误(如 Webhook Key 未配置) - log.error("通知渠道配置错误 - 渠道ID: {}, 错误: {}", channel.getId(), e.getMessage()); - throw new BusinessException(ResponseCode.NOTIFICATION_CHANNEL_CONFIG_ERROR, new Object[] {e.getMessage()}); - } catch (Exception e) { - log.error("通知发送失败 - 渠道ID: {}, 错误: {}", channel.getId(), e.getMessage(), e); - throw new BusinessException(ResponseCode.NOTIFICATION_SEND_FAILED, new Object[] {e.getMessage()}); - } - } /** * 将Map配置转换为具体的配置类型