接下来我们定义一个枚举类,方便我们去匹配对应的报文转换实现类。
package com.lifengdi.gateway.enums; import lombok.Getter; import org.apache.commons.lang.StringUtils; import org.springframework.lang.Nullable; /** * 报文结构转换转换类型枚举类 * * @author: Li Fengdi * @date: 2020-7-11 16:57:07 */ @Getter public enum TransformContentTypeEnum { DEFAULT(null, "jsonMessageTransformImpl") , APPLICATION_JSON("application/json", "jsonMessageTransformImpl") ; /** * 内容类型 */ private String contentType; /** * 报文转换结构实现类 */ private String transImpl; TransformContentTypeEnum(String contentType, String transImpl) { this.contentType = contentType; this.transImpl = transImpl; } /** * 根据contentType获取对应枚举 * <p> * 如果contentType为空则返回默认枚举 * </p> * * @param contentType contentType * @return TransformContentTypeEnum */ public static TransformContentTypeEnum getWithDefault(@Nullable String contentType) { if (StringUtils.isNotBlank(contentType)) { for (TransformContentTypeEnum transformContentTypeEnum : values()) { if (contentType.equals(transformContentTypeEnum.contentType)) { return transformContentTypeEnum; } } } return DEFAULT; } }这个类也很简单,定义枚举,然后一个静态方法,静态方法的作用是根据响应头中的contentType来获取对应的报文结构转换实现类,如果获取不到,则会返回一个默认的实现类,我这里定义的默认的实现类就是我们上边写的JsonMessageTransformImpl类。
最后呢,我们定义一个工厂类,供我们的Filter调用。
package com.lifengdi.gateway.transform; import com.lifengdi.gateway.enums.TransformContentTypeEnum; import com.lifengdi.gateway.properties.MessageTransformProperties; import com.lifengdi.gateway.properties.entity.MessageTransformUrl; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.nio.charset.Charset; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; /** * 报文结构转换工厂类 * * @author: Li Fengdi * @date: 2020-7-11 16:57:07 */ @Component public class MessageTransformFactory { @Resource private Map<String, AbstractMessageTransform> messageTransformMap; @Resource private MessageTransformProperties messageTransformProperties; /** * 根据contentType获取对应的内容转换实现类 * * @param contentType 内容类型 * @return 内容转换实现类 */ private AbstractMessageTransform getMessageTransform(String contentType) { return messageTransformMap.get(TransformContentTypeEnum.getWithDefault(contentType).getTransImpl()); } /** * 报文转换 * * @param originalContent 原始内容 * @param transformUrl url * @return 转换后的消息 */ private String messageTransform(String originalContent, MessageTransformUrl transformUrl) { String contentType = transformUrl.getContentType(); AbstractMessageTransform messageTransform = getMessageTransform(contentType); return messageTransform.transform(originalContent, transformUrl); } /** * 判断是否是需要转换报文结构的接口,如果是则转换,否则返回原值 * * @param path 接口路径 * @param originalContent 原始内容 * @return 转换后的内容 */ public String compareAndTransform(String path, String originalContent) { if (StringUtils.isBlank(originalContent)) { return null; } List<MessageTransformUrl> urlList = messageTransformProperties.getUrlList(); if (CollectionUtils.isEmpty(urlList)) { return originalContent; } return urlList .stream() .filter(transformUrl -> transformUrl.getPathList().contains(path)) .findFirst() .map(url -> messageTransform(originalContent, url)) .orElse(originalContent); } /** * 判断是否是需要转换报文结构的接口,如果是则转换,否则返回原值 * * @param path 接口路径 * @param originalContent 原始内容 * @param originalByteArray 二进制原始内容 * @param charset charset * @param newResponseBody 新报文内容 * @return 响应体数组数组 */ public byte[] compareAndTransform(String path, String originalContent, byte[] originalByteArray, Charset charset, AtomicReference<String> newResponseBody) { if (StringUtils.isBlank(originalContent)) { return null; } List<MessageTransformUrl> urlList = messageTransformProperties.getUrlList(); if (CollectionUtils.isEmpty(urlList)) { return originalByteArray; } return urlList.stream() .filter(transformUrl -> transformUrl.getPathList().contains(path)) .findFirst() .map(url -> { String messageTransform = messageTransform(originalContent, url); if (originalContent.equals(messageTransform)) { return originalByteArray; } newResponseBody.set(messageTransform); return messageTransform.getBytes(charset); }) .orElse(originalByteArray); } }这个工厂对外提供的方法只有compareAndTransform()两个方法,主要功能就是判断是否是需要转换报文结构的接口,如果是则转换,否则返回原值。
接下来就是在我们的Filter调用即可。调用代码如下:
content = messageTransformFactory.compareAndTransform(path, responseBody, content, charset, newResponseBody);Git地址:https://github.com/lifengdi/spring-cloud-gateway-demo
最后上面的只是简单的示例,很多情况都没有考虑进去,大家借鉴即可。
原文地址:https://www.lifengdi.com/archives/article/2006