JSP学習者向け:モデル1 vs モデル2アーキテクチャの徹底比較

2025-08-05

はじめに

前回の記事でMVCアーキテクチャについて学んだ皆さんは、Java Web開発における「モデル1」と「モデル2」という用語を耳にしたことがあるでしょう。この記事では、この2つのアプローチを詳細に比較し、それぞれの特徴、利点、欠点、そして適切な使用場面について解説します。

モデル1とモデル2の基本概念

モデル1アーキテクチャ

jsp-model1

モデル1は、JSPを中心としたシンプルなアーキテクチャです。主な特徴は:

  • JSPがリクエスト処理と表示の両方を担当
  • ビジネスロジックがJSP内に直接記述されるか、JavaBeansを利用
  • 小規模なアプリケーションに適している
  • 開発が簡単で習得しやすい

モデル2アーキテクチャ

jsp-model2

モデル2は、MVCパターンに基づいたより構造化されたアーキテクチャです。主な特徴は:

  • ServletがControllerとして機能
  • JSPはView専用として使用
  • 明確な役割分担(MVCの分離)
  • 中~大規模アプリケーションに適している
  • 保守性と拡張性が高い

コード比較:ユーザー登録機能

モデル1での実装例 (register.jsp)

<%@ page import="java.sql.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    // ビジネスロジックがJSP内に直接記述(アンチパターン)
    if ("POST".equals(request.getMethod())) {
        String name = request.getParameter("name");
        String email = request.getParameter("email");
        String password = request.getParameter("password");

        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password");

            String sql = "INSERT INTO users (name, email, password) VALUES (?, ?, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, name);
            pstmt.setString(2, email);
            pstmt.setString(3, password);

            int result = pstmt.executeUpdate();

            if (result > 0) {
                out.println("

登録成功しました

"); } else { out.println("

登録に失敗しました

"); } } catch (Exception e) { e.printStackTrace(); out.println("

エラーが発生しました: " + e.getMessage() + "

"); } finally { if (pstmt != null) pstmt.close(); if (conn != null) conn.close(); } } %>
<!DOCTYPE html>
<html>
<head>
    <title>ユーザー登録</title>
</head>
<body>
    <h1>ユーザー登録</h1>
    <form method="post">
       名前: <input type="text" name="name"><br>
       メール: <input type="email" name="email"><br>
       パスワード: <input type="password" name="password"><br>
       <button type="submit">登録</button>
    </form>
</body>
</html>

モデル2での実装例

1. Controller (RegisterServlet.java)

@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    private UserService userService = new UserService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/register.jsp").forward(request, response);
    }

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

        String name = request.getParameter("name");
        String email = request.getParameter("email");
        String password = request.getParameter("password");

        try {
            boolean success = userService.registerUser(name, email, password);

            if (success) {
                request.setAttribute("message", "登録成功しました");
            } else {
                request.setAttribute("error", "登録に失敗しました");
            }
        } catch (Exception e) {
            request.setAttribute("error", "エラーが発生しました: " + e.getMessage());
        }

        request.getRequestDispatcher("/register.jsp").forward(request, response);
    }
}

2. Model (UserService.java)

public class UserService {
    private UserDAO userDao = new UserDAO();

    public boolean registerUser(String name, String email, String password) 
            throws SQLException {
        // バリデーションなどのビジネスロジック
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("名前は必須です");
        }

        // パスワードの複雑性チェックなど...

        return userDao.insertUser(new User(name, email, password));
    }
}

3. View (register.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <title>ユーザー登録</title>
</head>
<body>
    <h1>ユーザー登録</h1>

    <%-- メッセージ表示 --%>
    <c:if test="${not empty message}">
        <p style="color:green">${message}</p>
    </c:if>
    <c:if test="${not empty error}">
        <p style="color:red">${error}</p>
    </c:if>

    <form method="post">
       名前: <input type="text" name="name"><br>
       メール: <input type="email" name="email"><br>
       パスワード: <input type="password" name="password"><br>
       <button type="submit">登録</button>
    </form>
</body>
</html>

比較表:モデル1 vs モデル2

項目モデル1モデル2
構造JSP中心MVCパターン
役割分担不明確(JSPがすべて処理)明確(Model-View-Controller)
開発速度速い(初期段階)やや遅い(設計が必要)
保守性低い(コードが散らばる)高い(責務が分離)
拡張性低い(大規模化に不向き)高い(大規模対応可)
テスト容易性困難(ロジックがJSP内)容易(各層を個別にテスト可能)
適応規模小規模・プロトタイプ中~大規模・本番システム
チーム開発不向き(競合が発生)適している(役割分担可能)
技術的負債蓄積しやすい蓄積しにくい

移行のベストプラクティス:モデル1からモデル2へ

既存のモデル1アプリケーションをモデル2にリファクタリングする場合の手順:

  1. ビジネスロジックの抽出
  • JSP内のJavaコードを特定
  • 該当コードをJavaBeansやサービスクラスに移動
  1. Controllerの導入
  • リクエスト処理用のServletを作成
  • JSPは表示専用に変更
  1. データアクセス層の分離
  • DAOパターンを導入
  • データベース操作を専用クラスに移動
  1. フロントコントローラーの導入(オプション)
  • 全リクエストを処理する中央Servletを配置
  • リクエストルーティングを一元管理

リファクタリング例

Before (モデル1):

<%-- JSP内に直接データベース操作 --%>
<%
String id = request.getParameter("id");
Connection conn = ...;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM products WHERE id=" + id);
// ...
%>

After (モデル2):

// Controller
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
    private ProductService productService = new ProductService();

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

        String id = request.getParameter("id");
        Product product = productService.getProductById(id);
        request.setAttribute("product", product);
        request.getRequestDispatcher("/productDetail.jsp").forward(request, response);
    }
}
<%-- JSPは表示のみ --%>
<p>商品名: ${product.name}</p>
<p>価格: ${product.price}円</p>

現代的な視点:モデル1の位置付け

モデル2が主流となった現在でも、モデル1には以下のような用途があります:

  1. プロトタイピング
  • コンセプト検証のための迅速な開発
  1. 小規模な管理画面
  • 社内用ツールなど限定的な利用
  1. 学習用途
  • JSPの基本を理解するためのステップ

しかし、以下の点に注意が必要です:

  • セキュリティリスク(SQLインジェクションなど)
  • 長期メンテナンスの困難さ
  • 技術的負債の蓄積

結論:どちらを選ぶべきか

プロジェクトの要件に基づいて適切なアーキテクチャを選択してください。

モデル1が適している場合:

  • 1~2週間で完了するような短期プロジェクト
  • 1人で開発する個人プロジェクト
  • 学習目的やデモ用アプリケーション

モデル2が必須な場合:

  • 企業向けの本番システム
  • 長期にわたってメンテナンスされるプロジェクト
  • 複数人で開発するチームプロジェクト
  • 将来的な機能拡張が予想される場合

Java Web開発のベストプラクティスとしては、モデル2(MVC)アーキテクチャを採用することが強く推奨されます。特に、Spring Frameworkなどの現代的なフレームワークはすべてMVCパターンに基づいて設計されているため、モデル2を理解することはプロフェッショナルなJava開発者になるための重要なステップです。

次のステップ

モデル2の理解を深めたら、以下のトピックに進むことをお勧めします:

  1. Front Controllerパターン – 複数のServletを統合的に管理
  2. Spring MVCフレームワーク – より高度なMVC実装
  3. DAOとRepositoryパターン – データアクセス層の設計
  4. 依存性注入(DI) – コンポーネント間の結合度低減

MVCアーキテクチャの完全な理解は、現代のJava Web開発における成功への鍵です。小さなプロジェクトから始めて、徐々に複雑なアプリケーションへとスキルを拡張していきましょう。