【Spring MVC】REST APIにて基本的な入力チェックを行う方法

概要

REST APIアプリにて、入力チェックを行う方法についてまとめた。
尚、入力チェックエラーハンドリング方法は扱わない。

あわせて読みたい

概要 これから数回にかけてREST APIについて学んだことを載せていく。 今回はREST APIの仕組みとプロジェクト作成方法について紹介する。 尚、RESTとは何かということについては取り扱わない。   仕組み[…]

 

前提

動作確認はTalend API Testerを使用した。
Talend API Testerの使用方法については以下を参照。

あわせて読みたい

概要 GUIのツールを使用してシンプルにREAT APIアプリにリクエストを送りたいと思い、Talend API Testerを使用してみた。 いろいろと便利だったため、基本的な使用方法について簡単にまとめた。   事[…]

Talend API Testerを使用してREST APIにリクエストする方法

 

基本的な入力チェック

サーバーリクエスト時の、クエリパラメータまたはリクエストボディのBean Validationを行う。
Bean Validationとは、JavaBeansのフィールドにアノテーションを付与してバリデーションを行う仕組みのこと

あわせて読みたい

概要 Spring MVCにてフォームの入力チェックを行う方法についてまとめた。 入力チェックには、フォームのフィールドに入力チェック用のアノテーションを付与する。 今回は基礎的なBean Validationと、その実装であるH[…]

【Spring MVC】フォームの入力チェック方法(基本な使い方)

 

ライブラリの追加

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;
}

 

@NotNull
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;
	}

}

 

@GetMapping(value = “rest06/”)
public List<Resource> get(@Valid ResourceQuery queryParam) {

Bean Validationを付与した入力チェックを有効にするためには、対象のリクエストクラスの前に@Validまたは@Validatedを付与する

 

動作確認

nameフィールドをクエリパラメータに設定しない状態でリクエスト送信する。

 

リクエスト


http://localhost:8080/rest_prototype/rest06/?hogeDate=2025-02-01

 

入力チェックエラーとなり、以下の挙動となる。

・ HTTPステータス: 400(Bad Request)
・ 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;
}

 

@NotNull
private String id;
@NotNull
private String name;
リクエストボディのidまたは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();
	}

}

 

@PostMapping(value = “rest06/create”)
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"}

 

入力チェックエラーとなり、以下の挙動となる。

・ HTTPステータス: 400(Bad Request)
・ org.springframework.web.bind.MethodArgumentNotValidExceptionがスローされる

 

まとめ

 

☑ バリデーションエラーが発生した場合、Spring MVCはデフォルトでHTTP 400ステータス (Bad Request) を返却する

☑ クエリパラメータの入力チェックエラー時、BindExceptionがスローされる

☑ リクエストボディの入力チェックエラー時、MethodArgumentNotValidExceptionがスローされる

 

スポンサーリンク