[SpringBoot] バリデーション – @Validated と @Valid の使い方

JavaSpringBoot

Spring Boot で REST API 作成時にバリデーションの方法を調べた。調査中に @Validated@Valid が出てきて、書き方や使い方にもいくつかの方法があって、どういう場面でどう使ったらいいのかよく分からなかった。結果、「こうした!」という最終形態をメモ。

build.gradle

バリデーションのパッケージを追加する。

implementation 'org.springframework.boot:spring-boot-starter-validation'

Bean (エンティティ)

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Length;

import com.example.demo.infrastructure.validation.group.Update;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table
public class Hoge {

	@NotNull
	private Integer id;

	@NotBlank(groups=Update.class)	// ➀
	@Length(max=30)
	private String fieldA;

	@Valid
	private Foo foo;

	@Size(min = 1, {Update.class, xxx.class})	// ➀ - 1
	@Valid	// ➁
	private List<Foo> foos;

	@NotEmpty
	@Valid	// ➁
	private List<@NotBlank String> list;
}

ネストしている Bean

public class Foo {

	@NotNull
	private Integer id;

	@NotBlank(groups=Update.class)
    private String name;
}

➀ バリデーションのグループ化。特定の場面でのみ実行したいバリデーションを指定することができる。複数クラス指定する場合は、 ➀ – 1 のようにリスト形式で指定する。

➁ Bean やコレクションをネストしている場合、 @Valid を付ける。 付けないと、ネスト先のバリデーションが効かない。

バリデーショングループのインタフェース

バリデーションのグループ化用のグループ。

import javax.validation.groups.Default;

public interface Update extends Default {

}

ここでは、javax.validation.groups.Default を継承しているため、グループ指定したときは、Update グループ + Default グループ (グループ指定していないバリデーション)が実行される。

Controller

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.infrastructure.entity.Hoge;
import com.example.demo.infrastructure.validation.group.Update;

import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/hoge")
@RequiredArgsConstructor
public class SampleController {

	@PostMapping
	public Hoge create(@Validated @RequestBody Hoge hoge) {
		// 処理
	}

	@PutMapping("/{id}")
	public Hoge update(@PathVariable("id") Integer id, @Validated(Update.class) @RequestBody Hoge hoge) {
	    // 処理
	}
}

@RequestBody の前に @Validated を付ける。 @Validated(Update.class)  のようにグループもここで指定する。

create() は、Default グループ (グループ指定していないバリデーション)が実行される。

Posted by Agopeanuts