spring cloud feign客户端调用JSON数据接口对自定义类型反序列化失败源码分析

源码

  • org.springframework.cloud.openfeign.support.SpringDecoder
// 解码响应信息
public Object decode(final Response response, Type type)
			throws IOException, FeignException {
if (type instanceof Class || type instanceof ParameterizedType
			|| type instanceof WildcardType) {
		@SuppressWarnings({ "unchecked", "rawtypes" })
		HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
				type, this.messageConverters.getObject().getConverters());
		// 处理响应数据
		return extractor.extractData(new FeignResponseAdapter(response));
	}
	throw new DecodeException(response.status(),
			"type is not an instance of Class or ParameterizedType: " + type,
			response.request());
}
  • org.springframework.web.client.HttpMessageConverterExtractor
// 处理响应数据
public T extractData(ClientHttpResponse response) throws IOException {
	MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response);
	if (!responseWrapper.hasMessageBody() || responseWrapper.hasEmptyMessageBody()) {
		return null;
	}
	MediaType contentType = getContentType(responseWrapper);

	try {
		for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
			if (messageConverter instanceof GenericHttpMessageConverter) {
				GenericHttpMessageConverter<?> genericMessageConverter =
						(GenericHttpMessageConverter<?>) messageConverter;
				// 调用MessageConverter判断是否支持反序列化
				if (genericMessageConverter.canRead(this.responseType, null, contentType)) {
					if (logger.isDebugEnabled()) {
						ResolvableType resolvableType = ResolvableType.forType(this.responseType);
						logger.debug("Reading to [" + resolvableType + "]");
					}
					return (T) genericMessageConverter.read(this.responseType, null, responseWrapper);
				}
			}
			if (this.responseClass != null) {
				if (messageConverter.canRead(this.responseClass, contentType)) {
					if (logger.isDebugEnabled()) {
						String className = this.responseClass.getName();
						logger.debug("Reading to [" + className + "] as "" + contentType + """);
					}
					return (T) messageConverter.read((Class) this.responseClass, responseWrapper);
				}
			}
		}
	}
	catch (IOException | HttpMessageNotReadableException ex) {
		throw new RestClientException("Error while extracting response for type [" +
				this.responseType + "] and content type [" + contentType + "]", ex);
	}

	throw new RestClientException("Could not extract response: no suitable HttpMessageConverter found " +
			"for response type [" + this.responseType + "] and content type [" + contentType + "]");
}
  • org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter
// 此方法判断媒体类型是否可读取,值类型是否可以反序列化
public boolean canRead(Type type, @Nullable Class<?> contextClass, @Nullable MediaType mediaType) {
	if (!canRead(mediaType)) {
		return false;
	}
	JavaType javaType = getJavaType(type, contextClass);
	AtomicReference<Throwable> causeRef = new AtomicReference<>();
	if (this.objectMapper.canDeserialize(javaType, causeRef)) {
		return true;
	}
	// 如果无法反序列化,此处对无法支持反序列化的异常进行捕获并输出日志(此处日志级别为DEBUG)
	logWarningIfNecessary(javaType, causeRef.get());
	return false;
}
  • com.fasterxml.jackson.databind.DeserializationContext
// 查询对于值类型是否存在反序列化器
public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
  try {
        return _cache.hasValueDeserializerFor(this, _factory, type);
    } catch (JsonMappingException e) {
    	// 如果不支持反序列化,抛出异常在此处捕获并注入到cause中
        if (cause != null) {
            cause.set(e);
        }
    } catch (RuntimeException e) {
        if (cause == null) { // earlier behavior
            throw e;
        }
        cause.set(e);
    }
    return false;
}
原文地址:https://www.cnblogs.com/luguojun/p/14294728.html