RestTemplate使用し、あなたはまだ胸の中に熟れている原則?[春のMVCを学ぶお楽しみください]

各1

人々満月の円の中心、幸せな人の家族や国と---中秋節

序文

前にこれを読んで、私はあなたが読むことをお勧めしますパイオニアの論文は、より良いです。RestTemplate春がアクセスするために提供されRest、さまざまな提供していますクライアントサービスツール、便利なリモートHTTPサービスにアクセスする方法を、大幅にクライアントの準備の効率を向上させることができます
文アピールするために弱い弱い:人のためにSpring、まだ周囲使ってHttpClientこの記事を読んだ後、同級生(または他のクライアント)、およびカミンを、に切り替えることをお勧めしますRestTemplate(特別なニーズを持つ、もちろん、〜自分自身を除きます)。

RestTemplateHTTPサービスとの通信を簡素化し、プログラムコードは、それへのURLを提供し、その結果を抽出することができます。これはJDKの使用デフォルトHttpURLConnectionの通信は、しかし、我々はできるRestTemplate.setRequestFactory別のHTTPソースに切り替える:としてApache HttpComponentsNettyOkHttpなどが挙げられます。

RestOperations

安らかなインタフェースは、基本的な操作のセットを指定し残りはオペレーションの基本セットを定義し、その実装が一意であるRestTemplate以下、これを(直接使用されていないが、それは簡単にシミュレートまたはスタブされているので、テスト容易性を高めるための便利なオプションです。 )というフレーズをよく理解しているしてください。

参照して比較できるRedisOperationsだけであるの実装、RedisTemplate1。彼らは、デザインモードを採用しています模板模式

方法は以下のとおりです。

(40 +)の方法で、このインタフェースは、あまりにも多くて以来、私は標準のHTTPに従い、以下の表を分類します:

// @since 3.0
public enum HttpMethod {
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
    ...
}
HTTPMETHOD 方法
取得する ここに画像を挿入説明
ここに画像を挿入説明
役職 ここに画像を挿入説明
プット ここに画像を挿入説明
パッチ ここに画像を挿入説明
DELETE ここに画像を挿入説明
OPTIONS ここに画像を挿入説明
トレース ノー
任意(HTTPは任意の方法を実行します) ここに画像を挿入説明

しかし、多くの方法がフォローする強力なルールがあり、ことを観察しました。各メソッドは、達成するために、オーバーロード3で来る:文字列にURIパラメータをURLパラメータの2種類をその多くのを恐れる必要はなく、法律を習得するためにそれを使用し、その後、そして、私は使用する方法がわかりません。

xxxForObject:応答本体(本体は、物理的内容を指示する)を返す(T)
xxxForEntityた:それぞれの行は、身体に対する応答ヘッダ、応答コード、等を返却(ResponseEntity
xxxForLocation:提出が成功した後、リターンURI新しいリソース。URIを返すだけサービスプロバイダは、URIは、非常に軽量のように記述することができる新たなリソースの位置を表します。(URI)

注:として、デフォルトの文字列型のURL URLは、エスケープされる使用しhttp://example.com/hotel list、実行時のようにエスケープされhttp://example.com/hotel%20list、これは問題ありません暗黙の脱出。しかし、あなたは脱出してきたが、それは大丈夫ではない場合。
あなたはこの暗黙的に推奨されるURIをエスケープしたい場合は(URI uri = uriComponents.toUri())を構築しました。

== RestTemplate三つの方法== POSTリクエスト

post新代わって要求/それは戻り値であるので、リソースを作成します。その最も複雑なの使用、及びそのため本論文では、それを説明するための例のため。

あなたが巧みにブラウザを使用した場合开发者工具、デバッグを、あなたは確かに知っているPOST、それは2つの方法の質量参加で要求します。

  1. フォームデータの方法:我々はそれという形で提出する方法からし;(注:これはむしろ生のJSのソースよりも、jQueryのAJAXを参照)AJAXを使用してデフォルト・モードでは、それを提出することです〜
    ここに画像を挿入説明
  2. 要求ペイロードモード:マルチパートの方法/ JSONモード
    ここに画像を挿入説明
    ここに画像を挿入説明

これらの二つの方法が通過しているContent-Type場合:差にapplication/x-www-form-urlencodedそれはあるformdata方法;場合application/json、またはmultipart/form-dataある他の手段request payload方法

jQueryPOSTリクエストを実行すると、デフォルトの設定ではあなたを与えるだろうContent-Typeですapplication/x-www-form-urlencodedので、サーバが正しく解決することができます。
あなたはAJAX jsのネイティブを使用する場合は、あなたがいない場合は、显示的コンテンツタイプを設定し、デフォルトはtext / plainでは、サーバーは、それが唯一のオリジナルデータストリーミングモードを取得するためにデータを要求することにより解決することができるので、データを解析する方法を知らないです。(私は〜誰もがそれを乾燥させないと考えています)

交換やメソッドを実行します。

より一般的なリクエスト方法:の交換方法。このパラメータは受け入れなければならないRequestEntity、などのルートリクエスト、ヘッダー情報、ように提供することができる、すべて最終的に復帰しているResponseEntity(など、入れて、すべての要求は、GET、POSTを送信することができます)。
この方法を実行します。最も下の一般的な要求メソッドを。

RequestCallback:操作要求ヘッダとボディに発行された要求の実行; ResponseExtractor:解析/抽出HTTPレスポンスデータが、異常と資源クローズ心配しないで
RequestCallback.doWithRequest(ClientHttpRequest)白が取得することでClientHttpRequest、さらに処理後〜彼を
RestTemplateするacceptHeaderRequestCallback、httpEntityCallbackこれらの方法があることも〜それを設定
---

HttpAccessor、InterceptingHttpAccessor

2つの抽象クラスは、無視できないHystrixCommand和Ribbonロジックを、それが関係(インターセプター)を持っています。
HttpAccessor操作を定義する抽象基本クラスでClientHttpRequestFactoryパブリックプロパティは、それは一般的に直接使用されていません。

// @since 3.0
public abstract class HttpAccessor {
    
    // RestTemplate默认使用的客户端工厂:基于源生JDK
    private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

    // 若要切换成三方库的底层组件,设置此方法便可
    public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
        this.requestFactory = requestFactory;
    }
    ... // get方法
    
    // 供给子类非常方便的拿到一个ClientHttpRequest
    protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
        ClientHttpRequest request = getRequestFactory().createRequest(url, method);
        return request;
    }   
}

そのサブクラスは、次のとおりInterceptingHttpAccessor、それはまだ抽象的実現である、主にインターセプタの管理から要求されていますClientHttpRequestInterceptor

InterceptingHttpAccessor

// @since 3.0
// @see InterceptingClientHttpRequestFactory
public abstract class InterceptingHttpAccessor extends HttpAccessor {

    // 装载需要作用在RestTemplate上的拦截器们~~~
    private final List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
    @Nullable
    private volatile ClientHttpRequestFactory interceptingRequestFactory;

    // 这里语意是set,所以是完全的替换掉(支持ordered排序哦~~~)
    public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
        if (this.interceptors != interceptors) {
            this.interceptors.clear();
            this.interceptors.addAll(interceptors);
            AnnotationAwareOrderComparator.sort(this.interceptors);
        }
    }

    // 复写了父类的这个方法很有意思
    // 意思为:若你调用者手动set进来了,那就以调用者设置的工厂为准 否则使用的是InterceptingClientHttpRequestFactory
    @Override
    public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
        super.setRequestFactory(requestFactory);
        this.interceptingRequestFactory = null;
    }

    // 若配置了拦截器,那么默认就使用InterceptingClientHttpRequestFactory,而不再是SimpleClientHttpRequestFactory了~~~
    @Override
    public ClientHttpRequestFactory getRequestFactory() {
        List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
        if (!CollectionUtils.isEmpty(interceptors)) {
            ClientHttpRequestFactory factory = this.interceptingRequestFactory;
            if (factory == null) {
                factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
                this.interceptingRequestFactory = factory;
            }
            return factory;
        } else {
            return super.getRequestFactory();
        }
    }
}

InterceptingHttpAccessorメイン処理ロジックは次のとおりです。それが作成されます植物がブロッキング機能で、呼び出し側が要求インタセプタを設定発見された場合InterceptingClientHttpRequestFactory、それ以外の場合はデフォルトSimpleClientHttpRequestFactory

InterceptingClientHttpRequestFactory工場では生産ClientHttpRequest石をInterceptingClientHttpRequest、それがメソッドのインターセプタインターセプタを自分で実行します:nextInterceptor.intercept(request, body, this)

質問:実装される複数の構成の要求インタセプタがある場合は?
ソリューション:(循環)は、反復それが存在しないことが、ちょうど:これは混乱し、結論にジャンプなってはならないiterator.next()多くの一つだけを実行する場合は、と考えるのは、それは間違っているだろうここでは、限りインターセプターとして、実際に実行鎖の形でintercept最終的に方法でアクチュエータを呼び出すintercept()方法を、次にインターセプタチェーンが実装されているであろう。根本的な理由は、第3引数でthis、(ある同じアクチュエータを完了するために開始しますthis=InterceptingRequestExecution

---


== ==残りのテンプレート

RestTemplate使用して同期 HTTPリクエストクラスの実行モードを、基本となるデフォルトのJDKネイティブをHttpURLConnection APIこれは、インターフェイスを実装しRestOperations、開発者がより簡単にHTTPリクエストを送信できるようにテンプレートメソッド(オーバーロードされたメソッド)の多くを提供します。

なお、RestTemplateそれはSpring 3.0そこにはなく、Spring5.0の後、春が正式に推奨されorg.springframework.web.reactive.function.client.WebClient、特に非同期シーンのために、それを交換します。

RestTemplate非常に広いので、でも春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、様々な関連するコンポーネントの設定を含む関連する方法、の製造例を。

次は、それを達成するためのインタフェース・メソッドがあるより重要である、と私はいくつかの重要なポイントの説明説明を行ってください。

RestTemplate:

    @Override
    @Nullable
    public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
        //1、new AcceptHeaderRequestCallback(responseType)  它能在发送请求的之前这样一件事:
        // request.getHeaders().setAccept(allSupportedMediaTypes)
        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);

        // 最终调用的是execute方法,此时URL是个字符串
        // responseExtractor返回值提取器使用的是消息转换器去读取body哒~
        // 返回值就是返回的body本身(不含有返回的响应头等等信息~)
        return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
    }

    // 它返回的是ResponseEntity,不会返回null的  最终调用的依旧是execute方法
    // 此时候用的就不是消息转换器的提取器了,而是内部类`ResponseEntityResponseExtractor`(底层还是依赖消息转换器)
    // 但是这个提取器,提取出来的可都是ResponseEntity<T>实例~
    @Override
    public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
    }

    // HEAD请求:很简单,使用的提取器就是headersExtractor,从返回值里把响应header拿出来即可
    @Override
    public HttpHeaders headForHeaders(String url, Object... uriVariables) throws RestClientException {
        return nonNull(execute(url, HttpMethod.HEAD, null, headersExtractor(), uriVariables));
    }


    // POST请求
    @Override
    @Nullable
    public URI postForLocation(String url, @Nullable Object request, Object... uriVariables) throws RestClientException {
        // 1、HttpEntityRequestCallback  适配:把request适配成一个HttpEntity
        // 然后执行前,通过消息转换器把头信息、body信息等等都write进去
        RequestCallback requestCallback = httpEntityCallback(request);
        // 因为需要拿到URI,所以此处使用headersExtractor提取器先拿到响应的header即可~~~
        HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);
        return (headers != null ? headers.getLocation() : null);
    }

    // 除了httpEntityCallback()不一样,其余和get请求一样
    @Override
    @Nullable
    public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request, responseType);
        HttpMessageConverterExtractor<T> responseExtractor =
                new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
        return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
    }

    // PUT请求:因为没有返回值,所以不需要返回值提取器。所以,非常的简单~~~
    @Override
    public void put(String url, @Nullable Object request, Object... uriVariables) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(request);
        execute(url, HttpMethod.PUT, requestCallback, null, uriVariables);
    }

    // DELETE请求:也是木有返回值的。
    // 并且请注意:DELETE请求这里可都是不能接收body的,不能给请求设置请求体的
    // (虽然可能底层httpCLient支持,但这里不支持,请遵守规范)
    @Override
    public void delete(String url, Object... uriVariables) throws RestClientException {
        execute(url, HttpMethod.DELETE, null, null, uriVariables);
    }

    // OPTIONS请求:和HEAD请求的处理逻辑几乎一样
    @Override
    public Set<HttpMethod> optionsForAllow(String url, Object... uriVariables) throws RestClientException {
        ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
        HttpHeaders headers = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables);
        return (headers != null ? headers.getAllow() : Collections.emptySet());
    }

すべてのメソッドは、一般的に同じロジックを実行し、そしてあるRequestCallbackresponseExtractorように、そしてほとんどが最終的に根本的に委託されexecute()、それを行うための方法。

あなたは疑うください:私は何をすべきか腫れの値を返すように要求を入れている場合、戻り値は、無効である提供方法を​​置きますか?そして、次はもっと一般的な方法をご紹介します。exchange()

RestTemplate:

    @Override
    public <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
        // 把请求体适配为HttpEntity
        RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
        // 消息提取器使用ResponseEntityResponseExtractor
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);

        // 从上两个部分就能看到:exchange方法的入参、出参都是非常通用的~~~
        return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
    }

    // ParameterizedTypeReference参数化类型,用于处理泛型
    // 上面的responseType就是个Class。这里是个参数化类型~~~~~
    @Override
    public <T> ResponseEntity<T> exchange(String url, HttpMethod method, @Nullable HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException {

        Type type = responseType.getType();
        RequestCallback requestCallback = httpEntityCallback(requestEntity, type);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(type);
        return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
    }

    // 这个方法就非常精简了,让调用者自己去构造RequestEntity,里面是包含了请求的URL和方法等信息的
    @Override
    public <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) throws RestClientException {
        RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
        ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
        return nonNull(doExecute(requestEntity.getUrl(), requestEntity.getMethod(), requestCallback, responseExtractor));
    }

exchangeすべてのメソッドが使用されているHttpEntityResponseEntity要求エンティティの代表者と応答エンティティ、設計の汎用性を確認するために十分です。

Spring3.2は、提供した後ParameterizedTypeReference、このような一般的なリストに対処するために、主> ---パラメータ化された型を処理するために、

それもで見つけることができexchange()、最終的に委託し、メソッドexecute/doExecuteを実行します:

RestTemplate:

    // 3个execute方法。最终调用的都是doExecute方法
    // 它做的一件事:使用UriTemplateHandler把URL的参数填进去~~~
    // 底层使用的是我上文介绍的`UriComponentsBuilder`,还是比较简单的
    @Override
    @Nullable
    public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
        URI expanded = getUriTemplateHandler().expand(url, uriVariables);
        return doExecute(expanded, method, requestCallback, responseExtractor);
    }

doExecute方法:
    @Nullable
    protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
        ClientHttpResponse response = null;
        ClientHttpRequest request = createRequest(url, method);
        // 如果有回调,那就先回调处理一下子请求
        if (requestCallback != null) {
            requestCallback.doWithRequest(request);
        }
        // 真正意义上的发送请求。
        // 请注意:如果这里的request是`InterceptingClientHttpRequest`,那就回执行拦截器的intercept方法哦~~~
        // 至于什么时候是InterceptingClientHttpRequest呢?这个上面有讲的
        response = request.execute();
        // 处理结果(若有错误,那就抛出异常~~~)
        handleResponse(url, method, response);
        
        // 请求正常。那就使用返回值提取器responseExtractor提取出内容即可了~~~
        return (responseExtractor != null ? responseExtractor.extractData(response) : null);
        ...
        // 关闭响应(ClientHttpResponse继承了Closeable接口)
        finally {
            if (response != null) {
                response.close();
            }
        }
    }

読み込みdoExecute()テンプレート型実装手順を、それが明確であるRestTemplate、プロセスを完了するための応答を受信するための要求を出すから。Spring我々はプロセスに介入する中に入ることができるようにフックを提供するために、関連するコンポーネントの数を設計し、もちろん、それは、最も一般的なリクエストインターセプタであり、それは〜の内側にリボンのロードバランシングとHystrixヒューズで良いアプリケーションを持っています

AsyncRestTemplate

それは@since 4.0、新たな決意いくつかのシーンの非同期のHTTP要求が、人生は短いです、でSpring5.0ちょうどマーク@Deprecated、推奨されてWebClientそれを交換します。

その基本的な原理は達成することです:RestTemplate+ SimpleAsyncTaskExecutorタスクプールの道を非同期要求を達成するために、戻り値はListenableFutureマスタリングRestTemplate後に、それは使用障害ではありません

ミニマリストの使用デモの表示

原則の記述を読んで、私はあなたが胸に熟れを持っていると信じるに足る理由持つRestTemplateまで自由にそれを使用することができます。したがって、唯一以下の非常に単純なデモショーへの紙の使用に関して、私はそれが十分なだと思います。

public static void main(String[] args) throws IOException {
    RestTemplate restTemplate = new RestTemplate();
    String pageHtml = restTemplate.getForObject("http://www.baidu.com", String.class);
    System.out.println(pageHtml); // 百度首页的html...
}

ていることを説明する:ように要求は、htmlページを取得しHttpMessageConverterExtractor、応答が展開する際に、使用してStringHttpMessageConverter次のように抽出されたコードを処理するためには、次のとおりです。

StringHttpMessageConverter:
    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        // 从响应头的contentType里提取(若是application/json,那默认也是urf-8)
        // 若没有指定编码,就取值getDefaultCharset。比如本处访问百度,就取值默认值`ISO-8859-1`对body体进行编码的~
        Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType());
        return StreamUtils.copyToString(inputMessage.getBody(), charset);
    }

上記の場合を要求すると、私が使用できる小型のパートナーClientHttpRequestFactoryコントラスト(あるいは自分自身を、要求された送信するために例を使用するHttpClientステップの比較)は、使用して感情を感じるRestTemplateものを優雅にされ...

推奨読書

RestTemplateコンポーネント:ClientHttpRequestFactory、ClientHttpRequestInterceptor、ResponseExtractor Spring MVCのは] [学習楽しむ
@LoadBalanced注釈がRestTemplateは、負荷分散機能を持たせることができますなぜですか?[春の雲を楽しむことを学びます]

概要

主流としてマイクロサービス今日、RestTemplate武器として記述することができ、すべてのプログラマはそれを習得する必要があります。で、深さ、その実用化の理解、チューニングは、私はこの記事があなたが、胸に熟れを行う役立っていると信じて、本当の意味を持っています。
警告される:の簡単な分析の原則、なぜ次の記事はあなたを教えてくれる@LoadBalancedノートを作ることができRestTemplate、負荷分散を持っている能力を?

== 春、SpringBoot、MyBatisのソースコード解析およびその他の利害私にWXを追加することができため場合:fsx641385712、手動でグループに離陸することを勧め ==
== 春、SpringBoot、MyBatisのソースコード解析および他のために興味が私を追加WXことができる場合:fsx641385712、手動で離陸したグループにあなたを招待 ==

おすすめ

転載: www.cnblogs.com/fangshixiang/p/11532755.html