Ajaxは直接PUTリクエストを送信し、バックエンドはデータ原因と解決策を受け取ることができません

問題のI.概要:

    PUTのAjaxを直接送信要求が、カプセル化されたオブジェクトスプリングMVC、URIを介して他のIDフィールドは、正常にオブジェクトにデータ要求体でカプセル化されているが囲まれていません。

    request.getParameter()メソッドを使用してすることにより、HttpServletRequestオブジェクトだけでなく、データを取得しない。試験によって、要求がデータのフロントエンドから来ます

画像

第二に、解決策:

    原則下を向く、HttpPutFormContentFilterフィルターのweb.xmlを追加します。

  1  < フィルター> 
  2      < フィルタ - > httpPutFormContentFilter </ フィルタ -name > 
  3      < フィルタ - クラス> org.springframework.web.filter.HttpPutFormContentFilter </ フィルタリング> 
  4  </ フィルタ> 
  5  < フィルタ - マッピング> 
  6      < フィルタ - > httpPutFormContentFilter </ フィルタ -name >
  7      < URL - パターン> / * </ URL -pattern > 
  8  </ フィルタ -mapping >

第三に、分析の理由:

データは、地図としてパッケージ本体1 Tomcatを要求します、各オブジェクトの属性値のオブジェクトもrequest.getParameter呼び出されたときに、この値からrequest.getParameter()を呼び出すと、地図、Spring MVCのPOJOパッケージとなります()を取得する方法、および、適切なオブジェクトプロパティ、完全なカプセル化特性に割り当てられました。

データ2.しかし、PUT要求、Tomcatのパッケージは、マップ本体の要求ではないマップにカプセル化されたPOST要求データ要求の本体のみ、そう、直接呼び出しrequest.getParameter()メソッドか、又はSpring MVCのパッケージオブジェクトは、確かにプロパティの値を取得するために失敗します。

第四に、ソースコード解析:

1. TomcatのRequest.javaクラスのソースコードorg.apache.catalina.connectorパケットparseParameters()メソッドは、要求パラメータを解析するために使用され、最初の一連の方法は、配置と判断し、その要求パラメータを解析します。タイプを要求する次のコードが決定され、条件が直接返され満たされた場合、すなわち決定されないparseBodyMethod要求は、現在の実施形態は、含まれている場合、Tomcatサーバがパラメータ解決要求体の処理を続行、パッケージを含みますマップに、そうでない場合には、対応するパラメータにはマップされていない、むしろ解像度パラメータの以下の方法を実行するよりも、直接返します。

  1  であれば(!。getConnector()isParseBodyMethod(getMethod()メソッド)){
   2つの      成功=   3      リターン ;
  4 }

2. getConnector()メソッドは、現在接続を得るために使用され、その後、決定することを含むのisParseBodyMethod()メソッドを呼び出して設定parseBodyMethodSet値がメソッドに渡されず、この方法は、要求タイプの電流値です。

  1  / **
   2   * Request.javaクラス
   3   *現在の実施例を取り出す
   。4   * / 
  5  公共ストリングgetMethod()メソッド{
   6      リターン coyoteRequest.method()のtoString();.
   。7 }
   。8  
  。9  / **
 10   *コネクタ.javaクラス
 11   * / 
12である 保護 ブール isParseBodyMethod(文字列法){
 13は      リターン parseBodyMethodsSet.contains(方法);
 14 }

3. parseBodyMethodSetはparseBodyMethods parseBodyMethodSetに割り当てられた値に相当する一般的に使用される値は、デフォルトの設定され、デフォルト値はparseBodyMethodsポストです。

  1  / **
   2    *调用setParseBodyMethods将getParseBodyMethods()获取的parseBodyMethods的值赋值给
   3    * parseBodyMethods
   4    * / 
  5  保護 ボイド initInternal()がスロー LifecycleExceptionを{
   6  
  7      // ... 
  8  
  9      // makeは確認parseBodyMethodsSetを有しますデフォルト
10      であればヌル == parseBodyMethodsSet){
 11          setParseBodyMethods(getParseBodyMethods())。
12      }
 13  
14      // ... 
15 }
 16  
17  / **
18   取得parseBodyMethodsのa *値
 19。   * / 
20れる 保護された文字列parseBodyMethods = " POST ";
 21は、 
22である パブリック(文字列getParseBodyMethods){
 23れる     戻り 、この .parseBodyMethodsを;
 24 }
 25  
26である ** /
 27   コネクタと、コネクタを定義*ルール非会員解決要求POST要求を許可する、デフォルトではなく、ルールに導入された
 28   parseBodyMethodSetは、それがデフォルト値の使用*
 29   *値は方法parseBodyMethodsに割り当てられている
 30   methodSet値をparseBodyMethodsSetに割り当てられている*
 31である   * / 
32  公共 のボイドsetParseBodyMethods(文字列法){
 33  
34      HashSetの<ストリング> methodSet = 新しい HashSetの<文字列>();
35  
36      であればヌル =メソッド!){
 37          methodSet.addAll(は、Arrays.asList(methods.split( " \\はS *、\\はS * ")))。
38      }
 39  
40      // ... 
41  
42      この .parseBodyMethodsの=法。
43      この .parseBodyMethodsSet = methodSet。
44 }

唯一の方法は、直接要求オブジェクトを介してのgetParameter()やSpring MVCパッケージPOJOオブジェクトが取得していないかどうか、そのため、分析パラメータを投稿するときにparseBodyMethodSetは、デフォルト、唯一の現在のリクエストを投稿し、分析の前にいくつかの手順を実行することで4、パラメータ値。

五、HttpPutFormContentFilterフィルタ原理

  1  / *
   2   リクエストオブジェクトを再パッケージ*パッケージデータ要求本体、
   3   * / 
  。4  保護された ボイド doFilterInternal(最終 HttpServletRequestのリクエスト、HttpServletResponseの応答、れるFilterChainフィルターチェーン)がスロー ServletExceptionがは、IOException {
   5      //置く要求、または時にパッチを要求する時であると
  6      IF(( " PUT " .equals(request.getMethod())|| " PATCH " .equals(request.getMethod()))&& この .isFormContentType(リクエスト)){
   7          HttpInputMessage inputMessage = 新しい新しい ServletServerHttpRequest(要求){
   8             // HttpInputMessageにパッケージ、リクエストボディのデータストリームを取得
  9。             公共のInputStream getBody()はスローにIOException {
 10                  リターン request.getInputStreamを();
 11              }
 12れる          };
 13である 
14          HttpInputMessageを読み取るパッケージにパッケージの//最後のステップオブジェクトMultiValueMap 
15          //このオブジェクトは、地図から継承
16          マップに要求をカプセル化//データボディ
17。          MultiValueMap <文字列、文字列> = formParametersはこの .formConverter.read((クラス)ヌル、inputMessage);
 18れている 
19。         // HttpPutFormContentRequestWrapperを使用Requestオブジェクト再パッケージ
20を         = Warpper HttpServletRequestの新しい新 HttpPutFormContentFilter.HttpPutFormContentRequestWrapper(要求、formParameters);
 21である          FilterChain.doFilter(warpper、応答);
 22である      }  {
 23は          FilterChain.doFilter(リクエスト、レスポンス);
 24      }
 25 }
 26は、 
27  / **
 28   リクエストパッキング*オブジェクトの具体的な実現
 29   *は、最初の親クラスを呼び出し、()メソッドのgetParameterの親クラスを書き換える
 30   あなたが得ることができる場合*は親クラスに慣れることです。
 31   *あなたが得ることができない場合は、取得した現在のクラスを使用することです。
32   * / 
33は、 プライベート 静的 クラスHttpPutFormContentRequestWrapperは延び  	HttpServletRequestWrapperクラス{
 34        プライベート MultiValueMap <文字列、文字列> formParametersと、
35  
36        公共の文字列のgetParameter(文字列名){
 37               列queryStringValue = スーパー .getParameter(名);
38               ストリングformValue =(文字列)この .formParameters.getFirst(名前);
39               リターン queryStringValue!= nullのqueryStringValue:formValue。
40        }
 41  
42        // ... 
43 }

おすすめ

転載: www.cnblogs.com/lveyHang/p/11791412.html