JSPとServletを使った「データ登録処理」は、一見シンプルに見えるが、
内部では複数のステップが連携しています。
本記事では、実際のコードをベースに「何がどの順番で起きているのか」を整理します。
■全体の流れ
①JSPでform送信(POST)
②TomcatがServletへ ルーティング
③Servlet(doPost)でデータ取得・加工・DB登録
①JSP:form送信
<form id="newBook" action="<%=request.getContextPath()%>/addBook2" method="post" enctype="multipart/form-data">
ポイント
・request.getContextPath()
プロジェクトのルート(例:/BookMarket)を自動付与
・method="post"
データをサーバへ送信
・enctype="multipart/form-data"
ファイルアップロード時に必須
②Tomcatのルーティング
@WebServlet("/addBook2")
リクエスト:
/BookMarket/addBook2
↓
Tomcat内部で:
/addBook2 → UploadServlet
にマッピングされる
③Servlet:doPost処理
protected void doPost(HttpServletRequest request, HttpServletResponse response)
③-1 パラメータ取得
String name = request.getParameter("name");
③-2 数値変換
Integer price = Integer.parseInt(unitPrice);
文字列を数値に変換
③-3 ファイルアップロード処理
Part imagePart = request.getPart("BookImage");
流れ
1.ファイル名取得
2.保存先ディレクトリ作成
3.サーバに保存
Files.copy(in, filePath, StandardCopyOption.REPLACE_EXISTING);
※multipart/form-dataがないとここで失敗
③-4 DB登録
String sql = "INSERT INTO book (...) VALUES (?, ?, ...)";
pstmt.executeUpdate();
戻りが1であれば成功
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
<script type="text/javascript" src="./resources/js/validation.js"></script>
<title>ブック登録</title>
</head>
<body>
<fmt:requestEncoding value="UTF-8"/>
<fmt:setLocale value="${param.language}" />
<fmt:setBundle basename="bundle.message" />
<div class="container py-4">
<%@ include file="menu.jsp" %>
<div class="p-5 mb-4 bg-body-tertiary rounded-3">
<div class="container-fluid py-5">
<h1 class="display-5 fw-bold"><fmt:message key="title" /></h1>
<p class="col-md-8 fs-4">Book Addition</p>
</div>
</div>
<div class="row align-items-md-stretch">
<form id="newBook" action="<%=request.getContextPath()%>/addBook2" method="post" enctype="multipart/form-data" onsubmit="return true">
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="bookId" /></label>
<div class="col-sm-3">
<input type="text" id="bookId" name="bookId" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="name" /></label>
<div class="col-sm-3">
<input type="text" id="name" name="name" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="unitPrice" /></label>
<div class="col-sm-3">
<input type="number" id="unitPrice" name="unitPrice" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="author" /></label>
<div class="col-sm-3">
<input type="text" name="author" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="publisher" /></label>
<div class="col-sm-3">
<input type="text" name="publisher" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="releaseDate" /></label>
<div class="col-sm-3">
<input type="date" name="releaseDate" class="form-control" placeholder="YYYY-MM-DD" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="description" /></label>
<div class="col-sm-3">
<textarea name="description" id="description" rows="2" cols="50"
class="form-control" placeholder="100字以上記入してください" required></textarea>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="category" /></label>
<div class="col-sm-3">
<input type="text" name="category" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="unitsInStock" /></label>
<div class="col-sm-3">
<input type="number" id="unitsInStock" name="unitsInStock" class="form-control" required>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="condition" /></label>
<div class="col-sm-3">
<input type="radio" name="condition" value="New" checked><fmt:message key="condition_New" />
<input type="radio" name="condition" value="Old"><fmt:message key="condition_Old" />
<input type="radio" name="condition" value="Ebook"><fmt:message key="condition_Ebook" />
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2"><fmt:message key="bookImage" /></label>
<div class="col-sm-5">
<input type="file" name="BookImage" class="form-control">
</div>
</div>
<div class="mb-3 row">
<div class="col-sm-10 offset-sm-2">
<input type="submit" value="登録">
<input type="reset" class="btn btn-primary" value="reset">
</div>
</div>
</form>
</div>
</div>
</body>
</html>
package ch04.com.dao;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import dao.BookRepository;
import dto.Book;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
@WebServlet("/addBook2")
@MultipartConfig(
maxFileSize = 5 * 1024 * 1024
)
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().println("SERVLET OK");
System.out.println("UploadServlet入り成功");
request.setCharacterEncoding("UTF-8");
String bookId = request.getParameter("bookId");
String name = request.getParameter("name");
String unitPrice = request.getParameter("unitPrice");
String author = request.getParameter("author");
String publisher = request.getParameter("publisher");
String releaseDate = request.getParameter("releaseDate");
String description = request.getParameter("description");
String category = request.getParameter("category");
String unitsInStock = request.getParameter("unitsInStock");
String condition = request.getParameter("condition");
System.out.println("request成功");
Integer price;
try {
price = Integer.parseInt(unitPrice);
} catch (NumberFormatException e) {
price = 0;
}
long stock;
try {
stock = Long.parseLong(unitsInStock);
}catch (NumberFormatException e){
stock = 0;
}
Part imagePart = request.getPart("BookImage");
String fileName = "noimage.png";
System.out.println("=== START ===");
System.out.println("bookId=" + bookId);
System.out.println("name=" + name);
System.out.println("price=" + price);
if (imagePart != null && imagePart.getSize() > 0) {
fileName = Paths.get(imagePart.getSubmittedFileName())
.getFileName().toString();
String uploadPath = getServletContext().getRealPath("/resources/images");
Path uploadDir = Paths.get(uploadPath);
Files.createDirectories(uploadDir);
Path filePath = uploadDir.resolve(fileName);
try (InputStream in = imagePart.getInputStream()) {
Files.copy(in, filePath, StandardCopyOption.REPLACE_EXISTING);
}
}
System.out.println("connection前");
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtil.getConnection();
String sql = "INSERT INTO book (b_id, b_name, b_unitPrice, b_author, b_publisher, b_releaseDate, b_description, b_category, b_unitsInStock, b_condition, b_filename) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
System.out.println("connection中");
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, bookId);
pstmt.setString(2, name);
pstmt.setInt(3, price);
pstmt.setString(4, author);
pstmt.setString(5, publisher);
pstmt.setString(6, releaseDate);
pstmt.setString(7, description);
pstmt.setString(8, category);
pstmt.setLong(9, stock);
pstmt.setString(10, condition);
pstmt.setString(11, fileName);
int result = pstmt.executeUpdate();
System.out.println("INSERT結果: " + result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (pstmt != null) try { pstmt.close(); } catch(Exception e) {}
if (conn != null) try { conn.close(); } catch(Exception e ) {}
}
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%
Connection conn = null;
// ① 接続情報
String url = "jdbc:mysql://localhost:3306/bookmarket?serverTimezone=UTC";
String db_id = "system2";
String db_pw = "system1234";
try {
// ② ドライバ(MySQL)
Class.forName("com.mysql.cj.jdbc.Driver");
// ③ 接続
conn = DriverManager.getConnection(url, db_id, db_pw);
// out.println("<h3 style='color:blue'>接続成功(MySQL)</h3>");
} catch(Exception e) {
e.printStackTrace();
out.println("<h3 style='color:red'>接続失敗</h3>");
out.println("<p>" + e.getMessage() + "</p>");
}
%>