MVCモデルの簡単な例


基本的にスッキリわかる サーブレット&jsp入門 第7章のBMI計算プログラムに準じます。

MVCモデルとは

要素    役割    ファイル
Model アプリケーションの主たる処理やデータの格納などを行う 一般的なクラス
View ユーザーに対して画面の表示を行う       JSPファイル      
Controller ユーザーからの要求を受け取り、処理の実行をモデルに依頼し、その結果の表示をビューに依頼する     サーブレットクラス

javaBeams

インスタンスを保存できる領域の一つ。
以下のルールがある。
1. 直列化可能
2. クラスはpublicでパッケージに所属
3. publicで引数のないコンストラクタを持つ
4. フィールドはカプセル化されている
5. 命名規則に従ったgetter/setterを持つ

サンプルプログラム

コードごとに随時解説を入れます。

Model

アプリケーションの主たる処理やデータの格納などを行う
modelパッケージに保存。

Health.java
package model;

import java.io.Serializable;

public class Health implements Serializable {
  private double height, weight, bmi;
  private String bodyType;

  public double getHeight() {
    return height;
  }

  public void setHeight(Double height) {
    this.height = height;
  }

  public double getWeight() {
    return weight;
  }

  public void setWeight(Double weight) {
    this.weight = weight;
  }

  public void setBmi(Double bmi) {
    this.bmi = bmi;
  }

  public double getBmi() {
    return this.bmi;
  }

  public void setBodyType(String bodyType) {
    this.bodyType = bodyType;
  }

  public String getBodyType() {
    return this.bodyType;
  }
}

このコードがいわゆるJavaBeansである。

HealthCheckLogic.java
package model;

public class HealthCheckLogic {
  public void execute(Health health) {
    // BMIを算出して設定
    double weight = health.getWeight();
    double height = health.getHeight();
    double bmi = weight / (height / 100.0 * height / 100.0);
    health.setBmi(bmi);

    // BMI指数から体格を判定して設定
    String bodyType;
    if (bmi < 18.5) {
      bodyType = "痩せ型";
    } else if (bmi < 25) {
      bodyType = "普通";
    } else {
      bodyType = "肥満";
    }
    health.setBodyType(bodyType);
  }
}

特筆して書くことはなし.

Controller

ユーザーからの要求を受け取り、処理の実行をモデルに依頼し、その結果の表示をビューに依頼する。
servletパッケージに保存。

HealthCheck.java
package servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.Health;
import model.HealthCheckLogic;

@WebServlet("/HealthCheck")
public class HealthCheck extends HttpServlet {
  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request,
      HttpServletResponse response)
      throws ServletException, IOException {

    // フォワード
    RequestDispatcher dispatcher =
        request.getRequestDispatcher
            ("/WEB-INF/jsp/healthCheck.jsp");
    dispatcher.forward(request, response);
  }

  protected void doPost(HttpServletRequest request,
      HttpServletResponse response)
      throws ServletException, IOException {

    // リクエストパラメータを取得
    String weight = request.getParameter("weight"); // 身長
    String height = request.getParameter("height"); // 体重

    // 入力値をプロパティに設定
    Health health = new Health();
    health.setHeight(Double.parseDouble(height));
    health.setWeight(Double.parseDouble(weight));
    // 健康診断を実行し結果を設定
    HealthCheckLogic healthCheckLogic = new HealthCheckLogic();
    healthCheckLogic.execute(health);

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

    // フォワード
    RequestDispatcher dispatcher =
        request.getRequestDispatcher
            ("/WEB-INF/jsp/healthCheckResult.jsp");
    dispatcher.forward(request, response);
  }
}

URLパターン

@WebServlet("/HealthCheck")に記述。

serialVersionUID

private static final long serialVersionUID = 1L;は一種のおまじないのようなものに感じるが違う。
直列化した時、つまりjava.io.Serializableをインポートしたときに必要。
Serializableクラスのバージョンコントロールとして使用される。

リクエストスコープ

リクエストごとに生成されるスコープ。フォワード先とフォワード元でインスタンスを共有することが可能になる。

request.setAttribute("属性名", インスタンス)

属性名にスコープに保存するインスタンスの管理用の名前を指定。
インスタンスに保存するインスタンスを指定

リクエストスコープからインスタンスを取得する場合は以下のように記載。今回はhealthCheckResult.jspでこの処理を行っている。

取得するインスタンスの型 名前 = (取得するインスタンスの型)request.getAttribute("属性名")

キャストが必要な点に注意

フォワード

フォワードを利用することで、処理を他のサーブレットクラスやJSPファイルに移すことが可能。

RequestDispatcher dispatcher =
request.getRequestDispatcher
    ("フォワード先");
dispatcher.forward(request, response);

フォワード先の指定方法
JSPファイル → /WebContentからのパス
サーブレットクラス → /URLパターン

View

ユーザーに対して画面の表示を行う。
ここでは/WebContent/Web-INF/jspに保存。

healthCheck.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>
<form action="/example/HealthCheck" method="post">
身長:<input type="text" name="height">(cm)<br>
体重:<input type="text" name="weight">(kg)<br>
<input type="submit" value="診断">
</form>
</body>
</html>

10行目<form action="/example/HealthCheck" method="post">action属性の指定は以下のようになる。
サーブレットクラスの場合 → /アプリケーション名/URLパターン
JSPファイルの場合 → /アプリケーション名/WebContentからのパス

healthCheckResult.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="model.Health" %>
<%
// リクエストスコープに保存されたHealthを取得
Health health = (Health) request.getAttribute("health");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>スッキリ健康診断</title>
</head>
<body>
<h1>スッキリ健康診断の結果</h1>
<p>
身長:<%= health.getHeight() %><br>
体重:<%= health.getWeight() %><br>
BMI:<%= health.getBmi() %><br>
体格:<%= health.getBodyType() %>
</p>
<a href="/example/HealthCheck">戻る</a>
</body>
</html>

2行目の<%@ page import="model.Health" %>でmodelパッケージのHealth.classを呼び出している。
このコードがjavaBeansの使い方を理解するのに最適かも。

最後に

スッキリわかるサーブレット&JSP入門(国本大悟 著)を参照してください。
また本稿のソースコードの著作権は株式会社フレアリンクに帰属します。
Creative Commons BY-SA 4.0従い利用しています。