サーブレット&JSPの基本|Springで学習ペース診断を作成する

ServletとJSPで作った学習ペース診断を、Spring MVCで作り直そう。Controller、Service、Model、JSPをつなげて、リクエストスコープで診断結果を表示する流れを身に付けよう

これまで、ServletとJSPを使って、リクエストスコープを利用したWebアプリケーションを作成してきました。

その中で扱った題材の1つが、「学習ペース診断アプリ」です。

学習ペース診断アプリでは、利用者が目標学習時間と実際の学習時間を入力します。

サーバ側では、その2つの値をもとに達成率を計算し、学習ペースが順調なのか、少し足りないのか、大きく不足しているのかを判定します。

そして、計算結果をリクエストスコープに保存し、JSPで表示します。

この流れは、ServletとJSPで学んだMVCモデルの基本そのものです。

Spring MVCでも、考え方は大きく変わりません。

ただし、作り方が変わります。

Servletの代わりにControllerを作成します。

Logicクラスに相当する処理はServiceとして作成します。

データを格納するクラスは、通常のJavaクラスとして作成します。

結果画面の表示は、これまでと同じようにJSP、EL式、JSTLを使って行えます。

この記事では、以前作成した学習ペース診断アプリを、Springプロジェクトspring_studyで作り直します。

プロジェクトのベースパッケージはcom.example.demoとします。

データを格納するStudyPaceクラスはcom.example.demo.modelパッケージに配置します。

学習ペースの計算と判定を行うStudyPaceServiceクラスもcom.example.demo.modelパッケージに配置します。

リクエストを受け取るStudyCheckControllerクラスはcom.example.demo.controllerパッケージに配置します。

入力画面はstudyCheck.jsp、結果画面はstudyCheckResult.jspとして、src/main/webapp/WEB-INF/jspに配置します。

学習ペース診断アプリの流れ

学習ペース診断アプリでは、最初に入力画面を表示します。

利用者は、1日の目標学習時間と実際の学習時間を入力します。

送信ボタンをクリックすると、POSTリクエストがControllerに送信されます。

Controllerは、リクエストパラメータを受け取り、StudyPaceインスタンスに値を設定します。

その後、StudyPaceServiceに処理を依頼します。

StudyPaceServiceは、目標学習時間と実際の学習時間から達成率を計算し、判定結果をStudyPaceに設定します。

Controllerは、処理結果が入ったStudyPaceインスタンスをリクエストスコープに保存します。

最後に、結果画面であるstudyCheckResult.jspへフォワードし、JSPで診断結果を表示します。

Spring版学習ペース診断の役割分担

役割ファイル名内容
ModelStudyPace.java目標時間、実績時間、達成率、判定結果を持つ
ServiceStudyPaceService.java達成率を計算し、判定結果を設定する
ControllerStudyCheckController.java入力画面表示、POST処理、リクエストスコープ保存を行う
ViewstudyCheck.jsp目標時間と実績時間の入力画面を表示する
ViewstudyCheckResult.jsp学習ペース診断の結果を表示する

Springでは、Servletで作っていたコントローラ部分が、Spring MVCのControllerに変わります。

また、これまでLogicクラスとして作っていた処理担当クラスは、SpringではServiceとして作成します。

ビューにはJSPを使用します。

図1:Spring版学習ペース診断アプリの全体像

この図から分かること

Spring版の学習ペース診断アプリでは、Controller、Service、Model、JSPが連携して動きます。

入力画面で入力された目標学習時間と実際の学習時間は、StudyCheckControllerで受け取ります。

StudyCheckControllerはStudyPaceServiceに処理を依頼し、達成率と判定結果をStudyPaceに設定してもらいます。

処理後のStudyPaceはリクエストスコープに保存され、studyCheckResult.jspで表示されます。

ServletとJSPで作ったときの流れを、Spring MVCの形に置き換えていることが分かります。

Springプロジェクトの作成と構成

まず、Springプロジェクトspring_studyを用意します。

すでにspring_studyを作成済みであれば、新しく作り直す必要はありません。

まだ作成していない場合は、Spring Initializrを使ってSpringプロジェクトを作成します。

プロジェクトの主な設定

項目設定
プロジェクト名spring_study
ベースパッケージcom.example.demo
Controller配置先com.example.demo.controller
ModelとService配置先com.example.demo.model
JSP配置先src/main/webapp/WEB-INF/jsp

Springプロジェクトでは、ベースパッケージの下に役割ごとのパッケージを作成します。

Controllerはcom.example.demo.controllerに配置します。

ModelやServiceはcom.example.demo.modelに配置します。

JSPはsrc/main/webapp/WEB-INF/jspに配置します。

作成するファイル

種類ファイル名配置場所
データクラスStudyPace.javacom.example.demo.model
サービスクラスStudyPaceService.javacom.example.demo.model
コントローラクラスStudyCheckController.javacom.example.demo.controller
入力画面studyCheck.jspsrc/main/webapp/WEB-INF/jsp
結果画面studyCheckResult.jspsrc/main/webapp/WEB-INF/jsp

すべてのファイルを作成したら、ブラウザから次のURLへアクセスして動作を確認します。

http://localhost:8080/StudyCheck

Springプロジェクトでは、Eclipseの実行機能から特定のクラスやJSPを直接実行するよりも、アプリケーションを起動したうえでブラウザからURLを直接入力して確認するほうが確実です。

開発時のエラー対応

Springを使うと、エラー画面やメッセージの見た目が、これまでの動的Webプロジェクトとは違って見えることがあります。

しかし、原因を探す基本は変わりません。

画面が表示されない場合は、URL、Controllerの@GetMapping、ビュー名、JSPの配置場所を確認します。

POST送信がうまくいかない場合は、formタグのaction、method、Controllerの@PostMapping、リクエストパラメータ名を確認します。

結果が表示されない場合は、リクエストスコープに正しい属性名で保存されているか、JSP側で同じ属性名を使っているかを確認します。

エラー時に確認するポイント

状況確認すること
404エラーになるURLと@GetMappingの指定が一致しているか
JSPが見つからないapplication.propertiesのprefixとsuffix、JSPの配置場所を確認する
入力値が取得できないinputタグのname属性と@RequestParamの名前が一致しているか
結果が表示されないrequest.setAttributeの属性名とJSPのEL式が一致しているか
Serviceが使えない@Service、@RequiredArgsConstructor、finalフィールドを確認する

Springでは仕組みが増えますが、ServletとJSPで学んだリクエスト、レスポンス、スコープ、フォワードの考え方はそのまま役に立ちます。

情報を持つクラスを作成する

最初に、学習ペース診断の情報を持つStudyPaceクラスを作成します。

StudyPaceクラスには、目標学習時間、実際の学習時間、達成率、判定結果を保存します。

StudyPaceクラスが持つ情報

フィールド内容
goalHoursdouble目標学習時間
actualHoursdouble実際の学習時間
achievementRatedouble達成率
judgmentString判定結果

このクラスは、診断に必要な値と、診断結果をまとめて持つ入れ物です。

Controllerでインスタンスを作成し、Serviceで計算結果を設定し、JSPで結果を表示します。

ここでは、Lombokの@Dataを使って、getterやsetterを自動生成します。

学習ペース診断に関する情報を持つクラスの例

ファイル名: StudyPace.java

package com.example.demo.model;

import java.io.Serializable;

import lombok.Data;

@Data
public class StudyPace implements Serializable {
    private double goalHours;
    private double actualHours;
    private double achievementRate;
    private String judgment;
}

StudyPace.javaは、com.example.demo.modelパッケージに作成します。

@Dataを付けることで、getter、setter、toString、equals、hashCodeなどがLombokによって自動生成されます。

そのため、StudyPaceクラスの中にgetGoalHoursやsetGoalHoursなどを手書きする必要はありません。

Serializableを実装しているのは、このクラスのインスタンスをWebアプリケーション内で扱いやすくするためです。

リクエストスコープに保存してJSPで表示する場合でも、JavaBeansとして扱いやすい形になります。

サービスクラスを作成する

次に、学習ペース診断の処理を担当するサービスクラスを作成します。

ServletとJSPで作成したときは、StudyPaceLogicのようなLogicクラスが計算や判定を担当していました。

Springでは、このような主たる処理を担当するクラスをServiceとして作成します。

ここでは、クラス名をStudyPaceServiceとします。

StudyPaceServiceの役割

役割内容
目標時間を取得するStudyPaceからgoalHoursを取得する
実績時間を取得するStudyPaceからactualHoursを取得する
達成率を計算するactualHours ÷ goalHours × 100で計算する
判定を決める達成率に応じて判定結果を設定する
結果をStudyPaceに保存するachievementRateとjudgmentを設定する

たとえば、目標学習時間が120分、実際の学習時間が90分であれば、達成率は75.0%です。

この場合は、少し不足している状態として、判定結果をやや不足にします。

学習ペース診断に関する処理を行うサービスの例

ファイル名: StudyPaceService.java

package com.example.demo.model;

import org.springframework.stereotype.Service;

@Service
public class StudyPaceService {

    public void execute(StudyPace studyPace) {
        double goalHours = studyPace.getGoalHours();
        double actualHours = studyPace.getActualHours();

        double achievementRate = actualHours / goalHours * 100;
        studyPace.setAchievementRate(achievementRate);

        String judgment;
        if (achievementRate >= 100) {
            judgment = "順調";
        } else if (achievementRate >= 70) {
            judgment = "やや不足";
        } else {
            judgment = "大きく不足";
        }
        studyPace.setJudgment(judgment);
    }
}

StudyPaceService.javaは、com.example.demo.modelパッケージに作成します。

@Serviceを付けることで、Springはこのクラスをサービスとして認識します。

executeメソッドは、StudyPaceインスタンスを受け取ります。

StudyPaceから目標学習時間と実際の学習時間を取り出し、達成率を計算します。

達成率が100以上なら順調、70以上100未満ならやや不足、70未満なら大きく不足と判定します。

最後に、達成率と判定結果をStudyPaceに設定します。

このように、計算や判定のようなアプリケーションの主な処理は、ControllerではなくServiceに書きます。

図2:StudyPaceServiceが達成率と判定結果を設定する流れ

この図から分かること

StudyPaceServiceは、StudyPaceに保存された目標学習時間と実際の学習時間を使って達成率を計算します。

計算式は、実際の学習時間 ÷ 目標学習時間 × 100です。

たとえば、目標学習時間が120分、実際の学習時間が90分なら、達成率は75.0%です。

その結果、判定はやや不足になります。

計算結果と判定結果は、同じStudyPaceインスタンスに設定されます。

コントローラクラスを作成する

次に、リクエストを処理するControllerを作成します。

ServletとJSPで作成したときは、StudyCheckサーブレットのdoGetとdoPostで処理していました。

Springでは、StudyCheckControllerという通常のJavaクラスを作成し、@Controllerを付けます。

doGetに相当する処理は@GetMappingを付けたハンドラメソッドに書きます。

doPostに相当する処理は@PostMappingを付けたハンドラメソッドに書きます。

ServletからSpring Controllerへの置き換え

ServletとJSPでの作り方Springでの作り方
StudyCheckサーブレットStudyCheckController
doGet@GetMappingを付けたメソッド
doPost@PostMappingを付けたメソッド
request.getParameter@RequestParam
new StudyPaceLogicDIでStudyPaceServiceを利用
request.setAttributeHttpServletRequestのsetAttribute
RequestDispatcherでフォワードreturnでビュー名を返す

Springでは、Serviceをnewで作成しません。

@RequiredArgsConstructorとfinalフィールドを使い、コンストラクタインジェクションでStudyPaceServiceを利用します。

学習ペース診断に関するリクエストを処理するコントローラの例

ファイル名: StudyCheckController.java

package com.example.demo.controller;

import jakarta.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.example.demo.model.StudyPace;
import com.example.demo.model.StudyPaceService;

import lombok.RequiredArgsConstructor;

@Controller
@RequiredArgsConstructor
public class StudyCheckController {

    private final StudyPaceService studyPaceService;

    @GetMapping("/StudyCheck")
    public String showStudyCheck() {
        // フォワード
        return "studyCheck";
    }

    @PostMapping("/StudyCheck")
    public String executeStudyCheck(
            @RequestParam double goalHours,
            @RequestParam double actualHours,
            HttpServletRequest request) {

        // 入力値をプロパティに設定
        StudyPace studyPace = new StudyPace();
        studyPace.setGoalHours(goalHours);
        studyPace.setActualHours(actualHours);

        // 学習ペース診断を実行し結果を設定
        this.studyPaceService.execute(studyPace);

        // リクエストスコープに保存
        request.setAttribute("studyPace", studyPace);

        // フォワード
        return "studyCheckResult";
    }
}

StudyCheckController.javaは、com.example.demo.controllerパッケージに作成します。

@Controllerを付けることで、Springはこのクラスをコントローラとして認識します。

@RequiredArgsConstructorを付けることで、finalが付いたstudyPaceServiceフィールドを引数にもつコンストラクタがLombokによって自動生成されます。

StudyPaceServiceには@Serviceが付いているため、SpringがStudyPaceServiceのインスタンスを用意し、StudyCheckControllerに注入してくれます。

@GetMapping("/StudyCheck")が付いたshowStudyCheckメソッドは、入力画面を表示します。

戻り値としてstudyCheckを返しているため、SpringはstudyCheck.jspへフォワードします。

@PostMapping("/StudyCheck")が付いたexecuteStudyCheckメソッドは、診断実行時に呼び出されます。

@RequestParam double goalHoursで、リクエストパラメータgoalHoursを受け取ります。

@RequestParam double actualHoursで、リクエストパラメータactualHoursを受け取ります。

その後、StudyPaceインスタンスを作成し、入力値を設定します。

StudyPaceServiceのexecuteメソッドを呼び出して、達成率と判定結果を設定します。

処理後のStudyPaceインスタンスは、studyPaceという属性名でリクエストスコープに保存します。

最後に、studyCheckResultというビュー名を返し、結果画面へフォワードします。

図3:Controller、Service、JSPが連携する処理の流れ

この図から分かること

入力画面からPOSTリクエストが送られると、StudyCheckControllerの@PostMappingが付いたメソッドが実行されます。

Controllerは、リクエストパラメータgoalHoursとactualHoursを受け取り、StudyPaceに設定します。

その後、StudyPaceServiceに診断処理を依頼します。

Serviceは、達成率と判定結果をStudyPaceに設定します。

Controllerは処理後のStudyPaceをリクエストスコープに保存し、studyCheckResult.jspへフォワードします。

結果画面では、JSTLとEL式を使ってStudyPaceの内容を表示します。

ビューを作成する

次に、入力画面と結果画面のJSPを作成します。

SpringプロジェクトでJSPを使う場合、JSPファイルはsrc/main/webapp/WEB-INF/jspに配置します。

application.propertiesに次のような設定をしておくと、Controllerの戻り値とJSPファイルが対応します。

JSPのビュー設定

設定内容
spring.mvc.view.prefix=/WEB-INF/jsp/JSPを探すフォルダ
spring.mvc.view.suffix=.jspJSPファイルの拡張子

たとえば、Controllerがreturn "studyCheck"; を返すと、Springは/WEB-INF/jsp/studyCheck.jspを探します。

Controllerがreturn "studyCheckResult"; を返すと、Springは/WEB-INF/jsp/studyCheckResult.jspを探します。

学習ペース診断の入力画面の例

ファイル名: studyCheck.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学習ペース診断</title>
</head>
<body>
<h1>学習ペース診断</h1>
<p>目標学習時間と実際の学習時間を入力してください。</p>

<form action="StudyCheck" method="post">
<p>
目標学習時間:
<input type="number" name="goalHours" step="0.1"> 分
</p>
<p>
実際の学習時間:
<input type="number" name="actualHours" step="0.1"> 分
</p>
<input type="submit" value="診断する">
</form>
</body>
</html>

studyCheck.jspは、学習ペース診断の入力画面です。

formタグのactionにはStudyCheckを指定します。

methodにはpostを指定します。

これにより、診断するボタンをクリックすると、POST /StudyCheckのリクエストが送信されます。

Controller側では、@PostMapping("/StudyCheck")が付いたexecuteStudyCheckメソッドが実行されます。

inputタグのname属性には、goalHoursとactualHoursを指定しています。

この名前は、Controllerの@RequestParam double goalHours、@RequestParam double actualHoursと一致している必要があります。

step="0.1"を指定しているため、小数を含む値も入力できます。

学習ペース診断の結果画面の例

ファイル名: studyCheckResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>
<%@ taglib uri="jakarta.tags.core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学習ペース診断結果</title>
</head>
<body>
<h1>学習ペース診断結果</h1>

<p>目標学習時間:<c:out value="${studyPace.goalHours}" />分</p>
<p>実際の学習時間:<c:out value="${studyPace.actualHours}" />分</p>
<p>達成率:<c:out value="${studyPace.achievementRate}" />%</p>
<p>判定結果:<c:out value="${studyPace.judgment}" /></p>

<c:if test="${studyPace.judgment == '順調'}">
<p>目標を達成できています。この調子で学習を続けましょう。</p>
</c:if>

<c:if test="${studyPace.judgment == 'やや不足'}">
<p>あと少しで目標に届きます。短い復習時間を追加してみましょう。</p>
</c:if>

<c:if test="${studyPace.judgment == '大きく不足'}">
<p>今日は学習時間が不足しています。無理のない範囲で計画を見直しましょう。</p>
</c:if>

<a href="StudyCheck">入力画面へ戻る</a>
</body>
</html>

studyCheckResult.jspは、学習ペース診断の結果画面です。

JSTLを使うために、taglibディレクティブを記述しています。

Controllerでは、request.setAttribute("studyPace", studyPace)によって、StudyPaceインスタンスをリクエストスコープに保存しました。

そのため、JSPでは${studyPace.goalHours}、${studyPace.actualHours}、${studyPace.achievementRate}、${studyPace.judgment}のようにEL式で値を取得できます。

c:outを使うことで、値を安全に表示できます。

また、c:ifを使って、判定結果に応じた応援メッセージを切り替えています。

判定結果が順調であれば、目標を達成できていることを伝えます。

判定結果がやや不足であれば、あと少しで目標に届くことを伝えます。

判定結果が大きく不足であれば、無理のない範囲で計画を見直すように案内します。

動作確認をする

すべてのクラスとJSPを作成したら、Springアプリケーションを起動します。

Springプロジェクトの開始

「Boot ダッシュボード」ビュー内の「local」を展開し、実行するSpringプロジェクトを右クリックし、「(再)起動」を選択します。
 ※ 「Boot ダッシュボード」ビューを表示するには、「ウィンドウ」→「ビューの表示」内の「Boot ダッシュボード」を選択します。

Springプロジェクトを開始する場合は「spring_study」を選択してください。

Springプロジェクトを起動することで、Springに組み込まれた Apache Tomcat が起動します。
これで、起動した Spring プロジェクト内のコントローラや公開されているリソースに対して、リクエストを送信できるようになります。

Springプロジェクトを起動すると、「コンソール」ビューに、Springの起動メッセージが表示されます。

すでに、Apache Tomcat が起動している場合、次のエラーが表示されます。

この場合は、「Spring ダッシュボード」や「サーバ」ビューで起動中の Tomcat を停止させます。

次に、実行するSpringプロジェクトを右クリックし、「(再)起動」を選択します。

その後、ブラウザのアドレス欄に次のURLを入力します。

http://localhost:8080/StudyCheck

入力画面が表示されたら、目標学習時間と実際の学習時間を入力します。

動作確認の例

入力項目入力値
目標学習時間120
実際の学習時間90

診断するボタンをクリックし、結果画面に次のような内容が表示されれば、基本的な動作は成功です。

表示される結果の例

項目表示例
目標学習時間120.0分
実際の学習時間90.0分
達成率75.0%
判定結果やや不足

目標120分に対して実績90分の場合、90 ÷ 120 × 100で達成率は75.0%になります。

判定ルールでは、70%以上100%未満をやや不足としているため、判定結果はやや不足になります。

Servlet版からSpring版に変わったところ

今回の学習ペース診断アプリは、ServletとJSPで作成したアプリをSpring MVCの形に置き換えたものです。

ビューとしてJSPを使っている点は大きく変わりません。

また、リクエストスコープにStudyPaceを保存し、JSPでEL式とJSTLを使って表示する点も、これまで学習した内容とつながっています。

大きく変わるのは、リクエストを受け取る部分です。

Servletでは、HttpServletを継承したStudyCheckクラスを作り、doGetとdoPostを記述していました。

Springでは、通常のJavaクラスであるStudyCheckControllerを作り、@GetMappingと@PostMappingを使って処理を分けます。

Servlet版とSpring版の違い

項目Servlet版Spring版
リクエスト受付StudyCheckサーブレットStudyCheckController
GET処理doGet@GetMapping("/StudyCheck")
POST処理doPost@PostMapping("/StudyCheck")
パラメータ取得request.getParameter@RequestParam
処理クラスStudyPaceLogicStudyPaceService
処理クラスの利用newでインスタンス作成DIでServiceを注入
フォワードRequestDispatcherreturnでビュー名を返す
結果の保存request.setAttributerequest.setAttribute
結果表示JSP、EL式、JSTLJSP、EL式、JSTL

この表から分かるように、ビューやリクエストスコープの考え方は大きく変わりません。

Springで大きく変わるのは、Controllerの作り方とServiceの利用方法です。

フレームワークを支える標準技術

Springを使うと、ServletやJSPで書いていた処理の一部を、よりシンプルに書けるようになります。

たとえば、doGetやdoPostの代わりに@GetMappingや@PostMappingを使います。

request.getParameterの代わりに@RequestParamを使います。

RequestDispatcherでフォワード先を指定する代わりに、returnでビュー名を返します。

しかし、SpringがServletやJSPとまったく無関係に動いているわけではありません。

Spring MVCの裏側では、DispatcherServletがリクエストを受け取り、Controllerを呼び出しています。

JSPをビューとして使う場合は、最終的にJSPがHTMLを生成してブラウザへ返します。

つまり、Springは標準技術の上に成り立っているフレームワークです。

標準技術を理解しておくメリット

理解している内容Springで役立つ場面
リクエストとレスポンスControllerが何を受け取り、何を返すのか理解しやすい
GETとPOST@GetMappingと@PostMappingの使い分けが分かる
リクエストパラメータ@RequestParamの意味が分かる
リクエストスコープrequest.setAttributeとJSP表示の関係が分かる
JSPとJSTLSpringでもビュー表示を理解しやすい
MVCモデルController、Service、Viewの役割分担が分かる

ServletやJSPを丁寧に学んでおくと、Springの理解も深まります。

エラーが起きたときも、裏側でどのような流れになっているのかを想像しやすくなります。

フレームワークは変わっても基本は残る

Webアプリケーション開発のフレームワークは、時代とともに変化してきました。

かつてはStrutsが多く使われた時期がありました。

その後、日本ではSeasar2が使われた時期もあります。

Javaの標準仕様としてJSFが使われることもありました。

現在では、Spring Frameworkが広く利用されています。

また、Springの中でも技術は変化しています。

ビューでは、以前はJSPがよく使われましたが、現在はThymeleafが使われる場面も多くあります。

データベースアクセスでは、手作りのDAOから、JPAやSpring Data JPAのような仕組みへ進むこともあります。

しかし、どの技術を使う場合でも、リクエスト、レスポンス、MVCモデル、スコープ、DAOパターンの考え方は土台として残ります。

学んだ基本が次の技術につながる例

これまで学んだこと次につながる技術
JSPとJSTLThymeleaf
DAOパターンSpring Data JPA
ServletのコントローラSpring MVCのController
LogicクラスSpringのService
リクエストスコープControllerからViewへのデータ受け渡し

Springを学ぶときも、ServletとJSPで学んだ基礎はとても大切です。

今回の学習ペース診断アプリも、Servlet版の考え方をSpring版へ置き換えたものです。

まずは、小さなアプリをSpringで作り直すところから始めると、Controller、Service、Model、JSPの関係が自然に理解できるようになります。

Spring版学習ペース診断で押さえたいこと

Spring版の学習ペース診断アプリでは、StudyPace、StudyPaceService、StudyCheckController、studyCheck.jsp、studyCheckResult.jspを作成しました。

StudyPaceは、目標学習時間、実際の学習時間、達成率、判定結果を持つデータクラスです。

StudyPaceServiceは、達成率を計算し、判定結果を設定するサービスです。

StudyCheckControllerは、入力画面の表示、POSTリクエストの処理、リクエストスコープへの保存、結果画面へのフォワードを担当します。

studyCheck.jspは、目標学習時間と実際の学習時間を入力する画面です。

studyCheckResult.jspは、リクエストスコープに保存されたstudyPaceをEL式とJSTLで表示する画面です。

Servlet版からSpring版へ変わっても、MVCモデルの考え方は共通しています。

Controllerはリクエストを受け取り、Serviceに処理を依頼し、Modelに結果を保存し、Viewで表示します。

この流れを意識すると、Spring MVCの基本構造を落ち着いて理解できます。

これまで学んだServlet、JSP、リクエストスコープ、MVCモデルの知識を土台にして、SpringでのWebアプリケーション開発に少しずつ慣れていきましょう。