cc.shacocloud.mirage.web.AbstractMessageConverterMethodArgumentResolver Maven / Gradle / Ivy
package cc.shacocloud.mirage.web;
import cc.shacocloud.mirage.utils.SelfSortList;
import cc.shacocloud.mirage.web.exception.HttpMediaTypeNotSupportedException;
import cc.shacocloud.mirage.web.exception.InvalidMediaTypeException;
import cc.shacocloud.mirage.web.http.GenericHttpMessageConverter;
import cc.shacocloud.mirage.web.http.HttpMessageConverter;
import cc.shacocloud.mirage.web.http.MediaType;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.OrderUtils;
import java.lang.reflect.Type;
import java.util.*;
/**
* 基类,用于通过从与请求的主体读取解决方法参数值 HttpMessageConverters
*/
public abstract class AbstractMessageConverterMethodArgumentResolver implements HandleMethodArgumentResolver {
private static final Set SUPPORTED_METHODS = new HashSet<>(Arrays.asList(HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH));
protected final Log logger = LogFactory.getLog(getClass());
protected final List> messageConverters
= new SelfSortList<>(n -> OrderUtils.getOrder(n.getClass(), Ordered.LOWEST_PRECEDENCE));
protected final List allSupportedMediaTypes;
protected AbstractMessageConverterMethodArgumentResolver(List> messageConverters) {
this.messageConverters.addAll(messageConverters);
this.allSupportedMediaTypes = getAllSupportedMediaTypes(messageConverters);
}
/**
* 通过从给定的 VertXRoutingContext 中读取来创建预期参数类型的方法参数值
*
* @param 要创建的参数值的预期类型
* @param request 当前请求对象
* @param parameter 方法参数描述符
* @param targetType 目标类型,不一定与方法参数类型相同
* @return 创建的方法参数值
*/
@SuppressWarnings("unchecked")
protected Future> readWithMessageConverters(HttpRequest request,
MethodParameter parameter,
Type targetType) {
MediaType contentType;
boolean noContentType = false;
try {
contentType = request.headers().getContentType();
if (logger.isDebugEnabled()) {
logger.debug("从请求中找到预设的 'Content-Type' : " + contentType);
}
} catch (InvalidMediaTypeException ex) {
return Future.failedFuture(new HttpMediaTypeNotSupportedException(ex.getMessage()));
}
if (contentType == null) {
noContentType = true;
contentType = MediaType.APPLICATION_OCTET_STREAM;
if (logger.isDebugEnabled()) {
logger.debug("请求中未预设 'Content-Type' 使用默认值: " + contentType);
}
}
Class> contextClass = parameter.getContainingClass();
Class targetClass = (targetType instanceof Class ? (Class) targetType : null);
if (targetClass == null) {
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
targetClass = (Class) resolvableType.resolve();
}
HttpMethod httpMethod = request.method();
Future> bodyFuture = null;
// 循环所有的消息转换器
for (HttpMessageConverter> converter : this.messageConverters) {
// 如果是 基于 GenericHttpMessageConverter 的实现 则使用 GenericHttpMessageConverter来判断
GenericHttpMessageConverter> genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter>) converter : null);
if (genericConverter != null ? genericConverter.canRead(parameter, targetType, contextClass, contentType) :
(targetClass != null && converter.canRead(parameter, targetClass, contentType))) {
if (logger.isDebugEnabled()) {
logger.debug("匹配到参数解析处理类:" + (genericConverter != null ? genericConverter : converter));
}
// 读取数据
bodyFuture = (genericConverter != null ? genericConverter.read(parameter, targetType, contextClass, request) :
((HttpMessageConverter) converter).read(parameter, targetClass, request));
if (bodyFuture != null) break;
}
}
// 如果消息主体为空
if (bodyFuture == null) {
if (logger.isDebugEnabled()) {
logger.debug("方法参数 '" + parameter.getParameterName() + "' 未匹配到参数解析处理类!");
}
Buffer requestBody = request.getBody();
if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod)
|| (noContentType && (requestBody == null || requestBody.length() == 0))) {
return Future.succeededFuture();
}
return Future.failedFuture(new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes));
}
return bodyFuture;
}
/**
* 通过{@link MediaType#sortBySpecificity(List)}返回所有提供的按特异性排序*的消息转换器支持的媒体类型。
*/
private static List getAllSupportedMediaTypes(List> messageConverters) {
Set allSupportedMediaTypes = new LinkedHashSet<>();
for (HttpMessageConverter> messageConverter : messageConverters) {
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
}
List result = new ArrayList<>(allSupportedMediaTypes);
MediaType.sortBySpecificity(result);
return Collections.unmodifiableList(result);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy