コンテンツにスキップ

ありがとうございます。

ここから 第9段階:画面設計 + Thymeleaf構成設計 に進みます。

今回は、これまで設計した以下の構成を前提にします。

1
2
3
4
5
教材ライブラリ(LCMS)
        ↓
コース管理(LMS)
        ↓
受講管理

また、画面は以下の3ロールを中心に設計します。

  • 管理者

  • 教師

  • 受講者

※メンターは将来追加できるようにURL・権限設計のみ準備します。


1. Thymeleaf画面構成

パッケージ構成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
templates

├ layout
│  ├ header.html
│  ├ sidebar.html
│  └ base.html
│
├ teacher
│  ├ dashboard.html
│  │
│  └ content
│     ├ list.html
│     ├ create.html
│     ├ edit.html
│     └ detail.html
│
├ admin
│  └ approval
│     ├ list.html
│     └ detail.html
│
├ student
│  ├ course
│  │  ├ list.html
│  │  └ detail.html
│  │
│  └ lesson
│     └ view.html
│
└ error
   ├ 403.html
   └ 404.html

2. 共通レイアウト

利用技術:

  • Thymeleaf Layout Dialect

  • Bootstrap 5


base.html

役割:

  • ヘッダー

  • CSS

  • JavaScript

  • サイドバー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${title}">
        LMS
    </title>

    <link
        href="/css/bootstrap.min.css"
        rel="stylesheet">

</head>

<body>

<div th:replace="~{layout/header :: header}">
</div>

<div class="container-fluid">

    <div class="row">

        <aside class="col-md-2"
               th:replace="~{layout/sidebar :: sidebar}">
        </aside>


        <main class="col-md-10">

            <div th:fragment="content">
            </div>

        </main>

    </div>

</div>

</body>
</html>

3. 教師画面

教師ダッシュボード

URL:

1
/teacher

表示内容:

1
2
3
4
5
6
7
教材数

公開中
審査中
下書き

担当コース数

teacher/dashboard.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<h2>
教材管理
</h2>

<div class="row">

<div class="col-md-3">
<div class="card">
<div class="card-body">

<h5>
教材数
</h5>

<p th:text="${contentCount}">
0
</p>

</div>
</div>
</div>


<div class="col-md-3">
<div class="card">
<div class="card-body">

<h5>
審査中
</h5>

<p th:text="${reviewCount}">
0
</p>

</div>
</div>
</div>

</div>

4. 教材一覧画面

URL:

1
GET /teacher/content

Controller:

1
2
3
ContentQueryService
        ↓
ContentListDto

表示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
------------------------------------------------
教材名 | 種類 | 状態 | 利用数 | 操作
------------------------------------------------

Javaとは
動画
公開中
3コース
詳細

変数
Markdown
下書き
0
編集
------------------------------------------------

list.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<table class="table table-striped">

<thead>
<tr>
<th>
タイトル
</th>

<th>
種類
</th>

<th>
状態
</th>

<th>
利用数
</th>

<th>
操作
</th>

</tr>
</thead>


<tbody>

<tr th:each="content:${contents}">

<td th:text="${content.title}">
</td>

<td th:text="${content.contentType}">
</td>

<td th:text="${content.status}">
</td>

<td th:text="${content.usageCount}">
</td>


<td>

<a class="btn btn-primary btn-sm"
th:href="@{/teacher/content/{id}(id=${content.id})}">
詳細
</a>

</td>


</tr>

</tbody>

</table>

5. 教材作成画面

教材タイプによってFormを切り替えます。


URL

1
GET /teacher/content/create

入力項目:

共通:

1
2
3
4
5
タイトル

概要

教材タイプ

動画の場合:

1
2
3
4
5
6
7
動画種類

Youtube URL

Vimeo URL

R2 URL

Markdown:

1
2
3
4
5
本文
形式

Markdown
Text

Quiz:

1
2
3
4
5
問題文

選択肢

正解

6. Markdown表示

入力:

1
2
3
4
5
6
7
8
# Javaとは

Javaはプログラミング言語です。

## 特徴

- JVM
- オブジェクト指向

保存:

1
ContentVersion.body

表示時:

1
2
3
4
5
6
7
8
9
Markdown

↓

HTML

↓

Thymeleaf

推奨ライブラリ:

Gradle:

1
2
3
implementation(
"com.vladsch.flexmark:flexmark-all:0.64.8"
)

Service:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public String markdownToHtml(
        String markdown){

    Parser parser =
        Parser.builder().build();

    HtmlRenderer renderer =
        HtmlRenderer.builder().build();


    Node document =
        parser.parse(markdown);


    return renderer.render(document);
}

7. 動画表示画面

URL:

1
/student/lesson/{lessonId}

表示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Javaとは

------------------

[ Youtube Player ]

------------------

概要

添付資料

次へ

Youtube例

1
2
3
4
5
<iframe
width="800"
height="450"
th:src="${videoUrl}">
</iframe>

8. R2動画設計

Cloudflare R2の場合:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Browser

↓

Spring Controller

↓

署名URL発行

↓

Cloudflare R2

↓

Streaming

DB:

1
2
3
video_url

https://xxx.r2.cloudflarestorage.com/video001.mp4

ではなく、

1
2
3
storage_key

videos/java001/master.m3u8

管理を推奨します。


将来的には:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
mp4

↓

HLS

↓

master.m3u8

↓

segment.ts

方式にします。


9. クイズ画面

表示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Q1

Javaの特徴は?

○ JVMで動作する

○ OS専用

○ コンパイル不要

○ ブラウザ専用


[回答する]

Form:

1
2
3
4
5
6
7
8
@Data
public class QuizAnswerForm {

    private Long quizId;

    private List<Long> choiceIds;

}

10. 管理者承認画面

URL:

1
/admin/approval

一覧:

1
2
3
4
5
6
7
8
------------------------------------------------
教材       作成者       状態       操作
------------------------------------------------

Javaとは   山田先生   審査中

[詳細]
------------------------------------------------

詳細:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
教材内容

↓

プレビュー

↓

承認

↓

差戻し

11. 受講者コース一覧

URL:

1
/student/course

表示:

1
2
3
4
5
Java基礎講座

Java入門講座

Spring Boot入門

12. コース詳細

重要画面です。

構造:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Java基礎

├ 第1章 Java基礎

│
├ Lesson1 Javaとは
│      動画
│
├ Lesson2 変数
│      Markdown
│
└ Lesson3 確認テスト

Thymeleafでは再帰Fragmentを利用します。


section/tree.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div th:fragment="tree(section)">

<div class="card">

<div class="card-header">

<span th:text="${section.title}">
</span>

</div>


<div class="card-body">

<div th:each="child:${section.children}"
     th:replace="~{section/tree :: tree(${child})}">
</div>


</div>

</div>

</div>

13. Spring Security画面制御

Thymeleaf:

1
2
3
4
5
6
7
<div sec:authorize="hasRole('TEACHER')">

<a href="/teacher/content">
教材管理
</a>

</div>

依存:

1
2
3
implementation(
"org.thymeleaf.extras:thymeleaf-extras-springsecurity6"
)

14. URL設計まとめ

教師

URL 機能
/teacher ダッシュボード
/teacher/content 教材一覧
/teacher/content/create 教材作成
/teacher/content/{id} 教材詳細
/teacher/course コース管理

管理者

URL 機能
/admin 管理トップ
/admin/approval 承認一覧
/admin/approval/{id} 承認詳細

受講者

URL 機能
/student/course コース一覧
/student/course/{id} コース詳細
/student/lesson/{id} レッスン表示

第9段階終了時点

現在の完成状態:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
DB設計
   ↓
Entity設計
   ↓
Repository
   ↓
Mapper
   ↓
Service
   ↓
Controller
   ↓
Thymeleaf画面設計

まで一貫した設計になりました。


次の 第10段階 では、認証・認可を実装します。

内容:

  1. Spring Security 6設定

  2. Login画面

  3. UserDetailsService

  4. BCryptパスワード管理

  5. Roleによるアクセス制御

  6. ログインユーザー取得

  7. 教師の教材編集権限制御

  8. 管理者承認権限制御

教材管理システムでは権限管理が非常に重要なため、次はここを固めます。