概要
REST APIアプリにて、入力チェックを行う方法についてまとめた。
尚、入力チェックエラーハンドリング方法は扱わない。
概要 これから数回にかけてREST APIについて学んだことを載せていく。 今回はREST APIの仕組みとプロジェクト作成方法について紹介する。 尚、RESTとは何かということについては取り扱わない。 仕組み[…]
前提
動作確認はTalend API Testerを使用した。
Talend API Testerの使用方法については以下を参照。
概要 GUIのツールを使用してシンプルにREAT APIアプリにリクエストを送りたいと思い、Talend API Testerを使用してみた。 いろいろと便利だったため、基本的な使用方法について簡単にまとめた。 事[…]
基本的な入力チェック
サーバーリクエスト時の、クエリパラメータまたはリクエストボディのBean Validationを行う。
Bean Validationとは、JavaBeansのフィールドにアノテーションを付与してバリデーションを行う仕組みのこと。
概要 Spring MVCにてフォームの入力チェックを行う方法についてまとめた。 入力チェックには、フォームのフィールドに入力チェック用のアノテーションを付与する。 今回は基礎的なBean Validationと、その実装であるH[…]
ライブラリの追加
Bean Validationを使用するために、Hibernate Validatorライブラリをpom.xmlに追加する。
pom.xmlに追加した後、必要に応じてライブラリ資材をmaven install等でダウンロードする。
これにより、バリデーション用のアノテーション(例:@NotNull、@Min、@Size など)が使用可能になる。
pom.xml
<!-- 入力チェックを使用するためのモジュール -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.7.Final</version>
</dependency>
クエリパラメータの検証
GET通信のクエリパラメータをオブジェクトにバインドするケースで、
対象のオブジェクトにバリデーション用アノテーションを付与して検証する。
リクエストクラス
nameフィールドを入力チェック対象とする。
ResourceQuery.java
package com.example.rest_prototype.web.input;
import java.time.LocalDate;
import javax.validation.constraints.NotNull;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.Data;
/**
* リソース検索用オブジェクト
*/
@Data
public class ResourceQuery {
/** 名前 */
@NotNull
private String name;
/** とある日付 */
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate hogeDate;
}
private String name;
クエリパラメータのnameが送られてきていない場合、エラーとなる。
コントローラークラス
バリデーションを有効にする。
Rest06Controller.java
package com.example.rest_prototype.web.controller.rest06;
import java.net.URI;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.example.rest_prototype.biz.service.ResourceService;
import com.example.rest_prototype.web.input.ResourceQuery;
import com.example.rest_prototype.web.input.ResourceReq;
import com.example.rest_prototype.web.resources.Resource;
@RestController
public class Rest06Controller {
/** ビジネスロジック */
@Autowired
private ResourceService service;
/**
* クエリパラメータの入力チェック
* @param queryParam
* @return
*/
@GetMapping(value = "rest06/")
public List<Resource> get(@Valid ResourceQuery queryParam) {
// 検索結果
List<Resource> resList = service.findByParam(queryParam);
return resList;
}
}
public List<Resource> get(@Valid ResourceQuery queryParam) {
Bean Validationを付与した入力チェックを有効にするためには、対象のリクエストクラスの前に@Validまたは@Validatedを付与する。
動作確認
nameフィールドをクエリパラメータに設定しない状態でリクエスト送信する。
リクエスト
http://localhost:8080/rest_prototype/rest06/?hogeDate=2025-02-01
入力チェックエラーとなり、以下の挙動となる。
・ org.springframework.validation.BindExceptionがスローされる
リクエストボディの検証
POST通信などのリクエストボディをオブジェクトにバインドするケースで、
対象のオブジェクトにバリデーション用アノテーションを付与して検証する。
リクエストクラス
id、nameフィールドを入力チェック対象とする。
ResourceReq.java
package com.example.rest_prototype.web.input;
import java.time.LocalDate;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* REST APIへのリクエストオブジェクト
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResourceReq {
/** ID */
@NotNull
private String id;
/** 名前 */
@NotNull
private String name;
/** とある日付 */
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate hogeDate;
}
private String id;
@NotNull
private String name;
コントローラークラス
バリデーションを有効にする。
Rest06Controller.java
package com.example.rest_prototype.web.controller.rest06;
import java.net.URI;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import com.example.rest_prototype.biz.service.ResourceService;
import com.example.rest_prototype.web.input.ResourceQuery;
import com.example.rest_prototype.web.input.ResourceReq;
import com.example.rest_prototype.web.resources.Resource;
@RestController
public class Rest06Controller {
/** ビジネスロジック */
@Autowired
private ResourceService service;
/**
* クエリパラメータの入力チェック
* @param queryParam
* @return
*/
@GetMapping(value = "rest06/")
public List<Resource> get(@Validated ResourceQuery queryParam) {
// 検索結果
List<Resource> resList = service.findByParam(queryParam);
return resList;
}
/**
* リクエストボディの入力チェック
* @param param
* @return
*/
@PostMapping(value = "rest06/create")
public ResponseEntity<Void> post(@Valid @RequestBody ResourceReq req, UriComponentsBuilder builder) {
// リソース登録
var resource = new Resource(req.getId(), req.getName(), req.getHogeDate());
service.create(resource);
// ヘッダー設定用URI
URI uri = builder
.path("/rest01/{id}")
.buildAndExpand(resource.getId())
.toUri();
return ResponseEntity.created(uri).build();
}
}
public ResponseEntity<Void> post(@Valid @RequestBody ResourceReq req, UriComponentsBuilder builder) {
Bean Validationを付与した入力チェックを有効にするためには、対象のリクエストクラスの前に@Validまたは@Validatedを付与する。
動作確認
nameフィールドを設定しない状態でリクエスト送信する。
Talend API Testerなどを使用してリクエストボディを設定する。
リクエスト
http://localhost:8080/rest_prototype/rest06/create
送信するJSON
{"id": "4","hogeDate": "2025-01-10"}
入力チェックエラーとなり、以下の挙動となる。
・ org.springframework.web.bind.MethodArgumentNotValidExceptionがスローされる
まとめ
☑ バリデーションエラーが発生した場合、Spring MVCはデフォルトでHTTP 400ステータス (Bad Request) を返却する
☑ クエリパラメータの入力チェックエラー時、BindExceptionがスローされる
☑ リクエストボディの入力チェックエラー時、MethodArgumentNotValidExceptionがスローされる