PUTでのApache HttpClientをピット/のPOST

結論:
装うが、あなたは、ApacheのHttpClientを使用している場合は、PUT / POST、とき質量参加RequestBodyを使用するようにしてください。
そうでない場合はRequestBody、のQueryStringのApacheのHttpClientデータが少ない界面側よりもかかりますのでことを、キー値を提出する形式に変換されます

与えられている
サービスAへのインタフェース定義コピーサービスBいつものようにセルフテストに次いでFeignClientポストマン [エラートーンサービスAがサービスB]の間のインターフェイスエラー。

エラーメッセージ:

 

 

通常の状況下ではそこに起こることができないため、メッセージは、Wuguai非常にエレガントではありません。つまり、攻撃者は、このプロンプトストップパラメータは非常に厳格なチェックが表示されます。

データの生産と消費の
Bが提供するサービスのサービス[生産]:

 

 

サービスのフロントエンドに提供されるサービス:

 

 

サービスコンシューマは、サービス[B]を呼び出します。

 

 

これが書かれた当時は怠け者盗む:のQueryStringの直接の使用を、DTOデータ伝送の新たな定義を必要としません。エラー彼らは異常な方法を取らないので、これはアナリスト以下のもの、です。

BugShooting:ログの分析


要求されたデータストリームによって、ログ順序:サービスログ[A]は期待値と一致しています。

 

 

サービスB [予想にログ矛盾:以下のQueryString]:

 

 

問題が配置されています:サービスコールサービスB、失われたQueryString引数
印刷ログの重要性を!印刷ログは便利な学習です

 

そして、チェックコード、それに何も間違っては、特別のQueryStringマーク@RequestParamもマークされました!奇妙

BugShooting:巨人の肩の上に立ちます


私はピットを通じて誰かのワタリは、Baiduは、googleのかどうかを確認したい、ビングは、関連するケースの情報を見つけることができませんでした。介してのみ参照@Headers "ファイルアプリケーション/ JSONのContent-Type" または@PutMapping (値=  "/提供/ sync_strategies / syncStrategyId {}" ヘッダ= { "タイプ内容:ファイルアプリケーション/ JSON" })に明示的に宣言要求ヘッダーのアプローチ、次の無用を試してみてください。

 

BugShooting:デバッグ[ ニルヴァーナ]

我々は、この使用していないだろう、すべてのパラメータによって直接、事実を装うソースを再ソートする必要があり、再び:@RequestBodyを解決しますが、旗の前に立って自分自身を与えることができます。
デバッグ、それが発見され、このような論理PUTやPOSTメソッドがある場合にはApacheのHttpClient:
そこのQueryStringなくrequestBodyは、のQueryStringは、URLに置かれますが、QueryStringには、キー値データ形式の構造、形状やマスコミに変換されません提出:

org.apache.http.client.methods.RequestBuilder#ビルドは、
指定したアプリケーション/ X-WWW-フォーム- URLエンコードを、 とにRequestBodyのQueryStringを書き込みます。

 

 

org.apache.http.client.entity.UrlEncodedFormEntity#UrlEncodedFormEntity(java.lang.Iterable <?org.apache.http.NameValuePairが伸びる>、いるjava.nio.charset.Charset)

 

 

 

org.apache.http.client.utils.URLEncodedUtils#フォーマット(java.lang.Iterable <?延び org.apache.http.NameValuePair>は、チャー、いるjava.nio.charset.Charset)は、実際に、フォームへのQueryStringを変換しますフォームを送信するだけでなく、HTPP契約に沿ったものではなく、あなたができるこの方法を受信するための受信者が必要です。サービスBの使用、上のスクリーンショットを参照してください。そして、もちろん、我々は立ち上がっていなかった、のQueryStringからすなわち値に、@RequestParamを。簡単に言えば、ちょうど同じ宅配便を取ります。南門は、通常は取られますが、宅配便は北ゲートに行けば、あなたにこの変更を指示する必要がありません。南ゲートにも、あなたがた場合は、手の届かないところに間違いです。


2つの異なるデータ伝送

エラーはApacheのHttpClientは、要求を開始する場合:

 

 

 

所望の方法:

 

 

 

問題を発見し、解決策が明確になる:それはできませんRequestBodyを追加し
、私は冗長RequestBodyの行くを送っていること:

 

 

 

 

我々はすでにReqestBodyの値を見ることができます

 

QueryStringは、処理ロジックが変更するかどうかを見ていき、あなたが希望別のを見ることができます:

 

 

しかし、このアプローチは、これは無効なパラメータを削除しますように、他の学生は、コードを見ながら、そのサービスが利用できない、コードの増加のメンテナンスコスト、パラメータを必要としない業務が増加します。
したがって、要求はDTOパラメータにパッケージされ、その後、データは、体内で渡すことができます。

 

 

 

 

サプリメント


1は、ApacheのHTTPクライアントエンティティの初期化コードの入力] [RequestBody:

feign.httpclient.ApacheHttpClient#toHttpUriRequest

 

2、条件ピット上のステップ:装う使用するクライアントのApache Httpクライアントとして指定してください

       < 依存> 
            < groupIdを> org.springframework.cloud </ groupIdを> 
            < たartifactId >春・クラウド・スタータopenfeign </ たartifactId > 
        </ 依存関係> 

        <! - https://mvnrepository.com/artifact/io.github .openfeign /装う-のHTTPClient - > 
        < 依存> 
            < groupIdを> io.github.openfeign </ groupIdを> 
            < たartifactId >装う-のHTTPClient </ たartifactId > 
            <バージョン> 10.8 </ バージョン> 
        </ 依存関係>

この依存関係の装う - HTTPClientの以前のバージョンでは、以下を追加する必要があります。

        < 依存性> 
            < のgroupId > org.apache.httpcomponents </ のgroupId > 
            < たartifactId > HTTPClientの</ たartifactId > 
        </ 依存>

 

説明:サービスがチューン権を呼び出しの間にApacheのHttpClientはベテランのHTTPクライアントでは、接続プールのタイムアウト時間を設定することができます。この代替をサポートするために、最初から春クラウドBrixtion.SR5バージョン。
古典的なHttpClientを設定:

// のHttpClient 4.5.2古典的な接続プールの構成用い
    プライベートCloseableHttpClient getHttpClientを(){
         // ソケット工場関連するアクセス・プロトコル登録 
        レジストリ<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder。<ConnectionSocketFactory> 作成()
                .register( "HTTP" 、PlainConnectionSocketFactory。 INSTANCE)
                .register( "HTTPS" 、SSLConnectionSocketFactory.getSocketFactory())
                .build(); 

        // HttpConnectionFactory:設定書込み要求/応答処理構文解析 
        HttpConnectionFactory <HttpRoute、ManagedHttpClientConnection>はconnectionFactory = 新しい新しい ManagedHttpClientConnectionFactoryを(
                DefaultHttpRequestWriterFactory.INSTANCE、
                DefaultHttpResponseParserFactory.INSTANCE 
        ); 

        // DNSリゾルバ 
        DNSResolver DNSResolver = SystemDefaultDnsResolver.INSTANCE;
         // 接続プール管理プログラム作成 
        PoolingHttpClientConnectionManagerマネージャー= 新新PoolingHttpClientConnectionManager(socketFactoryRegistry、はconnectionFactory、DNSResolverを);
         // 設定されたデフォルトパラメータソケット 
        manager.setDefaultSocketConfig(SocketConfig。カスタム()setTcpNoDelay(真の).build()); 
        manager.setMaxTotal( 300); // 接続の最大数を設定します。この値は、新しい接続要求の上には、待って、ブロックする必要がある
         // ルーティングがMaxTotalの内訳です。
        //各経路の接続の実際の最大数は、デフォルト値DefaultMaxPerRouteによって制御されます。
        // MaxPerRouteは、大規模な同時実行をサポートするには小さすぎる設定:ConnectionPoolTimeoutException:プールから接続タイムアウトを待っ 
        manager.setDefaultMaxPerRoute(200); // ルートごとの最大接続数 
        manager.setValidateAfterInactivity(* 1000年5); // 接続から長い、デフォルト2S後に非アクティブに一度認証するために、接続プール、接続のニーズを取得する際

        // 設定されるデフォルトのリクエストパラメータ 
        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setConnectTimeout( * 1000 2)// 2Sへの接続タイムアウト 
                。 setSocketTimeout(* 1000年。5)// タイムアウト5Sへのデータ待ち 
                .setConnectionRequestTimeout(2 * 1000)//タイムアウトが2Sに設定されている待機中の接続プールから接続の取得
 //                 .setProxy(新しい新しいプロキシ(Proxy.Type.HTTP、たInetSocketAddress新新(「192.168.0.2」、1234)))// プロキシアップセット
                .buildを(); 

        CloseableHttpClient closeableHttpClient = HttpClients.custom()
                .setConnectionManager(マネージャ)
                (.setConnectionManagerShared falseに// 接続プールモードが共有されていない、これは共有が他のHttpClientと共有されているかどうかを指す 
                .evictIdleConnections(60、TimeUnit.SECONDS)//は定期的にアイドル接続回収 
                .evictExpiredConnectionsを()// 回復が接続期限切れ 
                .setConnectionTimeToLive(60、TimeUnit.SECONDS)//長い接続情報の決定に基づいて、設定されていない場合、生存期間を接続し 
                .setDefaultRequestConfig(defaultRequestConfig)// デフォルトのリクエストパラメータ設定 
                .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)// 接続の再利用戦略を、すなわちかどうかキープアライブ 
                .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)// 長い接続構成、すなわち、どのくらい生産取得長い接続 
                .setRetryHandler(新新 DefaultHttpRequestRetryHandler(0、falseに))// 再試行回数を設定、デフォルトは3回であり、現在は無効オフである
                .build(); 

        / ** 
         *停止または解放接続プール閉じるために接続され、JVMを再起動
         * /スレッド(){
        Runtime.getRuntime()addShutdownHook(。新しい
            @Override 
            公共 のボイドの実行(){
                 試み{ 
                    closeableHttpClient.close(); 
                    log.info( "HTTPクライアントは、閉じました" ); 
                } キャッチ(IOExceptionを電子){ 
                    log.error(e.getMessage()、E)。
                } 
            } 
        })。
        返すcloseableHttpClientを。
    }

 

https://github.com/helloworldtang/spring-boot-cookbook/blob/master/learning-demo/src/main/java/com/tangcheng/learning/web/config/RestTemplateConfig.java

 

https://mp.weixin.qq.com/s/N4zqSfMAgB6b5jnUsa1z2w

 

おすすめ

転載: www.cnblogs.com/softidea/p/12549071.html