RestTemplate的使用和原理你都烂熟于胸了吗?【享学Spring MVC】 (3)

InterceptingHttpAccessor最主要的处理逻辑为:若发现调用者设置了请求拦截器,那么它创建的工厂是具有拦截功能的InterceptingClientHttpRequestFactory,否则就是默认的SimpleClientHttpRequestFactory。

InterceptingClientHttpRequestFactory工厂它产生的ClientHttpRequest是InterceptingClientHttpRequest,然而它就会执行拦截器的拦截方法喽:nextInterceptor.intercept(request, body, this)

提问:如有配置有多个请求拦截器,都会执行吗?
解答:这个千万不要犯迷糊和轻易下结论:以为没有迭代它(for循环)而只是iterator.next()就以为若有多个就只会执行一个,那就大错特错了。这里实际是形成了一个执行链条,只要拦截器的intercept方法内最终还调用执行器的intercept()方法,那么拦截器链就会一直执行下去。其根本缘由是第三个参数传入的是this,至始至终都是同一个执行器(this=InterceptingRequestExecution)

--- ==RestTemplate==

RestTemplate采用同步方式执行 HTTP 请求的类,底层默认使用JDK原生 HttpURLConnection API。它实现了接口RestOperations,提供了非常多的模版方法(重载方法)让开发者能更简单地发送 HTTP 请求。

需要注意的是,RestTemplate是Spring 3.0就有了,但在Spring5.0后,Spring官方是推荐使用org.springframework.web.reactive.function.client.WebClient替代它,特别是对于异步的场景。

RestTemplate因为使用极其广泛,so即使到了Spring 5.0,官方只是建议替代,但并没有标注@Deprecated,因此至少目前你还可以想咋用就咋用吧。
但是AsyncRestTemplate是明确标注了@Deprecated,强烈建议使用org.springframework.web.reactive.function.client.WebClient去代替,所以在5.0后不建议再使用它了~。

当然还需要说明一点:若你的项目中没有使用到WebFlux的技术栈来处理请求,那么也没必要说为了使用而使用,所以没必要专门为了它而导包(个人建议)~

// @since 3.0 public class RestTemplate extends InterceptingHttpAccessor implements RestOperations { // 去classpath探测 是否有这些消息转换器相关的jar~ // 一般情况下我们都会导jackson2Present~~~ private static boolean romePresent; private static final boolean jaxb2Present; private static final boolean jackson2Present; private static final boolean jackson2XmlPresent; private static final boolean jackson2SmilePresent; private static final boolean jackson2CborPresent; private static final boolean gsonPresent; private static final boolean jsonbPresent; ... // 下面四个变量很重要: // 消息转换器们(显然对JSON格式默认是支持得***的) private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); // 默认的请求异常处理器,Spring5.0后其实可以使用它ExtractingResponseErrorHandler // 它能够利用消息换换气提取你的错误内容。并且还支持自定义错误码、错误序列等等~ private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler(); // 用于URL的构建 private UriTemplateHandler uriTemplateHandler; // 默认的返回值提取器~~~~ private final ResponseExtractor<HttpHeaders> headersExtractor = new HeadersExtractor(); // 空构造,应该是平时使用得最多的了:一切都使用默认的组件配置Resource等等 public RestTemplate() { // 这个几个消息转换器是支持的。字节数组、字符串、 this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); this.messageConverters.add(new ResourceHttpMessageConverter(false)); this.messageConverters.add(new SourceHttpMessageConverter<>()); // 对form表单提交方式的支持 this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); // 接下里便是一些列的判断,若类路径上有才会加进来 if (jackson2Present) { this.messageConverters.add(new MappingJackson2HttpMessageConverter()); } ... // new DefaultUriBuilderFactory() this.uriTemplateHandler = initUriTemplateHandler(); } // 你懂的,若想用OkHttp,也可以在构造时就指定 public RestTemplate(ClientHttpRequestFactory requestFactory) { this(); setRequestFactory(requestFactory); } // 若不想用默认的消息转换器,也可以自己指定(其实一般都不这么去干,而是后面自己再add进来) public RestTemplate(List<HttpMessageConverter<?>> messageConverters) { Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required"); this.messageConverters.addAll(messageConverters); this.uriTemplateHandler = initUriTemplateHandler(); } ... // 省略上面属性的get/set犯法们 }

这部分源码我列出来,都是在对构建一个RestTemplate实例的准备工作相关方法,包括对各个相关组件的设置。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggfjz.html