JSP開発者のためのServlet基本構造徹底解説

2025-08-04

はじめに:Servletとは何か?

Servletは、JavaでWebアプリケーションを開発するためのサーバーサイドコンポーネントです。JSP(JavaServer Pages)の裏側では、実はServletが重要な役割を果たしています。JSPファイルはコンパイルされるとServletに変換され、実行されます。つまり、JSPを深く理解するためにはServletの知識が不可欠なのです。

本記事では、既にHTTPプロトコルとWebアプリケーションの基本を理解している方を対象に、JSP開発に必要なServletの知識を包括的に解説します。

第1章 Servletの基本構造

1.1 Servletクラスの基本形

すべてのServletはjavax.servlet.http.HttpServletクラスを継承します。以下は最も基本的なServletの構造です:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class BasicServlet extends HttpServlet {

    // 初期化処理
    public void init() throws ServletException {
        // Servletの初期化コード
    }

    // GETリクエスト処理
    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response)
            throws ServletException, IOException {
        // GETリクエストに対する処理
    }

    // POSTリクエスト処理
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response)
            throws ServletException, IOException {
        // POSTリクエストに対する処理
    }

    // 終了処理
    public void destroy() {
        // リソースの解放など
    }
}

1.2 Servletのライフサイクル

Servletには明確なライフサイクルが存在します:

  1. 初期化(init) – ServletコンテナによってServletがロードされ、init()メソッドが1回だけ呼び出される
  2. リクエスト処理(service) – クライアントからのリクエストに応じてdoGet()doPost()が呼び出される
  3. 終了(destroy) – Servletがアンロードされる際にdestroy()メソッドが呼び出される

1.3 主要なメソッドの役割

メソッド名説明呼び出しタイミング
init()Servletの初期化Servletが最初にロードされるときに1回だけ
doGet()GETリクエスト処理HTTP GETリクエストを受信したとき
doPost()POSTリクエスト処理HTTP POSTリクエストを受信したとき
service()全リクエストの処理全てのHTTPリクエスト(通常はオーバーライドしない)
destroy()終了処理Servletがアンロードされるとき

第2章 ServletとJSPの連携

2.1 JSPからServletを呼び出す

JSPページからServletを呼び出す主な方法:

<!-- フォームを使用する場合 -->
<form action="MyServlet" method="post">
    <input type="text" name="username">
    <input type="submit" value="送信">
</form>

<!-- リンクを使用する場合 -->
<a href="MyServlet?param=value">Servletを呼び出す</a>

2.2 ServletからJSPへデータを渡す(フォワード)

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

    // データをリクエスト属性に設定
    request.setAttribute("message", "Hello from Servlet!");

    // JSPにフォワード
    RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
    dispatcher.forward(request, response);
}

2.3 ServletからJSPへリダイレクト

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

    // 何らかの処理

    // リダイレクト(URLが変わる)
    response.sendRedirect("result.jsp");
}

第3章 実践的なServlet開発

3.1 アノテーションを使用したServlet登録

Servlet 3.0以降では、web.xmlではなくアノテーションでServletを登録できます:

@WebServlet(
    name = "MyServlet",
    urlPatterns = {"/myServlet", "/myServlet/*"},
    initParams = {
        @WebInitParam(name = "admin", value = "admin@example.com")
    }
)
public class MyServlet extends HttpServlet {
    // ...
}

3.2 フィルタの作成と活用

フィルタはServletの前処理・後処理を行うコンポーネントです:

@WebFilter("/*")
public class LoggingFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
        // 初期化処理
    }

    public void doFilter(ServletRequest request, 
                         ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException {

        // 前処理
        System.out.println("リクエストを受信: " + 
                          ((HttpServletRequest)request).getRequestURI());

        // 次のフィルタまたはServletへ
        chain.doFilter(request, response);

        // 後処理
        System.out.println("レスポンスを送信");
    }

    public void destroy() {
        // 終了処理
    }
}

3.3 リスナーの活用

Webアプリケーションのライフサイクルイベントを監視:

@WebListener
public class AppListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("アプリケーションが起動しました");
    }

    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("アプリケーションが終了します");
    }
}

第4章 ServletとJSPの連携パターン

4.1 MVCパターンの実装

Servletをコントローラとして使用する典型的なMVCパターン:

リクエスト → コントローラ(Servlet) → モデル(Javaクラス) → ビュー(JSP) → レスポンス

コントローラ(Servlet)の例:

@WebServlet("/user")
public class UserController extends HttpServlet {

    private UserService userService = new UserService();

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

        String action = request.getParameter("action");

        if ("list".equals(action)) {
            List users = userService.getAllUsers();
            request.setAttribute("users", users);
            request.getRequestDispatcher("/userList.jsp").forward(request, response);
        } else if ("detail".equals(action)) {
            int id = Integer.parseInt(request.getParameter("id"));
            User user = userService.getUserById(id);
            request.setAttribute("user", user);
            request.getRequestDispatcher("/userDetail.jsp").forward(request, response);
        }
    }
}

ビュー(JSP)の例 (userList.jsp):

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

4.2 データベース連携の実装

Servletでデータベースに接続する例:

@WebServlet("/products")
public class ProductServlet extends HttpServlet {

    private DataSource dataSource;

    public void init() throws ServletException {
        try {
            // JNDIでデータソースを取得
            Context ctx = new InitialContext();
            dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/MyDB");
        } catch (NamingException e) {
            throw new ServletException("データソースが見つかりません", e);
        }
    }

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

        List products = new ArrayList<>();

        try (Connection conn = dataSource.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM products")) {

            while (rs.next()) {
                Product p = new Product();
                p.setId(rs.getInt("id"));
                p.setName(rs.getString("name"));
                p.setPrice(rs.getBigDecimal("price"));
                products.add(p);
            }

            request.setAttribute("products", products);
            request.getRequestDispatcher("/productList.jsp").forward(request, response);

        } catch (SQLException e) {
            throw new ServletException("データベースエラー", e);
        }
    }
}

第5章 高度なServletテクニック

5.1 非同期処理の実装

Servlet 3.0以降でサポートされた非同期処理:

@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {

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

        AsyncContext asyncContext = request.startAsync();
        asyncContext.setTimeout(30000); // 30秒

        // 別スレッドで長時間処理を実行
        asyncContext.start(() -> {
            try {
                // 時間のかかる処理
                Thread.sleep(5000);

                // 結果を設定
                asyncContext.getRequest().setAttribute("result", "処理完了");

                // JSPにフォワード
                asyncContext.dispatch("/result.jsp");
            } catch (Exception e) {
                asyncContext.complete();
            }
        });
    }
}

5.2 ファイルアップロードの処理

Servletでのファイルアップロード処理:

@WebServlet("/upload")
@MultipartConfig(
    fileSizeThreshold = 1024 * 1024,    // 1MB
    maxFileSize = 1024 * 1024 * 5,     // 5MB
    maxRequestSize = 1024 * 1024 * 10  // 10MB
)
public class FileUploadServlet extends HttpServlet {

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

        // 通常のフォームフィールド
        String description = request.getParameter("description");

        // ファイルパート処理
        Part filePart = request.getPart("file");
        String fileName = Paths.get(
                           filePart.getSubmittedFileName()
                          ).getFileName().toString();

        // ファイル保存
        InputStream fileContent = filePart.getInputStream();
        Files.copy(fileContent, Paths.get("/uploads", fileName));

        response.getWriter().print("アップロード成功: " + fileName);
    }
}

5.3 セッション管理の詳細

Servletでのセッション管理:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

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

        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (authenticate(username, password)) {
            // セッションを取得(存在しなければ新規作成)
            HttpSession session = request.getSession();

            // セッションタイムアウト設定(秒単位)
            session.setMaxInactiveInterval(30 * 60); // 30分

            // セッション属性設定
            session.setAttribute("user", username);
            session.setAttribute("loginTime", new Date());

            // ログイン成功後のページへリダイレクト
            response.sendRedirect("welcome.jsp");
        } else {
            // ログイン失敗
            request.setAttribute("error", "無効なユーザー名またはパスワード");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }

    private boolean authenticate(String username, String password) {
        // 実際の認証ロジック
        return true;
    }
}

第6章 Servletの設定とデプロイ

6.1 web.xmlの設定

従来のweb.xmlを使用したServlet設定:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.example.MyServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>value</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/myServlet</url-pattern>
        <url-pattern>/myServlet/*</url-pattern>
    </servlet-mapping>
    
    <session-config>
        <session-timeout>30</session-timeout> <!-- 分単位 -->
    </session-config>
    
    <error-page>
        <error-code>404</error-code>
        <location>/error/404.jsp</location>
    </error-page>
</web-app>

6.2 初期化パラメータの取得

Servletで初期化パラメータを取得する方法:

public class ConfigServlet extends HttpServlet {

    private String configValue;

    public void init() throws ServletException {
        // web.xmlまたは@WebInitParamから初期化パラメータを取得
        configValue = getServletConfig().getInitParameter("config");
    }

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

        response.getWriter().println("Config Value: " + configValue);
    }
}

まとめ:ServletとJSPの関係を再確認

ServletはJSPの基盤技術であり、JSPページは最終的にServletに変換されて実行されます。この関係を理解することで、より効果的なJSP開発が可能になります。

  • JSPはプレゼンテーション層に特化 – HTML生成に適している
  • Servletはコントローラ層に適している – ビジネスロジックやフロー制御
  • 組み合わせて使用することで、保守性の高いアプリケーションを構築可能

Servletの知識はJSP開発の基盤となります。本記事で学んだ内容を活かして、より高度なWebアプリケーション開発に挑戦してください。