3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavalinでWebアプリケーションを構築する

Last updated at Posted at 2019-11-14

Javalinというフレームワークを試してみたので投稿します。

このフレームワークは、参考書や日本語のサイトなどの情報が少ないですが、DocsとTutorialがとてもわかりやすく、特にTutorialには、それぞれサンプルプログラムがGitHUBに投稿されているので、Intellijにそのままインポートしてカスタマイズできたりしますので、WEBアプリを作成するのにあまり困らないでしょう。

環境

カテゴリ
os windows 10 home 64bit
Java 1.8
framework Javalin 3.6
開発環境 IntelliJ IDEA 2019.2

#1. Hello World

Gradleプロジェクトを新規作成して、以下を実装するだけです。JavaがインストールされていればWeb Serverも立ち上がります。Tomcatも必要ありません。

HelloWorld.java
import io.javalin.Javalin;

public class HelloWorld {
    public static void main(String[] args) {
        Javalin app = Javalin.create().start(7000);
        app.get("/", ctx -> ctx.result("Hello World"));
    }
}

#2. Tutorial(Basic website structure)

実践では、Tutorialのサンプルプログラムをダウンロードし、カスタマイズするようなアプローチがいいでしょう。
「Basic website structure」tipsy/javalin-website-exampleをダウンロードして、Intellijで開いてみます。

project.tree
└─src
    └─main
        ├─java
        │  └─app
        │      │  Main.java
        │      ├─book
        │      │      Book.java
        │      │      BookController.java
        │      │      BookDao.java
        │      ├─index
        │      │      IndexController.java
        │      ├─login
        │      │      LoginController.java
        │      ├─user
        │      │      User.java
        │      │      UserController.java
        │      │      UserDao.java
        │      └─util
        │              Filters.java
        │              HerokuUtil.java
        │              MessageBundle.java
        │              Path.java
        │              RequestUtil.java
        │              ViewUtil.java
        └─resources
            ├─localization
            │      messages_de.properties
            │      messages_en.properties
            ├─public
            │  │  main.css
            │  └─img
            │          english.png
            │          favicon.png
            │          german.png
            │          logo.png
            ├─velocity
            │  │  layout.vm
            │  │  notFound.vm
            │  ├─book
            │  │      all.vm
            │  │      one.vm
            │  ├─index
            │  │      index.vm
            │  └─login
            │          login.vm
            └─velocityconfig
                    velocity_implicit.vm

Mainを実行するとそのまま動きます。あとはDAOなどのクラスをデータベースに変換するだけで、プロジェクトテンプレートを作成することができます。

#3. Thymeleaf

さきほどインポートしたプロジェクトのテンプレートエンジンは「velocity」になっています。Thymeleafを使いたい場合は変更が必要です。「javalin」は、thymeleafもデフォルトでサポートしているようですが、dialectに対応していないようなので、カスタマイズしましょう。

htmlのルートは、「/public/templates」とします。以下の構成でファイルを作成していきます。
layout.htmlで、layout-dialectを使ってhtmlのレイアウトを共通化します。

└─src
    ├─main
    │  ├─java
    │  │  └─app
    │  │          AppThymeleafRenderer.java
    │  │          Main.java
    │  └─resources
    │      ├─public
    │      │  └─css
    │      │         main.css
    │      └─templates
    │          │  layout.html
    │          └─example
    │                  index.html

(1) gradle.gradleに以下を追加します。
※Projectは、gradleで焼き直ししています

    compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.11.RELEASE'
    compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.4.1'
    compile "org.webjars:jquery:3.4.1"

(2) ThymeleafRenderer

Thymeleafは、「layout-dialect」を使う場合などカスタマイズする場合独自のrendererを作成する必要があります。

AppThymeleafRenderer.java

import io.javalin.http.Context;
import io.javalin.plugin.rendering.FileRenderer;
import nz.net.ultraq.thymeleaf.LayoutDialect;
import org.jetbrains.annotations.NotNull;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

import java.util.Map;

public class AppThymeleafRenderer implements FileRenderer {

    private final TemplateEngine templateEngine;

    public AppThymeleafRenderer() {
        templateEngine = templateEngine();
    }

    @Override
    public String render(@NotNull String filePath, @NotNull Map<String, Object> model, @NotNull Context ctx) {
        WebContext context =
                new WebContext(ctx.req, ctx.res, ctx.req.getServletContext(), ctx.req.getLocale());
        context.setVariables(model);
        return templateEngine.process(filePath, context);
    }

    private TemplateEngine templateEngine() {
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        // LayoutDialectを追加する。
        templateEngine.addDialect(new LayoutDialect());
        return templateEngine;
    }

    private ITemplateResolver templateResolver() {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        // /templatesフォルダをルートにする。
        templateResolver.setPrefix("/templates/");
        return templateResolver;
    }

}

(3) Main.javaに追加

Mainメソッドで、「JavalinRenderer」に、先に作成した「AppThymeleafRenderer」クラスを追加します。
また、Routerでhtmlを返す場合は、「ctx.render」とします。

Main.java

public class Main {
    public static void main(String[] args) {

//add
        JavalinRenderer.register(new AppThymeleafRenderer(), ".html");
//add end
        Javalin app = Javalin.create(config->{
            config.enableWebjars();
            config.addStaticFiles("/public");
        }).start(7000);
//add
        app.get("/template", ctx -> {
            Map<String, Object> model = new HashMap<>();
            model.put("hello", "hello world");
            ctx.render("/example/index.html", model);
        });
//add end

(4) layout.html

layout.html
<!DOCTYPE html>
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title>Spring Boot Sample Site</title>
    <meta name="description" content="common-meta">
    <script th:src="@{/webjars/jquery/3.4.1/jquery.min.js}"></script>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>
<div class="container">
    <div class="inner">
        <div class="body header">
            <div class="apptitle">Example</div>
        </div>
        <div class="body main">
            <div layout:fragment="contents"></div>
        </div>
        <div class="body footer">
            <footer style="text-align:center;">共通フッタ</footer>
        </div>
    </div>
</div>
</body>
</html>
index.html
<!DOCTYPE html>
<html
        xmlns:th="http://www.thymeleaf.org"
        xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
        layout:decorate="~{/layout.html}">
<head></head>
<body>
<div layout:fragment="contents">
    <div th:text="${hello}">hello</div>
</div>
</body>
</html>

http://localhost:7000/templateにアクセスすると、layoutも正しく出力されてます。

image.png

#4. Database

いろいろ悩んだ末、「Apache commons-dbutils」を使うことにしました。理由は単純にわかりやすいので。Connection Poolは、「HikariCP」、Databaseには「postgresql」を使用します。

build.gradle
    compile "com.zaxxer:HikariCP:2.7.3"
    compile "org.postgresql:postgresql:42.2.8"
    compile "commons-dbutils:commons-dbutils:1.7"
PGDataSource.java

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;

public class PGDataSource {
    private static HikariDataSource ds = null;
    public PGDataSource(){
        HikariConfig hikariconfig = new HikariConfig();
        hikariconfig.setUsername("testuser");
        hikariconfig.setPassword("************************");
        hikariconfig.setJdbcUrl("jdbc:postgresql://localhost:5432/javalindb");
        hikariconfig.setMaximumPoolSize(2);
        ds=new HikariDataSource(hikariconfig);
    }
    public DataSource getDataSource(){
        return ds;
    }
    public void close(){
        if (!ds.isClosed()) ds.close();
    }

}
User.java
import lombok.Data;

@Data
public class User {
    private String username;
    private String password;
    public User(){};
    public User(String username, String password){
        this.username=username;
        this.password=password;
    };
}
Main.java
public class Main {

//add
    private static PGDataSource ds;
    public static Connection getConnection() throws SQLException {
        Connection connection = ds.getDataSource().getConnection();
        return connection;
    }
//add end
    public static void main(String[] args) {
        JavalinRenderer.register(new AppThymeleafRenderer(), ".html");
//add
        ds = new PGDataSource();
//add end
//・・・・・・・
//add
        app.get("/user", ctx -> {
            QueryRunner runner = new QueryRunner();
            ResultSetHandler rsh = new BeanListHandler(User.class);
            List<User> users = (List<User>) runner.query(getConnection(),
                    "select username from public.users",rsh);
            ctx.json(users);
        });
//add end

image.png

これだけわかれば、あとはDocsとTutorialを見ていけばWEBアプリを作成できます。

#5. 参考サイト

Javalinを調べたときのメモ
nodchipの日記-Apache Commons DbUtils

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?