SpringBootパラメータ検証の手法は何ですか?
1. 検証アノテーションを使用する
Spring Boot
には組み込みの検証アノテーションが用意されており、null または空のフィールドのチェックや強制実行など、入力フィールドを簡単かつ迅速に検証できます。長さの制限、正規表現を使用したパターンの検証、および電子メール アドレスの検証。
最も一般的に使用される検証アノテーションには、次のようなものがあります。
@NotNull
: 指定されたフィールドを null にすることはできません。@NotEmpty
: 指定されたリスト フィールドを空にすることはできません。@NotBlank
: 文字列フィールドが空であってはいけない、またはスペースのみが含まれていてはいけないことを指定します。@Min
および@Max
: 数値フィールドの最小値と最大値を指定します。@Pattern
: 文字列フィールドが一致する必要がある正規表現パターンを指定します。@Email
: 文字列フィールドが有効な電子メール アドレスである必要があることを指定します。
具体的な使用法については、次の例を参照してください:
public class User { @NotNull private Long id; @NotBlank @Size(min = 2, max = 50) private String firstName; @NotBlank @Size(min = 2, max = 50) private String lastName; @Email private String email; @NotNull @Min(18) @Max(99) private Integer age; @NotEmpty private List<String> hobbies; @Pattern(regexp = "[A-Z]{2}\d{4}") private String employeeId;
2. カスタム検証アノテーションを使用する
Spring Boot の組み込み検証アノテーションは便利ですが、すべての状況をカバーしているわけではありません。特別なパラメーター検証シナリオがある場合は、Spring の JSR 303 検証フレームワークを使用してカスタム検証アノテーションを作成できます。カスタム アノテーションを使用すると、検証ロジックの再利用性と保守性が向上します。
ユーザーが投稿を作成できるアプリケーションがあるとします。各投稿にはタイトルと本文が必要であり、タイトルはすべての投稿で一意である必要があります。 Spring Boot は、フィールドが空かどうかをチェックするための組み込みの検証アノテーションを提供しますが、一意性をチェックするための組み込みの検証アノテーションは提供しません。この場合、この状況に対処するカスタム検証アノテーションを作成できます。
最初に、カスタム制約アノテーション UniqueTitle
:
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = UniqueTitleValidator.class) public @interface UniqueTitle { String message() default "Title must be unique"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
を作成します。次に、データベースから取得する目的で PostRepository
インターフェイスを作成します。投稿:
public interface PostRepository extends JpaRepository<Post, Long> { Post findByTitle(String title); }
次に、バリデーター クラス UniqueTitleValidator
を次のように定義する必要があります。
@Component public class UniqueTitleValidator implements ConstraintValidator<UniqueTitle, String> { @Autowired private PostRepository postRepository; @Override public boolean isValid(String title, ConstraintValidatorContext context) { if (title == null) { return true; } return Objects.isNull(postRepository.findByTitle(title)); } }
UniqueTitleValidator
は ConstraintValidator
Interface を実装します。 , これには 2 つのジェネリック タイプがあります: 1 つ目はカスタム アノテーション UniqueTitle
、2 つ目は検証されるフィールド タイプ (この場合は String
) です。 PostRepository クラスを使用してデータベースから投稿を取得します。
isValid() メソッドは、
title が null かどうか、または
PostRepository をクエリすることで一意であるかどうかを確認します。
title が null または一意の場合、検証は成功し、true が返されます。
public class Post { @UniqueTitle private String title; @NotNull private String body; }
@UniqueTitle注釈は、
Post クラスの
title 変数に適用されます。このフィールドを検証すると、
UniqueTitleValidator クラスで定義された検証ロジックがトリガーされます。
REST エンドポイントがあるとします。エンドポイントは、ユーザーのユーザー名とパスワードを含む JSON リクエスト本文を期待します。入力が有効であることを確認するには、DTO (データ転送オブジェクト) クラスを作成し、そのフィールドに検証アノテーションを適用します。
public class UserDTO { @NotBlank private String username; @NotBlank private String password; }
@NotBlank アノテーションを使用して、
を確認します。 username および
password フィールドは空または null ではありません。
@RestController @RequestMapping("/users") @Validated public class UserController { @Autowired private UserService userService; @PostMapping public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDto) { userService.createUser(userDto); return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully"); } }
@Validated アノテーションを使用します。メソッドレベルの検証を有効にするには、
@Valid アノテーションを
userDto パラメータに適用して、検証プロセスをトリガーします。
RESTful API がある場合の例です。名前と電子メール アドレスのフィールドが空ではなく、18 歳から 99 歳までであることを確認します。これらのフィールドに加えて、ユーザーがアカウントを作成しようとすると、明確なエラー メッセージまたは「電子メール」も表示されます。重複した「ユーザー名」.メール」。
public class User { @NotBlank(message = "用户名不能为空") private String name; @NotBlank(message = "Email不能为空") @Email(message = "无效的Emaild地址") private String email; @NotNull(message = "年龄不能为空") @Min(value = 18, message = "年龄必须大于18") @Max(value = 99, message = "年龄必须小于99") private Integer age; }
@Valid アノテーションを使用してユーザー入力を検証します。
@RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @PostMapping public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult result) { if (result.hasErrors()) { List<String> errorMessages = result.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.toList()); return ResponseEntity.badRequest().body(errorMessages.toString()); } // save the user to the database using UserService userService.saveUser(user); return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully"); } }
@ Valid を使用します。 アノテーションを使用して
User オブジェクトの検証をトリガーし、
BindingResult オブジェクトを使用して検証エラーをキャッチします。
5.将 i18n 用于错误消息
如果你的应用程序支持多种语言,则必须使用国际化 (i18n) 以用户首选语言显示错误消息。
以下是在 Spring Boot 应用程序中使用 i18n 处理错误消息的示例
首先,在资源目录下创建一个包含默认错误消息的 messages.properties
文件
# messages.properties user.name.required=Name is required. user.email.invalid=Invalid email format. user.age.invalid=Age must be a number between 18 and 99.
接下来,为每种支持的语言创建一个 messages_xx.properties
文件,例如,中文的 messages_zh_CN.properties
。
user.name.required=名称不能为空. user.email.invalid=无效的email格式. user.age.invalid=年龄必须在18到99岁之间.
然后,更新您的验证注释以使用本地化的错误消息
public class User { @NotNull(message = "{user.id.required}") private Long id; @NotBlank(message = "{user.name.required}") private String name; @Email(message = "{user.email.invalid}") private String email; @NotNull(message = "{user.age.required}") @Min(value = 18, message = "{user.age.invalid}") @Max(value = 99, message = "{user.age.invalid}") private Integer age; }
最后,在 Spring 配置文件中配置 MessageSource bean
以加载 i18n
消息文件
@Configuration public class AppConfig { @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; } @Bean public LocalValidatorFactoryBean validator() { LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean(); validatorFactoryBean.setValidationMessageSource(messageSource()); return validatorFactoryBean; } }
现在,当发生验证错误时,错误消息将根据随请求发送的“Accept-Language”标头以用户的首选语言显示。
6.使用分组验证
验证组是 Spring Boot 验证框架的一个强大功能,允许您根据其他输入值或应用程序状态应用条件验证规则。
现在有一个包含三个字段的User
类的情况下:firstName
、lastName
和email
。我们要确保如果 email
字段为空,则 firstName
或 lastName
字段必须非空。否则,所有三个字段都应该正常验证。
为此,我们将定义两个验证组:EmailNotEmpty
和 Default
。EmailNotEmpty
组将包含当 email
字段不为空时的验证规则,而 Default
组将包含所有三个字段的正常验证规则。
创建带有验证组的 User
类
public class User { @NotBlank(groups = Default.class) private String firstName; @NotBlank(groups = Default.class) private String lastName; @Email(groups = EmailNotEmpty.class) private String email; // getters and setters omitted for brevity public interface EmailNotEmpty {} public interface Default {} }
请注意,我们在User
类中定义了两个接口,EmailNotEmpty
和 Default
。这些将作为我们的验证组。
接下来,我们更新Controller
使用这些验证组
@RestController @RequestMapping("/users") @Validated public class UserController { public ResponseEntity<String> createUser( @Validated({org.example.model.ex6.User.EmailNotEmpty.class}) @RequestBody User userWithEmail, @Validated({User.Default.class}) @RequestBody User userWithoutEmail) { // Create the user and return a success response } }
我们已将@Validated
注释添加到我们的控制器,表明我们想要使用验证组。我们还更新了 createUser
方法,将两个 User
对象作为输入,一个在 email
字段不为空时使用,另一个在它为空时使用。
@Validated
注释用于指定将哪个验证组应用于每个 User
对象。对于 userWithEmail
参数,我们指定了 EmailNotEmpty
组,而对于 userWithoutEmail
参数,我们指定了 Default
组。
进行这些更改后,现在将根据“电子邮件”字段是否为空对“用户”类进行不同的验证。如果为空,则 firstName
或 lastName
字段必须非空。否则,所有三个字段都将正常验证。
7.对复杂逻辑使用跨域验证
如果需要验证跨多个字段的复杂输入规则,可以使用跨字段验证来保持验证逻辑的组织性和可维护性。跨字段验证可确保所有输入值均有效且彼此一致,从而防止出现意外行为。
假设我们有一个表单,用户可以在其中输入任务的开始日期和结束日期,并且我们希望确保结束日期不早于开始日期。我们可以使用跨域验证来实现这一点。
首先,我们定义一个自定义验证注解EndDateAfterStartDate
:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = EndDateAfterStartDateValidator.class) public @interface EndDateAfterStartDate { String message() default "End date must be after start date"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
然后,我们创建验证器EndDateAfterStartDateValidator
:
public class EndDateAfterStartDateValidator implements ConstraintValidator<EndDateAfterStartDate, TaskForm> { @Override public boolean isValid(TaskForm taskForm, ConstraintValidatorContext context) { if (taskForm.getStartDate() == null || taskForm.getEndDate() == null) { return true; } return taskForm.getEndDate().isAfter(taskForm.getStartDate()); } }
最后,我们将EndDateAfterStartDate
注释应用于我们的表单对象TaskForm
:
@EndDateAfterStartDate public class TaskForm { @NotNull @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate startDate; @NotNull @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate endDate; }
现在,当用户提交表单时,验证框架将自动检查结束日期是否晚于开始日期,如果不是,则提供有意义的错误消息。
8.对验证错误使用异常处理
可以使用异常处理ExceptionHandler
来统一捕获和处理验证错误。
以下是如何在 Spring Boot 中使用异常处理来处理验证错误的示例:
@RestControllerAdvice public class RestExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { Map<String, Object> body = new LinkedHashMap<>(); body.put("timestamp", LocalDateTime.now()); body.put("status", status.value()); // Get all errors List<String> errors = ex.getBindingResult() .getFieldErrors() .stream() .map(x -> x.getDefaultMessage()) .collect(Collectors.toList()); body.put("errors", errors); return new ResponseEntity<>(body, headers, status); } }
在这里,我们创建了一个用 @RestControllerAdvice
注解的 RestExceptionHandler
类来处理我们的 REST API 抛出的异常。然后我们创建一个用 @ExceptionHandler
注解的方法来处理在验证失败时抛出的 MethodArgumentNotValidException
。
在处理程序方法中,我们创建了一个 Map
对象来保存错误响应的详细信息,包括时间戳、HTTP 状态代码和错误消息列表。我们使用 MethodArgumentNotValidException
对象的 getBindingResult()
方法获取所有验证错误并将它们添加到错误消息列表中。
最后,我们返回一个包含错误响应详细信息的ResponseEntity
对象,包括作为响应主体的错误消息列表、HTTP 标头和 HTTP 状态代码。
有了这个异常处理代码,我们的 REST API 抛出的任何验证错误都将被捕获并以结构化和有意义的格式返回给用户,从而更容易理解和解决问题。
9.测试你的验证逻辑
需要为你的验证逻辑编写单元测试,以帮助确保它正常工作。
@DataJpaTest public class UserValidationTest { @Autowired private TestEntityManager entityManager; @Autowired private Validator validator; @Test public void testValidation() { User user = new User(); user.setFirstName("John"); user.setLastName("Doe"); user.setEmail("invalid email"); Set<ConstraintViolation<User>> violations = validator.validate(user); assertEquals(1, violations.size()); assertEquals("must be a well-formed email address", violations.iterator().next().getMessage()); } }
我们使用 JUnit 5 编写一个测试来验证具有无效电子邮件地址的“用户”对象。然后我们使用 Validator
接口来验证 User
对象并检查是否返回了预期的验证错误。
10.考虑客户端验证
客户端验证可以通过向用户提供即时反馈并减少对服务器的请求数量来改善用户体验。但是,不应依赖它作为验证输入的唯一方法。客户端验证很容易被绕过或操纵,因此必须在服务器端验证输入,以确保安全性和数据完整性。
以上がSpringBootパラメータ検証の手法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Jasypt の概要 Jasypt は、開発者が最小限の労力で基本的な暗号化機能を自分のプロジェクトに追加できる Java ライブラリであり、暗号化の仕組みを深く理解する必要はありません。一方向および双方向暗号化の高いセキュリティ。標準ベースの暗号化テクノロジー。パスワード、テキスト、数値、バイナリを暗号化します... Spring ベースのアプリケーション、オープン API への統合、JCE プロバイダーでの使用に適しています... 次の依存関係を追加します: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1 Jasypt の特典はシステムのセキュリティを保護し、コードが漏洩した場合でもデータ ソースは保証されます。

使用シナリオ 1. 注文は正常に行われましたが、支払いが 30 分以内に行われませんでした。支払いがタイムアウトになり、注文が自動的にキャンセルされました 2. 注文に署名があり、署名後 7 日間評価が行われませんでした。注文がタイムアウトして評価されない場合、システムはデフォルトでプラスの評価を設定します 3. 注文は正常に行われます。販売者が 5 分間注文を受け取らない場合、注文はキャンセルされます。 4. 配送がタイムアウトします。 SMS リマインダーをプッシュします... 遅延が長く、リアルタイム パフォーマンスが低いシナリオでは、タスク スケジュールを使用して定期的なポーリング処理を実行できます。例: xxl-job 今日は選択します

1. Redis は分散ロックの原則を実装しており、分散ロックが必要な理由 分散ロックについて話す前に、分散ロックが必要な理由を説明する必要があります。分散ロックの反対はスタンドアロン ロックです。マルチスレッド プログラムを作成するとき、共有変数を同時に操作することによって引き起こされるデータの問題を回避します。通常、ロックを使用して共有変数を相互に除外し、データの正確性を確保します。共有変数の使用範囲は同じプロセス内です。共有リソースを同時に操作する必要があるプロセスが複数ある場合、どうすれば相互排他的になるのでしょうか?今日のビジネス アプリケーションは通常マイクロサービス アーキテクチャであり、これは 1 つのアプリケーションが複数のプロセスをデプロイすることも意味します。複数のプロセスが MySQL の同じレコード行を変更する必要がある場合、順序の乱れた操作によって引き起こされるダーティ データを避けるために、分散が必要です。今回導入するスタイルはロックされています。ポイントを獲得したい

Springboot はファイルを読み取りますが、jar パッケージにパッケージ化した後、最新の開発にアクセスできません。jar パッケージにパッケージ化した後、Springboot がファイルを読み取れない状況があります。その理由は、パッケージ化後、ファイルの仮想パスが変更されるためです。は無効であり、ストリーム経由でのみアクセスできます。読み取ります。ファイルはリソースの下にあります publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

Springboot+Mybatis-plus が SQL ステートメントを使用して複数テーブルの追加操作を実行しない場合、私が遭遇した問題は、テスト環境で思考をシミュレートすることによって分解されます: パラメーターを含む BrandDTO オブジェクトを作成し、パラメーターをバックグラウンドに渡すことをシミュレートします。 Mybatis-plus で複数テーブルの操作を実行するのは非常に難しいことを理解してください。Mybatis-plus-join などのツールを使用しない場合は、対応する Mapper.xml ファイルを設定し、臭くて長い ResultMap を設定するだけです。対応する SQL ステートメントを記述します。この方法は面倒に見えますが、柔軟性が高く、次のことが可能です。

SpringBoot と SpringMVC はどちらも Java 開発で一般的に使用されるフレームワークですが、それらの間には明らかな違いがいくつかあります。この記事では、これら 2 つのフレームワークの機能と使用法を調べ、その違いを比較します。まず、SpringBoot について学びましょう。 SpringBoot は、Spring フレームワークに基づいたアプリケーションの作成と展開を簡素化するために、Pivotal チームによって開発されました。スタンドアロンの実行可能ファイルを構築するための高速かつ軽量な方法を提供します。

1. RedisAPI のデフォルトのシリアル化メカニズムである RedisTemplate1.1 をカスタマイズします。API ベースの Redis キャッシュ実装では、データ キャッシュ操作に RedisTemplate テンプレートを使用します。ここで、RedisTemplate クラスを開いて、クラスのソース コード情報を表示します。publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations、BeanClassLoaderAware{//キーを宣言、値の各種シリアル化メソッド、初期値は空 @NullableprivateRedisSe

この記事では、dubbo+nacos+Spring Boot の実際の開発について詳しく説明する例を書きます。この記事では理論的な知識はあまり取り上げませんが、dubbo を nacos と統合して開発環境を迅速に構築する方法を説明する最も簡単な例を書きます。
