AngularJSとSpring MVCによるフォーム検証
1. 概要
検証は、予想したほど簡単ではありません。 そしてもちろん、ユーザーがアプリケーションに入力した値を検証することは、データの整合性を維持するために非常に重要です。
Webアプリケーションのコンテキストでは、データ入力は通常HTMLフォームを使用して行われ、クライアント側とサーバー側の両方の検証が必要です。
このチュートリアルでは、implementing client-side validation of form input using AngularJS and server-side validation using the Spring MVC frameworkについて説明します。
2. Mavenの依存関係
まず、次の依存関係を追加しましょう。
org.springframework
spring-webmvc
4.3.7.RELEASE
org.hibernate
hibernate-validator
5.4.0.Final
com.fasterxml.jackson.core
jackson-databind
2.8.7
spring-webmvc、hibernate-validator、およびjackson-databindの最新バージョンは、MavenCentralからダウンロードできます。
3. Spring MVCを使用した検証
これは簡単に回避できるため、アプリケーションはクライアント側の検証のみに依存しないでください。 誤った値や悪意のある値が保存されたり、アプリケーションロジックが不適切に実行されたりするのを防ぐには、サーバー側でも入力値を検証することが重要です。
Spring MVCは、JSR 349 Bean Validation仕様アノテーションを使用してサーバー側の検証をサポートします。 この例では、仕様のリファレンス実装であるhibernate-validatorを使用します。
3.1. データモデル
適切な検証アノテーションが付けられたプロパティを持つUserクラスを作成しましょう。
public class User {
@NotNull
@Email
private String email;
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
@Min(18)
@Digits(integer = 2, fraction = 0)
private int age;
// standard constructor, getters, setters
}
上記で使用されている注釈は、hibernate-validatorライブラリに固有の@Emailと@NotBlankを除いて、JSR 349仕様に属しています。
3.2. Spring MVCコントローラー
/userエンドポイントを定義するコントローラークラスを作成しましょう。これは、新しいUserオブジェクトをListに保存するために使用されます。
リクエストパラメータを介して受信したUserオブジェクトの検証を有効にするには、宣言の前に@Validアノテーションを付ける必要があり、検証エラーはBindingResultインスタンスで保持されます。
オブジェクトに無効な値が含まれているかどうかを判断するには、BindingResultのhasErrors()メソッドを使用できます。
hasErrors()がtrueを返す場合、合格しなかった検証に関連するエラーメッセージを含むJSON arrayを返すことができます。 それ以外の場合は、オブジェクトをリストに追加します。
@PostMapping(value = "/user")
@ResponseBody
public ResponseEntity
ご覧のとおり、server-side validation adds the advantage of having the ability to perform additional checks that are not possible on the client side.
この場合、同じメールアドレスのユーザーがすでに存在するかどうかを確認できます。存在する場合は、ステータス409CONFLICTを返します。
また、ユーザーのリストを定義し、いくつかの値で初期化する必要があります。
private List users = Arrays.asList(
new User("[email protected]", "pass", "Ana", 20),
new User("[email protected]", "pass", "Bob", 30),
new User("[email protected]", "pass", "John", 40),
new User("[email protected]", "pass", "Mary", 30));
ユーザーのリストをJSONオブジェクトとして取得するためのマッピングも追加しましょう。
@GetMapping(value = "/users")
@ResponseBody
public List getUsers() {
return users;
}
Spring MVCコントローラーで必要な最後の項目は、アプリケーションのメインページを返すマッピングです。
@GetMapping("/userPage")
public String getUserProfilePage() {
return "user";
}
AngularJSセクションでuser.htmlページを詳しく見ていきます。
3.3. Spring MVC設定
基本的なMVC構成をアプリケーションに追加しましょう。
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example.springmvcforms")
class ApplicationConfiguration implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver htmlViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/html/");
bean.setSuffix(".html");
return bean;
}
}
3.4. アプリケーションの初期化
アプリケーションを実行するためにWebApplicationInitializerインターフェースを実装するクラスを作成しましょう。
public class WebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx
= new AnnotationConfigWebApplicationContext();
ctx.register(ApplicationConfiguration.class);
ctx.setServletContext(container);
container.addListener(new ContextLoaderListener(ctx));
ServletRegistration.Dynamic servlet
= container.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
3.5. Curlを使用したSpringMvc検証のテスト
AngularJSクライアントセクションを実装する前に、次のコマンドでcURLを使用してAPIをテストできます。
curl -i -X POST -H "Accept:application/json"
"localhost:8080/spring-mvc-forms/user?email=aaa&password=12&age=12"
応答は、デフォルトのエラーメッセージを含む配列です。
[
"not a well-formed email address",
"size must be between 4 and 15",
"may not be empty",
"must be greater than or equal to 18"
]
4. AngularJS検証
クライアント側の検証は、有効なデータを正常に送信する方法に関する情報をユーザーに提供し、ユーザーがアプリケーションと引き続き対話できるようにするため、ユーザーエクスペリエンスの向上に役立ちます。
AngularJSライブラリは、フォームフィールドに検証要件を追加し、エラーメッセージを処理し、有効なフォームと無効なフォームをスタイル設定するための優れたサポートを提供します。
まず、検証メッセージに使用されるngMessagesモジュールを挿入するAngularJSモジュールを作成しましょう。
var app = angular.module('app', ['ngMessages']);
次に、前のセクションで構築したAPIを使用するAngularJSサービスとコントローラーを作成しましょう。
4.1. AngularJSサービス
このサービスには、MVCコントローラーメソッドを呼び出す2つのメソッドがあります。1つはユーザーを保存するため、もう1つはユーザーのリストを取得するためです。
app.service('UserService',['$http', function ($http) {
this.saveUser = function saveUser(user){
return $http({
method: 'POST',
url: 'user',
params: {email:user.email, password:user.password,
name:user.name, age:user.age},
headers: 'Accept:application/json'
});
}
this.getUsers = function getUsers(){
return $http({
method: 'GET',
url: 'users',
headers:'Accept:application/json'
}).then( function(response){
return response.data;
} );
}
}]);
4.2. AngularJSコントローラー
UserCtrlコントローラーはUserServiceを挿入し、サービスメソッドを呼び出し、応答メッセージとエラーメッセージを処理します。
app.controller('UserCtrl', ['$scope','UserService', function ($scope,UserService) {
$scope.submitted = false;
$scope.getUsers = function() {
UserService.getUsers().then(function(data) {
$scope.users = data;
});
}
$scope.saveUser = function() {
$scope.submitted = true;
if ($scope.userForm.$valid) {
UserService.saveUser($scope.user)
.then (function success(response) {
$scope.message = 'User added!';
$scope.errorMessage = '';
$scope.getUsers();
$scope.user = null;
$scope.submitted = false;
},
function error(response) {
if (response.status == 409) {
$scope.errorMessage = response.data.message;
}
else {
$scope.errorMessage = 'Error adding user!';
}
$scope.message = '';
});
}
}
$scope.getUsers();
}]);
上記の例では、userFormの$validプロパティがtrueの場合にのみサービスメソッドが呼び出されることがわかります。 それでも、この場合、重複する電子メールの追加チェックがあります。これはサーバー上でのみ実行でき、error()関数で個別に処理されます。
また、フォームが送信されたかどうかを示すsubmitted変数が定義されていることに注意してください。
最初、この変数はfalseになり、saveUser()メソッドを呼び出すと、trueになります。 ユーザーがフォームを送信する前に検証メッセージを表示したくない場合は、submitted変数を使用してこれを防ぐことができます。
4.3. AngularJS検証を使用したフォーム
AngularJSライブラリとAngularJSモジュールを利用するには、user.htmlページにスクリプトを追加する必要があります。
次に、ng-appおよびng-controllerプロパティを設定することにより、モジュールとコントローラーを使用できます。
HTMLフォームを作成しましょう:
デフォルトのHTML5検証を防ぎ、独自の検証に置き換えるために、フォームにnovalidate属性を設定する必要があることに注意してください。
submitted変数の値がtrueの場合、ng-class属性はform-errorCSSクラスをフォームに動的に追加します。
ng-submit属性は、フォームが送信されたときに呼び出されるAngularJSコントローラー関数を定義します。 ng-clickの代わりにng-submitを使用すると、ENTERキーを使用したフォームの送信にも応答するという利点があります。
次に、ユーザー属性の4つの入力フィールドを追加しましょう。
各入力フィールドには、ng-model属性を介してuser変数のプロパティへのバインディングがあります。
For setting validation rulesでは、HTML5required属性といくつかのAngularJS固有の属性ng-minglength, ng-maxlength, ng-min,およびng-trimを使用します。
emailフィールドには、クライアント側の電子メール検証に値emailのtype属性も使用します。
In order to add error messages corresponding to each field、AngularJSはng-messagesディレクティブを提供します。これは、入力の$errorsオブジェクトをループし、各検証ルールに基づいてメッセージを表示します。
入力定義の直後にemailフィールドのディレクティブを追加しましょう。
他の入力フィールドにも同様のエラーメッセージを追加できます。
ブール式でng-showプロパティを使用するemailフィールドのWe can control when the directive is displayed。 この例では、フィールドの値が無効な場合、つまり$invalidプロパティがtrueであり、submitted変数もtrueである場合に、ディレクティブを表示します。
フィールドに対して一度に表示されるエラーメッセージは1つだけです。
$validプロパティに応じて、フィールドが有効な場合は、入力フィールドの後にチェックマーク記号(HEXコード文字✓で表される)を追加することもできます。
✓
AngularJS検証では、ng-validやng-invalidなどのCSSクラス、またはng-invalid-requiredやng-invalid-minlengthなどのより具体的なクラスを使用したスタイリングのサポートも提供されます。
フォームのform-errorクラス内の無効な入力に対してCSSプロパティborder-color:redを追加しましょう。
.form-error input.ng-invalid {
border-color:red;
}
CSSクラスを使用して、エラーメッセージを赤で表示することもできます。
.error-messages {
color:red;
}
すべてをまとめた後、有効な値と無効な値を組み合わせて入力した場合に、クライアント側のフォーム検証がどのように表示されるかの例を見てみましょう。
5. 結論
このチュートリアルでは、AngularJSとSpringMVCを使用してクライアント側とサーバー側の検証を組み合わせる方法を示しました。
いつものように、例の完全なソースコードはover on GitHubにあります。
アプリケーションを表示するには、実行後に/userPageのURLにアクセスします。