JSP学習者向け:MVCアーキテクチャの理解と実践

2025-08-05

はじめに

Servlet、JSP、JDBCを学んだ皆さんは、次にこれらの技術をどのように組み合わせて効果的なWebアプリケーションを構築するかについて考える時期に来ています。この記事では、MVCアーキテクチャという重要な設計パターンを解説し、学んだ技術をどのように統合すれば良いかを具体的に説明します。

MVCアーキテクチャとは

MVC(Model-View-Controller)は、アプリケーションを3つの主要なコンポーネントに分離する設計パターンです。

  • Model(モデル): データとビジネスロジックを担当
  • View(ビュー): ユーザーインターフェース(表示)を担当
  • Controller(コントローラ): ユーザーからの入力を受け取り、モデルとビューを制御

この分離により、コードの保守性、拡張性、テスト容易性が向上します。

JSP/Servlet環境でのMVC実装

Java Webアプリケーションでは、以下のように各コンポーネントを割り当てます。

MVCコンポーネントJava Web技術
ModelJavaBeans, JDBC, DAOクラス
ViewJSPページ
ControllerServlet

具体的なデータフロー

  1. ユーザーがブラウザからリクエストを送信
  2. Servlet(Controller)がリクエストを受信
  3. ServletがJavaBeans/DAO(Model)を呼び出してデータ処理
  4. Modelがデータベース(JDBC)とやり取り
  5. Servletが処理結果をJSP(View)に転送
  6. JSPがHTMLを生成してユーザーに返却

実践例:ユーザー管理システム

具体的なコード例でMVCを理解しましょう。ユーザー一覧を表示する機能を作成します。

1. Modelの実装 (User.java)

public class User {
    private int id;
    private String name;
    private String email;

    // コンストラクタ、ゲッター、セッター
    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // getterとsetterメソッド
    public int getId() { return id; }
    public String getName() { return name; }
    public String getEmail() { return email; }
    // その他のsetterメソッド...
}

2. DAOクラス (UserDAO.java) – Modelの一部

public class UserDAO {
    private Connection connection;

    public UserDAO() {
        // データベース接続初期化
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydb", "user", "password");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List getAllUsers() {
        List users = new ArrayList<>();
        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM users");

            while (rs.next()) {
                users.add(new User(
                    rs.getInt("id"),
                    rs.getString("name"),
                    rs.getString("email")
                ));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return users;
    }
}

3. Controllerの実装 (UserServlet.java)

@WebServlet("/users")
public class UserServlet extends HttpServlet {
    private UserDAO userDao;

    @Override
    public void init() {
        userDao = new UserDAO();
    }

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

        // Modelからデータ取得
        List users = userDao.getAllUsers();

        // Viewにデータを渡す
        request.setAttribute("userList", users);

        // Viewに転送
        RequestDispatcher dispatcher = request.getRequestDispatcher("/userList.jsp");
        dispatcher.forward(request, response);
    }
}

4. Viewの実装 (userList.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <title>ユーザー一覧</title>
</head>
<body>
    <h1>ユーザー一覧</h1>
    <table border="1">
        <tr>
            <th>ID</th>
            <th>名前</th>
            <th>メール</th>
        </tr>
        <c:forEach var="user" items="${userList}">
            <tr>
                <td>${user.id}</td>
                <td>${user.name}</td>
                <td>${user.email}</td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

MVCのメリット

この構造には多くの利点があります。

  1. 関心の分離: 各コンポーネントが単一の責任を持つ
  2. 保守性の向上: 変更が局所的になる
  • デザイン変更 → Viewのみ修正
  • ビジネスロジック変更 → Modelのみ修正
  • ナビゲーション変更 → Controllerのみ修正
  1. 再利用性: 同じModelを異なるViewで利用可能
  2. テスト容易性: 各コンポーネントを個別にテスト可能

よくある間違いとベストプラクティス

避けるべきアンチパターン

  1. JSPにビジネスロジックを書く
   <%-- 悪い例 --%>
   <%
     Connection conn = DriverManager.getConnection(...);
     Statement stmt = conn.createStatement();
     ResultSet rs = stmt.executeQuery("SELECT * FROM users");
     while (rs.next()) {
   %>
       <%= rs.getString("name") %>
   <%
     }
     conn.close();
   %>
  1. Servletに表示ロジックを書く
   // 悪い例
   PrintWriter out = response.getWriter();
   out.println("");
   out.println("

ユーザー一覧

"); // ...

推奨されるプラクティス

  1. JSTLとEL式の使用: JSPでのスクリプトレットを避ける
  2. 適切なスコープの選択:
  • リクエストスコープ: 1回のリクエストで使用
  • セッションスコープ: ユーザーセッション中に保持
  • アプリケーションスコープ: 全ユーザーで共有
  1. フロントコントローラーパターン: 全リクエストを1つのServletで受けて適切なハンドラに振り分ける

発展的なトピック

フレームワークの利用

MVCをより簡単に実装できるフレームワークがあります。

  1. Spring MVC: アノテーションベースの設定
   @Controller
   public class UserController {
       @Autowired
       private UserService userService;

       @GetMapping("/users")
       public String listUsers(Model model) {
           model.addAttribute("users", userService.getAllUsers());
           return "userList";
       }
   }
  1. Jakarta EE (旧Java EE)のMVC: JAX-RSベースの実装

RESTful APIとの統合

現代のWebアプリケーションでは、フロントエンド(React/Vueなど)とバックエンドを分離し、JSONでデータをやり取りする構成が一般的です。

@WebServlet("/api/users")
public class UserApiServlet extends HttpServlet {
    private UserDAO userDao = new UserDAO();
    private Gson gson = new Gson();

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

        response.setContentType("application/json");
        List users = userDao.getAllUsers();
        response.getWriter().print(gson.toJson(users));
    }
}

まとめ

MVCアーキテクチャは、Servlet、JSP、JDBCで学んだ技術を効果的に組み合わせるための設計パターンです。各コンポーネントの役割を明確に分離することで、以下のようなメリットが得られます。

  1. コードの見通しが良くなり、開発効率が向上
  2. 変更に強く、保守性が高いアプリケーションを構築可能
  3. チーム開発での役割分担が明確になる
  4. 将来的な拡張やフレームワーク導入が容易

最初は少し複雑に感じるかもしれませんが、実際に小さなプロジェクトで実践してみると、その価値が実感できるでしょう。まずはユーザー管理や商品管理などの簡単なCRUDアプリケーションから始めて、MVCの理解を深めてください。