1概要

このチュートリアルでは、フィールド値と照合するためにデータベースから取得した正規表現を使用するカスタム検証アノテーションを作成する方法について説明します。

基本実装としてHibernate Validatorを使用します。


2 Mavenの依存関係

開発には、以下の依存関係が必要になります。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>


spring-boot-starter-thymeleaf

、https://の最新バージョンsearch.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-data-jpa%22[spring-boot-starter-data-jpa]はMaven Centralからダウンロードできます。


3カスタム検証アノテーション

この例では、データベースから取得した正規表現に対して値を検証する

@ ContactInfo

というカスタム注釈を作成します。次に、この検証を、

Customer

というPOJOクラスの

contactInfo

フィールドに適用します。

データベースから正規表現を取得するために、これらを

ContactInfoExpression

エンティティクラスとしてモデル化します。


3.1. データモデルとリポジトリ


id

フィールドと

contactInfo

フィールドを使用して

Customer

クラスを作成しましょう。

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String contactInfo;

   //standard constructor, getters, setters
}

次に、

ContactInfoExpression

クラスを見てみましょう。これは、

pattern

というプロパティに正規表現の値を保持します。

@Entity
public class ContactInfoExpression {

    @Id
    @Column(name="expression__type")
    private String type;

    private String pattern;

   //standard constructor, getters, setters
}

次に、

ContactInfoExpression

エンティティを操作するためにSpring Dataに基づくリポジトリインタフェースを追加しましょう。

public interface ContactInfoExpressionRepository
  extends Repository<ContactInfoExpression, String> {

    Optional<ContactInfoExpression> findById(String id);
}


3.2. データベース設定

正規表現を保存するために、

H2

インメモリデータベースを使用して、以下の永続性設定を行います。

@EnableJpaRepositories("com.baeldung.dynamicvalidation.dao")
@EntityScan("com.baeldung.dynamicvalidation.model")
@Configuration
public class PersistenceConfig {

    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2)
          .addScript("schema-expressions.sql")
          .addScript("data-expressions.sql")
          .build();
        return db;
    }
}

上記の2つのスクリプトは、スキーマを作成し、

contact

info

expression

テーブルにデータを挿入するために使用されます。

CREATE TABLE contact__info__expression(
  expression__type varchar(50) not null,
  pattern varchar(500) not null,
  PRIMARY KEY ( expression__type )
);


data-expressions.sql

スクリプトは、タイプ

email



phone、

、および

website

を表す3つのレコードを追加します。これらは、有効な電子メールアドレス、有効な米国の電話番号、または有効なURLであることを検証するための正規表現を表します。

insert into contact__info__expression values ('email',
  '[a-z0-9!#$%&** +/=?^__`{|}~-]+(?:\.[a-z0-9!#$%&** +/=?^__`{|}~-]+)** @(?:[a-z0-9](?:[a-z0-9-]** [a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]** [a-z0-9])?')
insert into contact__info__expression values ('phone',
  '^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$')
insert into contact__info__expression values ('website',
  '^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)** \.[a-z]{2,5}(:[0-9]{1,5})?(\/.** )?$')


3.3. カスタムバリデータの作成

実際の検証ロジックを含む

ContactInfoValidator

クラスを作成しましょう。 Java Validation仕様のガイドラインに従って、クラスは

ConstraintValidator

インタフェース** を実装し、__isValid()メソッドをオーバーライドします。

このクラスは、現在使用されている連絡先情報のタイプ(

email



phone、

、または

website

)の値(

contactInfoType

というプロパティで設定)を取得し、それを使用してデータベースから正規表現の値を取得します。

public class ContactInfoValidator implements ConstraintValidator<ContactInfo, String> {

    private static final Logger LOG = Logger.getLogger(ContactInfoValidator.class);

    @Value("${contactInfoType}")
    private String expressionType;

    private String pattern;

    @Autowired
    private ContactInfoExpressionRepository expressionRepository;

    @Override
    public void initialize(ContactInfo contactInfo) {
        if (StringUtils.isEmptyOrWhitespace(expressionType)) {
            LOG.error("Contact info type missing!");
        } else {
            pattern = expressionRepository.findById(expressionType)
              .map(ContactInfoExpression::getPattern).get();
        }
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (!StringUtils.isEmptyOrWhitespace(pattern)) {
            return Pattern.matches(pattern, value);
        }
        LOG.error("Contact info pattern missing!");
        return false;
    }
}


contactInfoType

プロパティは、

application.properties

ファイルで、

email



phone

、または

website

のいずれかの値に設定できます。

contactInfoType=email


3.4. カスタム制約アノテーションを作成する

それでは、今度はカスタム制約用のアノテーションインターフェースを作成しましょう。

@Constraint(validatedBy = { ContactInfoValidator.class })
@Target({ METHOD, FIELD, ANNOTATION__TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactInfo {
    String message() default "Invalid value";

    Class<?>[]groups() default {};

    Class<? extends Payload>[]payload() default {};
}


3.5. カスタム制約を適用する

最後に、

Customer

クラスの

contactInfo

フィールドに検証アノテーションを追加しましょう。

public class Customer {

   //...
    @ContactInfo
    @NotNull
    private String contactInfo;

   //...
}


4 Spring ControllerとHTMLフォーム

検証アノテーションをテストするために、

@ Valid

アノテーションを使用して

Customer

オブジェクトの検証をトリガーするSpring MVCリクエストマッピングを作成します。

@PostMapping("/customer")
public String validateCustomer(@Valid Customer customer, BindingResult result, Model model) {
    if (result.hasErrors()) {
        model.addAttribute("message", "The information is invalid!");
    } else {
        model.addAttribute("message", "The information is valid!");
    }
    return "customer";
}


Customer

オブジェクトはHTMLフォームからコントローラに送信されます。

<form action="customer" method="POST">
Contact Info: <input type="text" name="contactInfo"/> <br/>
<input type="submit" value="Submit"/>
</form>
<span th:text="${message}"></span>

まとめると、アプリケーションをSpring Bootアプリケーションとして実行できます。

@SpringBootApplication
public class DynamicValidationApp {
    public static void main(String[]args) {
        SpringApplication.run(DynamicValidationApp.class, args);
    }
}


5結論

この例では、データベースから動的に正規表現を取得し、それを使用して注釈付きフィールドを検証するカスタム検証注釈を作成する方法を示しました。

例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot[over on GitHub]にあります。