1. 概要

現在、 Spring Play GrailsなどのJEEベースのフレームワークがWebアプリケーション開発に利用できます。

他のものよりもそれらの1つを選択する理由があるかもしれません。 ただし、私たちの選択は、ユースケースと解決しようとしている問題にも依存します。

この入門チュートリアルでは、Ninja Webフレームワークを調べて、簡単なWebアプリケーションを作成します。 同時に、それが提供するいくつかの基本的な機能を調べます。

2. 忍者

Ninja は、フルスタックでありながら軽量のWebフレームワークであり、既存のJavaライブラリを利用して作業を実行します。

HTMLからJSONレンダリング、永続性からテストまでの機能を備えた、スケーラブルなWebアプリケーションを構築するためのワンストップソリューションです。

これは、設定より規約パラダイムに従い、コードをモデルコントローラー、サービスなどのパッケージに分類します。

Ninjaは、JSON / XMLレンダリング用のJackson、依存関係管理用のGuice、永続性用のHibernate、データベース移行用のFlywayなどの主要機能に人気のあるJavaライブラリを使用しています。

迅速な開発のために、コードのホットリロード用にSuperDevModeを提供します。 そのため、開発環境での変更を即座に確認できます。

3. 設定

Ninjaには、Webアプリケーションを作成するための標準的なツールセットが必要です。

  • Java1.8以降
  • Maven3以降
  • IDE(EclipseまたはIntelliJ)

Mavenアーキタイプを使用して、Ninjaプロジェクトをすばやくセットアップします。 グループID、アーティファクトID、バージョン番号の後にプロジェクト名を入力するように求められます。

mvn archetype:generate -DarchetypeGroupId=org.ninjaframework \
  -DarchetypeArtifactId=ninja-servlet-archetype-simple

または、既存のMavenプロジェクトの場合、最新のninja-core依存関係をpom.xmlに追加できます。

<dependency>
    <groupId>org.ninjaframework</groupId>
    <artifactId>ninja-core</artifactId>
    <version>6.5.0</version>
</dependency>

次に、Mavenコマンドを実行して、ファイルを初めてコンパイルします。

mvn clean install

最後に、Ninjaが提供するMavenコマンドを使用してアプリを実行しましょう。

mvn ninja:run

出来上がり! アプリケーションが起動し、 localhost:8080からアクセスできるようになります。

4. プロジェクト構造

Ninjaによって作成されたMavenのようなプロジェクト構造を見てみましょう。

フレームワークは、規則に基づいていくつかのパッケージを作成します。

Javaクラスは、 src / main/javaのconf controllers models 、およびservicesディレクトリに分類されます。[ X148X]

同様に、 src / test / java は、対応する単体テストクラスを保持します。

src / main /javaの下のviewsディレクトリには、HTMLファイルが含まれています。 また、 src / main / java / asset ディレクトリには、画像、スタイルシート、JavaScriptファイルなどのリソースが含まれています。

5. コントローラ

フレームワークのいくつかの基本的な機能について説明する準備が整いました。 コントローラは、要求を受信し、特定の結果を含む応答を返すクラスです。

まず、従うべきいくつかの規則について説明しましょう。

  • controllers パッケージにクラスを作成し、名前の末尾にControllerを付けます。
  • リクエストを処理するメソッドは、Resultクラスのオブジェクトを返す必要があります

HTMLをレンダリングする簡単なメソッドを使用してApplicationControllerクラスを作成しましょう。

@Singleton
public class ApplicationController {
    public Result index() {
        return Results.html();
    }
}

ここで、 index メソッドは、Resultsクラスのhtmlメソッドを呼び出してHTMLをレンダリングします。 Result オブジェクトは、応答コード、ヘッダー、Cookieなどのコンテンツをレンダリングするために必要なすべてのものを保持します。

注: Guiceの@Singletonアノテーションでは、アプリ全体でコントローラーのインスタンスを1つだけ許可します

6. 意見

index メソッドの場合、Ninjaは views /ApplicationControllerディレクトリの下にあるindex .ftl.htmlというHTMLファイルを検索します。

NinjaはHTMLレンダリングにFreemarkerテンプレートエンジンを使用します。 したがって、 views の下にあるすべてのファイルには、.ftl.html拡張子が付いている必要があります。

indexメソッドのi ndex .ftl.htmlファイルを作成しましょう。

<html>  
<head>
    <title>Ninja: Index</title>
</head>
<body>
    <h1>${i18n("helloMsg")}</h1>
    <a href="/userJson">User Json</a>
</body>
</html>

ここでは、Ninjaが提供する i18n タグを使用して、message.propertiesファイルからhelloMsgプロパティを取得しました。 これについては、後の国際化のセクションで詳しく説明します。

7. ルート

次に、リクエストがindexメソッドに到達するためのルートを定義します。

Ninjaは、confパッケージのRoutesクラスを使用して、URLをコントローラーの特定のメソッドにマップします。

ApplicationControllerindexメソッドにアクセスするためのルートを追加しましょう。

public class Routes implements ApplicationRoutes {
    @Override
    public void init(Router router) {          
        router.GET().route("/index").with(ApplicationController::index);
    }
}

それでおしまい! localhost:8080 /indexindexページにアクセスする準備が整いました。

8. JSONレンダリング

すでに説明したように、NinjaはJSONレンダリングにJacksonを使用します。 JSONコンテンツをレンダリングするには、Resultsクラスのjsonメソッドを使用できます。

userJsonメソッドをApplicationControllerクラスに追加し、単純なHashMapのコンテンツをJSONでレンダリングしてみましょう。

public Result userJson() {
    HashMap<String, String> userMap = new HashMap<>();
    userMap.put("name", "Norman Lewis");
    userMap.put("email", "[email protected]");    
    return Results.json().render(user);
}

次に、userJsonにアクセスするために必要なルーティングを追加します。

router.GET().route("/userJson").with(ApplicationController::userJson);

これで、 localhost:8080 /userJsonを使用してJSONをレンダリングできます。

9. サービス

ビジネスロジックをコントローラから分離して、必要に応じてサービスを注入するサービスを作成できます。

まず、抽象化を定義するための単純なUserServiceインターフェースを作成しましょう。

public interface UserService {
    HashMap<String, String> getUserMap();
}

次に、UserServiceインターフェイスをUserServiceImplクラスに実装し、getUserMapメソッドをオーバーライドします。

public class UserServiceImpl implements UserService {
    @Override
    public HashMap<String, String> getUserMap() {
        HashMap<String, String> userMap = new HashMap<>(); 
        userMap.put("name", "Norman Lewis"); 
        userMap.put("email", "[email protected]"); 
        return userMap;
    }
}

次に、Guiceが提供するNinjaの依存性注入機能を使用して、UserServiceインターフェイスをUserServiceImplクラスにバインドします。

confパッケージで利用可能なModuleクラスにバインディングを追加しましょう。

@Singleton
public class Module extends AbstractModule {
    protected void configure() {        
        bind(UserService.class).to(UserServiceImpl.class);
    }
}

最後に、 @Inject アノテーションを使用して、UserService依存関係をApplicationControllerクラスに挿入します。

public class ApplicationController {
    @Inject
    UserService userService;
    
    // ...
}

したがって、ApplicationControllerUserServicegetUserMapメソッドを使用するように設定されています。

public Result userJson() {
    HashMap<String, String> userMap = userService.getUserMap();
    return Results.json().render(userMap);
}

10. フラッシュスコープ

Ninjaは、Flash Scopeと呼ばれる機能を介して、リクエストからの成功メッセージとエラーメッセージを処理するためのシンプルで効率的な方法を提供します。

コントローラで使用するには、FlashScope引数をメソッドに追加します。

public Result showFlashMsg(FlashScope flashScope) {
    flashScope.success("Success message");
    flashScope.error("Error message");
    return Results.redirect("/home");
}

注:Resultsクラスのredirectメソッドは、ターゲットを指定されたURLにリダイレクトします。

次に、ルーティング /flashshowFlashMsgメソッドに追加し、フラッシュメッセージを表示するようにビューを変更します。

<#if (flash.error)??>
    <div class="alert alert-danger">
        ${flash.error}
    </div>
</#if>
<#if (flash.success)??>
    <div class="alert alert-success">
        ${flash.success}
    </div>
</#if>

これで、 FlashScopelocalhost:8080 /flashで動作していることがわかります。

11. 国際化

Ninjaは、構成が簡単な組み込みの国際化機能を提供します。

まず、application.confファイルでサポートされている言語のリストを定義します。

application.languages=fr,en

次に、デフォルトのプロパティファイル(英語の場合は messages.properties )を作成し、メッセージのキーと値のペアを使用します。

header.home=Home!
helloMsg=Hello, welcome to Ninja Framework!

同様に、言語固有のプロパティファイルのファイル名に言語コードを追加できます。たとえば、フランス語の場合はmessage_fr.propertiesファイルです。

header.home=Accueil!
helloMsg=Bonjour, bienvenue dans Ninja Framework!

構成の準備ができたら、ApplicationControllerクラスで国際化を簡単に有効にできます。

LangクラスまたはMessagesクラスを使用する方法は、次の2つです。

@Singleton
public class ApplicationController {
    @Inject
    Lang lang;

    @Inject
    Messages msg;
    
    // ...
}

次に、 Lang クラスを使用して、結果の言語を設定できます。

Result result = Results.html();
lang.setLanguage("fr", result);

同様に、 Messages クラスを使用すると、言語固有のメッセージを取得できます。

Optional<String> language = Optional.of("fr");        
String helloMsg = msg.get("helloMsg", language).get();

12. 永続性

NinjaはJPA2.0をサポートし、Hibernateを利用してWebアプリケーションでの永続性を有効にします。 また、迅速な開発のための組み込みのH2データベースサポートを提供します。

12.1. モデル

データベース内のテーブルに接続するには、Entityクラスが必要です。 このため、Ninjaは、modelsパッケージでエンティティクラスを検索するという規則に従います。 そこで、Userエンティティクラスを作成します。

@Entity
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Long id;
    public String firstName;
    public String email;  
}

次に、Hibernateを構成し、データベース接続の詳細を設定します。

12.2. 構成

Hibernate構成の場合、Ninjaはpersistence.xmlファイルがsrc/ main / java /META-INFディレクトリにあることを想定しています。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  version="2.0">
   
    <!-- Database settings for development -->
    <persistence-unit name="dev_unit"
      transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.connection.autocommit" value="true" />
        </properties>
    </persistence-unit>
</persistence>

次に、データベース接続の詳細をapplication.confに追加します。

ninja.jpa.persistence_unit_name=dev_unit
db.connection.url=jdbc:h2:./devDb
db.connection.username=sa
db.connection.password=

12.3. EntityManager

最後に、Guiceの Provider クラスを使用して、EntityManagerのインスタンスをApplicationControllerに挿入します。

public class ApplicationController {
    @Inject 
    Provider<EntityManager> entityManagerProvider;

    // ...
}

これで、EntityManagerを使用してUserオブジェクトを永続化する準備が整いました。

@Transactional
public Result insertUser(User user) {
    EntityManager entityManager = entityManagerProvider.get();
    entityManager.persist(user);
    entityManager.flush();
    return Results.redirect("/home");
}

同様に、 EntityManager を使用して、DBからUserオブジェクトを読み取ることができます。

@UnitOfWork
public Result fetchUsers() {
    EntityManager entityManager = entityManagerProvider.get();
    Query q = entityManager.createQuery("SELECT x FROM User x");
    List<User> users = (List<User>) q.getResultList();
    return Results.json().render(users);
}

ここで、Ninjaの @UnitOfWork アノテーションは、トランザクションを処理せずにデータベース接続に関するすべてを処理します。 したがって、通常はトランザクションを必要としない読み取り専用クエリに便利です。

13. 検証

Ninjaは、JSR303仕様に従うことにより、Bean検証の組み込みサポートを提供します。

Userエンティティのプロパティに@NotNullアノテーションを付けて、機能を調べてみましょう。

public class User {
    // ...
    
    @NotNull
    public String firstName;
}

次に、検証を有効にするために、ApplicationControllerですでに説明したinsertUserメソッドを変更します。

@Transactional
public Result insertUser(FlashScope flashScope, @JSR303Validation User user, Validation validation) {
    if (validation.getViolations().size() > 0) {
        flashScope.error("Validation Error: User can't be created");
    } else {
        EntityManager entityManager = entitiyManagerProvider.get();
        entityManager.persist(user);
        entityManager.flush();
        flashScope.success("User '" + user + "' is created successfully");
    }
    return Results.redirect("/home");
}

Ninjaの@JSR303Validation アノテーションを使用して、Userオブジェクトの検証を有効にしました。 次に、 Validation 引数を追加して、 hasViolations getViolations addViolationなどのメソッドによる検証を処理します。

最後に、 FlashScope オブジェクトを使用して、検証エラーを画面に表示します。

注:Ninjaは、Bean検証のJSR303仕様に従います。 ただし、JSR380仕様( Bean Validation 2.0 )が新しい標準です。

14. 結論

この記事では、Ninja Webフレームワーク(一般的なJavaライブラリを使用して便利な機能を提供するフルスタックフレームワーク)について説明しました。

まず、コントローラーモデル、サービスを使用して簡単なWebアプリケーションを作成しました。 次に、永続性のためにアプリでJPAサポートを有効にしました。

同時に、ルート、JSONレンダリング、国際化、Flashスコープなどのいくつかの基本的な機能を見ました。

最後に、フレームワークによって提供される検証サポートについて説明しました。

いつものように、すべてのコード実装はGitHub利用できます。