web-dev-qa-db-ja.com

Spring RESTおよびPATCHメソッド

SpringBootとSpringRESTを使用しています。モデルのプロパティを更新するHTTP PATCHメソッドについて理解したい

それを機能させる方法を説明する良いチュートリアルはありますか?

  • 送信するHTTPPATCHメソッドと本文
  • コントローラーの方法と更新操作の管理方法
12
fvisticot

提供された回答の多くがすべてJSONパッチまたは不完全な回答であることに気づきました。以下は、実際のコードを機能させるために必要なものの完全な説明と例です

まず、PATCHは選択的なPUTです。これを使用して、オブジェクトまたはオブジェクトのリストの任意の数のフィールドを更新します。 PUTでは、通常、オブジェクト全体を更新とともに送信します。

パッチ/ object/7

{
   "objId":7,
   "objName": "New name"
}

PUT/object/7

{
   "objId":7,
   "objName": "New name",
   "objectUpdates": true,
   "objectStatus": "ongoing",
   "scoring": null,
   "objectChildren":[
       {
          "childId": 1
       },
     ............ 
}

これにより、大量のエンドポイントなしでレコードを更新できます。たとえば、上記の場合、スコアを更新するにはobject/{id}/scoreが必要であり、名前を更新するにはobject/{id}/nameが必要です。文字通り、アイテムごとに1つのエンドポイント、またはフロントエンドが更新ごとにオブジェクト全体を投稿する必要があります。巨大なオブジェクトがある場合、これには多くのネットワーク時間や不要なモバイルデータがかかる可能性があります。このパッチにより、モバイルプラットフォームが使用する必要がある最小限のオブジェクトプロパティsendを持つエンドポイントを1つ持つことができます。

以下は、パッチの実際の使用例です。

@ApiOperation(value = "Patch an existing claim with partial update")
@RequestMapping(value = CLAIMS_V1 + "/{claimId}", method = RequestMethod.PATCH)
ResponseEntity<Claim> patchClaim(@PathVariable Long claimId, @RequestBody Map<String, Object> fields) {

    // Sanitize and validate the data
    if (claimId <= 0 || fields == null || fields.isEmpty() || !fields.get("claimId").equals(claimId)){
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST); // 400 Invalid claim object received or invalid id or id does not match object
    }

    Claim claim = claimService.get(claimId);

    // Does the object exist?
    if( claim == null){
        return new ResponseEntity<>(HttpStatus.NOT_FOUND); // 404 Claim object does not exist
    }

    // Remove id from request, we don't ever want to change the id.
    // This is not necessary, you can just do it to save time on the reflection
    // loop used below since we checked the id above
    fields.remove("claimId");

    fields.forEach((k, v) -> {
        // use reflection to get field k on object and set it to value v
        // Change Claim.class to whatver your object is: Object.class
        Field field = ReflectionUtils.findField(Claim.class, k); // find field in the object class
        field.setAccessible(true); 
        ReflectionUtils.setField(field, claim, v); // set given field for defined object to value V
    });

    claimService.saveOrUpdate(claim);
    return new ResponseEntity<>(claim, HttpStatus.OK);
}

新しい開発者は通常、そのようなリフレクションを処理しないため、上記は一部の人々にとって混乱を招く可能性があります。基本的に、この関数を本文に渡すと、指定されたIDを使用して関連するクレームが検出され、キーと値のペアとして渡されたフィールドのみが更新されます。

本文の例:

パッチ/ claims/7

{
   "claimId":7,
   "claimTypeId": 1,
   "claimStatus": null
}

上記は、claimTypeIdとclaimStatusをクレーム7の指定された値に更新し、他のすべての値は変更されません。

したがって、リターンは次のようになります。

{
   "claimId": 7,
   "claimSrcAcctId": 12345678,
   "claimTypeId": 1,
   "claimDescription": "The vehicle is damaged beyond repair",
   "claimDateSubmitted": "2019-01-11 17:43:43",
   "claimStatus": null,
   "claimDateUpdated": "2019-04-09 13:43:07",
   "claimAcctAddress": "123 Sesame St, Charlotte, NC 28282",
   "claimContactName": "Steve Smith",
   "claimContactPhone": "777-555-1111",
   "claimContactEmail": "[email protected]",
   "claimWitness": true,
   "claimWitnessFirstName": "Stan",
   "claimWitnessLastName": "Smith",
   "claimWitnessPhone": "777-777-7777",
   "claimDate": "2019-01-11 17:43:43",
   "claimDateEnd": "2019-01-11 12:43:43",
   "claimInvestigation": null,
   "scoring": null
}

ご覧のとおり、変更したいデータ以外のデータを変更せずに、オブジェクト全体が返されます。ここでの説明には少し繰り返しがあることはわかっていますが、はっきりと説明したいと思います。

4
Nox

SpringがPATCHおよびPUTと関係している限り、POSTメソッドに本質的な違いはありません。課題は、PATCHリクエストで何を渡すか、およびコントローラーでデータをどのようにマップするかです。 @RequestBodyを使用してバリューBeanにマッピングする場合、実際に設定されているものとnull値の意味を理解する必要があります。その他のオプションは、PATCHリクエストを1つのプロパティに制限し、それをURLで指定するか、値をMapにマップします。参照 Spring MVC PATCHメソッド:部分更新

2
jny