0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spring入門

Last updated at Posted at 2025-01-04

Spring フレームワークの自己学習メモです。Udemy、サーチマンさんの「ゼロから環境構築,文法,JSP,レイヤー,依存性,DB接続,Webアプリを一気に学ぶ」の講座をなぞっています。

開発環境

  • Mac mini (Apple M1 2020) 16GB メモリー
  • macOS Sequoia 15.0.1

Pleiades All in One Eclipse のインストール

リリース2024 Standard Edition を選択しました。

  • pleiades-2024-09-java-mac_20240917.dmg

Java バージョンを切り替えたい

現在のバージョン

% javac -version
javac 23.0.1
% java -version
openjdk version "23.0.1" 2024-10-15
OpenJDK Runtime Environment (build 23.0.1+11-39)
OpenJDK 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)
%

$JAVA_HOME を確認しておきます。

% echo $JAVA_HOME
/Users/m/Dev/openjdk/jdk-23.0.1.jdk/Contents/Home
%

このバージョンでいいので、このまま進めます。

もしバージョンを切り替えるのは、こんな感じかと

インストール済みの Java を確認

% /usr/libexec/java_home -V
Matching Java Virtual Machines (1):
    17.0.4.1 (arm64) "Eclipse Adoptium" - "OpenJDK 17.0.4.1" /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
%

切り替えと確認

% export JAVA_HOME="/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home"
% PATH=$JAVA_HOME/bin:$PATH
% source ~/.zshrc
%
% javac -version
javac 17.0.4.1
%
% java -version
openjdk version "17.0.4.1" 2022-08-12
OpenJDK Runtime Environment Temurin-17.0.4.1+1 (build 17.0.4.1+1)
OpenJDK 64-Bit Server VM Temurin-17.0.4.1+1 (build 17.0.4.1+1, mixed mode)
%

DB

MySQL

インストール

% brew install mysql
% which mysql
/opt/homebrew/bin/mysql
%

起動

% mysql.server start
Starting MySQL
.. SUCCESS!
%

初期設定

% mysql_secure_installation

停止

% mysql.server stop
Shutting down MySQL
. SUCCESS!
%

ログイン

% mysql -u root -p
Enter password:

(snip)

mysql>

アンインストール

% mysql.server stop
Shutting down MySQL
. SUCCESS!
% brew uninstall mysql

DB作成

  • create database (DB名) default character set utf8mb4 collate utf8mb4_general_ci;
mysql> create database user default character set utf8mb4 collate utf8mb4_general_ci;
Query OK, 1 row affected (0.00 sec)

mysql>

DB一覧

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| user               |
+--------------------+
5 rows in set (0.00 sec)

mysql>

DB切替

mysql> use user;
Database changed
mysql>

create table

mysql> create table user (
    -> id int  NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> name varchar(255),
    -> email varchar(255));
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql> alter table user add constraint user_u1 unique (email);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql>

テーブル一覧

mysql> show tables;
+----------------+
| Tables_in_user |
+----------------+
| user           |
+----------------+
1 row in set (0.01 sec)

mysql>

データ投入

mysql> insert into user (name, email) values ('ishi32', 'ishi32@example.com');
Query OK, 1 row affected (0.01 sec)

mysql> select * from user;
+----+--------+--------------------+
| id | name   | email              |
+----+--------+--------------------+
|  1 | ishi32 | ishi32@example.com |
+----+--------+--------------------+
1 row in set (0.00 sec)

mysql>

Spring プロジェクト作成

  • 「プロジェクト・エクスプローラ」で右クリック
  • [新規] -> [その他] -> [Spring Boot] -> [Spring スターター・プロジェクト (Spring Initializer)] -> [次へ]
    • 名前: app1
    • タイプ: Maven
    • グループ: com.bkiban
    • 説明: User manage
    • パッケージ: com.bkiban.app1
  • [次へ] -> (デフォルトで)[次へ] -> (デフォルトで)[完了]

pom.xml

に以下を追加

	<dependencies>
 (snip)
		<!-- Spring Boot Starter Tomcat -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>

		<!-- JSP support -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<!-- Spring Boot JDBC -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<!-- MySQL connector -->
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>

  		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.9</version>
		</dependency>

	</dependencies>

src/main/resources/application.properties

以下を追加

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/user
spring.datasource.username=root
spring.datasource.password=********

spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp

jsp の格納場所を作成

  • src/main で右クリック
  • [新規] -> [フォルダ]
  • 「フォルダ名」に webapp
  • [完了]
  • src/main/webapp で右クリック
  • [新規] -> [フォルダ]
  • 「フォルダ名」に WEB-INF
  • [完了]

各レイアを作成

  • controller
    • src/main/java/com/bkiban/app1 で右クリック
    • [新規] -> [フォルダ]
    • 「フォルダ名」に
    • [完了]
    • src/main/webapp で右クリック
    • [新規] -> [フォルダ]
    • 「フォルダ名」に controller
    • [完了]
  • entity
  • repository
  • service

Spring の各レイヤー (パッケージ) の役割

  • Controller (HTTPの処理)
    ブラウザからの HTTP リクエストを受け取り、必要の応じて Service を呼び出し、その処理結果がある場合は View (JSP や HTML) へ返却する。
  • Service (ビジネスロジック)
  • Repository (DBアクセス)
  • Entity (DBのテーブルに対応)
    テーブルごとに、各項目の定義と Getter、Setter をオブジェクトとして定義する。

entity

  • src/main/java/com/bkiban/app1/entity で右クリック
  • [新規] -> [その他] -> [Java] -> [クラス]
    • 名前: User
  • [完了]
package com.bkiban.app1.entity;

public class User {

	private int id;
	private String name;
	private String email;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}

repository (インターフェース)

インターフェースには、設計で必要とされるメソッドを全て「抽象メソッド」として定義しておく。こうすることで実装をあらかじめ担保しておく。

  • src/main/java/com/bkiban/app1/repository で右クリック
  • [新規] -> [その他] -> [Java] -> [インターフェース]
  • [次へ]
    • 「名前」: UserRepository
    • [完了]
package com.bkiban.app1.repository;

import java.util.List;

import com.bkiban.app1.entity.User;

public interface UserRepository {

	//ユーザリストを取得
	List<User> findAll();

	//idによるユーザ取得
	User findById(int id);

	//ユーザ挿入
	void insertUser(User user);

	//ユーザ更新
	void updateUser(User user);

	//ユーザ削除
	void deleteUser(int id);

}

ArrayList<User>User がエラーになっていたら、import が足りていないので User にマウスをあてて、「User をインポートします (com.bkiban.app1.entity)」をクリックする

service (インターフェース)

  • src/main/java/com/bkiban/app1/service で右クリック
  • [新規] -> [その他] -> [Java] -> [インターフェース]
  • [次へ]
    • 「名前」: UserService
    • [完了]
  • コードは UserRepository.java とほぼ同じ
package com.bkiban.app1.service;

import java.util.List;

import com.bkiban.app1.entity.User;

public interface UserService {

	//全ユーザを取得
	List<User> findAll();

	//リクエストからユーザオブジェクトを作成
	User makeUser(User request);

	//ユーザ挿入
	void insertUser(User user);

	//idによるユーザ取得
	User findById(int id);

	//ユーザ更新
	void updateUser(User user);

	//ユーザ削除
	void deleteUser(int id);
	
}

repository (実装)

  • src/main/java/com/bkiban/app1/repository で右クリック
  • [新規] -> [その他] -> [Java] -> [クラス]
  • [次へ]
    • 「名前」: UserRepositoryImpl
    • 「インターフェース:」で [追加] をクリック
    • 「Search」に User といれると表示される「UserRepository」をクリック
    • [OK]
    • [完了]
  • 以下が自動的に生成される
package com.bkiban.app1.repository;

import java.util.List;

import com.bkiban.app1.entity.User;

public class UserRepositoryImpl implements UserRepository {

	@Override
	public List<User> findAll() {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public User findById(int id) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public void insertUser(User user) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void updateUser(User user) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void deleteUser(int id) {
		// TODO 自動生成されたメソッド・スタブ

	}

}
  • @Repository を追記
  • @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate; を追記
  • 各メソッドを以下のように更新する
package com.bkiban.app1.repository;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.bkiban.app1.entity.User;

@Repository
public class UserRepositoryImpl implements UserRepository {

	@Autowired
	private NamedParameterJdbcTemplate jdbcTemplate;

	@Override
	public List<User> findAll() {
		//SQL文の作成
		final String sql = "select id, name, email from user";

		//SQLの実行
		List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<User>(User.class));

		return userList;
	}

	@Override
	public User findById(int id) {
		//SQL文の作成
		final String sql 
		= "select id, name, email from user where id = :id";

		// パラメータの作成
		MapSqlParameterSource param = new MapSqlParameterSource();
		param.addValue("id", id);

		// SQLの実行
		List<User> userList = 
		jdbcTemplate.query(sql, param, new BeanPropertyRowMapper<User>(User.class));

		//リストを判定して戻す
		return userList.isEmpty() ? null : userList.get(0);
	}

	@Override
	public void insertUser(User user) {
		//SQL文の作成
		final String sql = "insert into user(name, email) "
				+ "values(:name,:email)";

		// パラメータの作成
		MapSqlParameterSource param = new MapSqlParameterSource();
		param.addValue("name", user.getName());
		param.addValue("email", user.getEmail());

		// SQLの実行
		jdbcTemplate.update(sql, param);
	}

	@Override
	public void updateUser(User user) {
		//SQL文の作成
		final String sql 
		= "update user set name=:name, email=:email "
		+ "where id=:id";

		// パラメータの作成
		MapSqlParameterSource param = new MapSqlParameterSource();
		param.addValue("id", user.getId());
		param.addValue("name", user.getName());
		param.addValue("email", user.getEmail());

		// SQLの実行
		jdbcTemplate.update(sql, param);
	}

	@Override
	public void deleteUser(int id) {
		//SQL文の作成
		final String sql = "delete from user where id=:id";

		// パラメータの作成
		MapSqlParameterSource param = new MapSqlParameterSource();
		param.addValue("id", id);

		// SQLの実行
		jdbcTemplate.update(sql, param);
	}

}

service (実装)

  • src/main/java/com/bkiban/app1/service で右クリック
  • [新規] -> [その他] -> [Java] -> [クラス]
  • [次へ]
    • 「名前」: UserServiceImpl
    • 「インターフェース:」で [追加] をクリック
    • 「Search」に User といれると表示される「UserService」をクリック
    • [OK]
    • [完了]
  • 以下が自動的に生成される
package com.bkiban.app1.service;

import java.util.List;

import com.bkiban.app1.entity.User;

public class UserServiceImpl implements UserService {

	@Override
	public List<User> findAll() {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public User makeUser(User request) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public void insertUser(User user) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public User findById(int id) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	@Override
	public void updateUser(User user) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void deleteUser(int id) {
		// TODO 自動生成されたメソッド・スタブ

	}

}
  • @Service を追記
  • @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate; を追記
  • 各メソッドを以下のように更新する
package com.bkiban.app1.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bkiban.app1.entity.User;
import com.bkiban.app1.repository.UserRepository;

@Service
public class UserServiceImpl implements UserService {

	@Autowired
	UserRepository userRepository;

	@Override
	public List<User> findAll() {
		return userRepository.findAll();
	}

	@Override
	public User makeUser(User request) {
		//社員オブジェクトの作成
		User user = new User();
		//社員オブジェクトに値を代入
		user.setId(request.getId());
		user.setName(request.getName());
		user.setEmail(request.getEmail());
		//社員オブジェクトを戻す
		return user;
	}

	@Override
	public void insertUser(User user) {
		userRepository.insertUser(user);
	}

	@Override
	public User findById(int id) {
		return userRepository.findById(id);
	}

	@Override
	public void updateUser(User user) {
		userRepository.updateUser(user);
	}

	@Override
	public void deleteUser(int id) {
		userRepository.deleteUser(id);

	}

}

controller

  • src/main/java/com/bkiban/app1/controller で右クリック
  • [新規] -> [その他] -> [Java] -> [クラス]
  • [次へ]
    • 「名前」: UserController
    • [完了]
  • 以下が自動的に生成される
package com.bkiban.app1.controller;

public class UserController {

}
  • @Controller を追記
  • @Autowired
    private ShainService shainService; を追記
  • 各メソッドを以下のように追加する
package com.bkiban.app1.controller;

import java.util.List;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.bkiban.app1.entity.User;
import com.bkiban.app1.service.UserService;

@Controller
public class UserController {

	@Autowired
	private UserService userService;

	@GetMapping("/index")
	public String index(Model model) {

		// リスト取得
		List<User> userList = userService.findAll();

		// JSPに渡す
		model.addAttribute("userList", userList);
		// JSPに転送
		return "index";
	}

	@GetMapping("/insert")
	public String insert() {
		// JSPに転送
		return "insert";
	}

	@PostMapping("/insert")
	public String insert(@ModelAttribute User request) {
		//public void insert(@ModelAttribute User request) {

		//System.out.println(shain.getId() + ":" + shain.getName()
		//+ ":" + shain.getSei() + ":" + shain.getNen()
		//+ ":" + shain.getAddress());

		System.out.println(request + ":" + request.getName() + ":" + request.getEmail());
		System.out.println(ToStringBuilder.reflectionToString(request, ToStringStyle.DEFAULT_STYLE));

		//パラメータ値から社員作成
		User user = userService.makeUser(request);

		//DBに挿入
		userService.insertUser(user);

		// リダイレクト
		return "redirect:/index";
	}

	@GetMapping("/update")
	public String update(
			@RequestParam("id") int id,
			Model model) {

		//対象データを取得
		User user = userService.findById(id);

		// JSPに渡す
		model.addAttribute("user", user);

		// JSPに転送
		return "update";
	}

	@PostMapping("/update")
	public String update(@ModelAttribute User request) {

		//パラメータ値から社員作成
		User user = userService.makeUser(request);

		//DB更新
		userService.updateUser(user);

		// リダイレクト
		return "redirect:/index";
	}

	@GetMapping("/delete")
	public String delete(
			@RequestParam("id") int id,
			Model model) {

		//対象データを取得
		User user = userService.findById(id);

		// JSPに渡す
		model.addAttribute("user", user);

		// JSPに転送
		return "delete";
	}

	@PostMapping("/delete")
	public String delete(
			@RequestParam("id") int id) {

		//DBから削除
		userService.deleteUser(id);

		// リダイレクト
		return "redirect:/index";
	}

}

public String index(Model model) の Model がエラーになっている。マウスをあてて、「'Model' をインポートします (org.springframework.ui)」をクリックする

JSP

  • src/main/webapp/WEB-INF で右クリック
  • [新規] -> [その他] -> [Web] -> [JSP ファイル]
  • [次へ]
    • 「名前」: index
    • [完了]
  • 以下の内容に更新する
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="java.util.ArrayList"%>
<%@page import="com.bkiban.app1.entity.User"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ユーザ一覧</title>
<style>
table {
	border-collapse: collapse; /* セルの境界線を重ねて単線にする */
}

th, td {
	border: 1px solid black; /* セルの境界線のスタイルを設定 */
	padding: 10px;
}
</style>
</head>
<body>
	<h1>ユーザ一覧</h1>

	<table border="1">
		<tr bgcolor="#cccccc">
			<th>ID</th>
			<th>名前</th>
			<th>メールアドレス</th>
			<th>変更</th>
			<th>削除</th>
		</tr>

		<%
		ArrayList<User> userList = (ArrayList<User>) request.getAttribute("userList");
		%>
		<%
		for (User user : userList) {
		%>
		<tr>
			<td><%=user.getId()%></td>
			<td><%=user.getName()%></td>
			<td><%=user.getEmail()%></td>
			<td><a href="update?id=<%=user.getId()%>">変更</a></td>
			<td><a href="delete?id=<%=user.getId()%>">削除</a></td>
		</tr>
		<%
		}
		%>

	</table>
	<p></p>
	<!-- 「ユーザを登録する」ボタン -->
	<form action="insert" method="get">
		<input type="submit" value="ユーザを登録する">
	</form>
</body>
</html>
  • insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>社員登録画面</title>
<style>
.form-input {
	width: 100%;
}

.form-table td {
	padding: 5px;
}

.form-table label {
	text-align: right;
}

.form-button {
	margin-top: 10px;
}
</style>
</head>

<body>
	<h1>社員登録画面</h1>
	<form action="insert" method="post">
		<table class="form-table">
			<tr>
				<td><label for="name">名前:</label></td>
				<td><input type="text" id="name" name="name" class="form-input"
					required></td>
			</tr>
			<tr>
				<td><label for="email">メールアドレス:</label></td>
				<td><input type="text" id="email" name="email"
					class="form-input" required></td>
			</tr>
		</table>
		<button type="submit" class="form-button">登録</button>
	</form>
</body>

</html>
  • update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.bkiban.app1.entity.User"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ユーザ更新画面</title>
<style>
.form-input {
	width: 100%;
}

.form-table td {
	padding: 5px;
}

.form-table label {
	text-align: right;
}

.form-button {
	margin-top: 10px;
}
</style>
</head>
<body>
	<%-- shainから社員情報を取得する --%>
	<%
	User user = (User) request.getAttribute("user");
	%>
	<h1>ユーザ更新画面</h1>
	<form action="update" method="post">
		<table class="form-table">
			<tr>
				<td><label for="id">ID:</label></td>
				<td><%=user.getId()%></td>
			</tr>
			<tr>
				<td><label for="name">名前:</label></td>
				<td><%=user.getName()%></td>
			</tr>
			<tr>
				<td><label for="email">メールアドレス:</label></td>
				<td><input type="text" id="email" name="email"
					value="<%=user.getEmail()%>" class="form-input" required></td>
			</tr>
		</table>
		<button type="submit" class="form-button">更新</button>
		<input type="hidden" name="id" value="<%=user.getId()%>">
		<input type="hidden" name="name" value="<%=user.getName()%>">
	</form>
</body>
</html>
  • delete.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.bkiban.app1.entity.User"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ユーザ削除画面</title>
<style>
.form-input {
	width: 100%;
}

.form-table td {
	padding: 5px;
}

.form-table label {
	text-align: right;
}

.form-button {
	margin-top: 10px;
}
</style>
</head>
<body>
	<%-- shainから社員情報を取得する --%>
	<%
	User user = (User) request.getAttribute("user");
	%>
	<h1>ユーザ削除画面</h1>
	<form action="delete" method="post">
		<table class="form-table">
			<tr>
				<td><label for="id">ID:</label></td>
				<td><%=user.getId()%></td>
			</tr>
			<tr>
				<td><label for="name">名前:</label></td>
				<td><%=user.getName()%></td>
			</tr>
			<tr>
				<td><label for="email">メールアドレス:</label></td>
				<td><%=user.getEmail()%></td>
			</tr>
		</table>
		<button type="submit" class="form-button">削除</button>
		<input type="hidden" name="id" value="<%=user.getId()%>">
	</form>
</body>
</html>

動作確認

  • Bootダッシュボードで app1 を起動
  • ブラウザから localhost:8080/index にアクセス

スクリーンショット 2025-01-04 14.55.55.png

  • [ユーザを登録する] をクリック

スクリーンショット 2025-01-04 14.57.48.png

  • [登録] をクリック

スクリーンショット 2025-01-04 14.58.47.png

  • ID: 1 の [削除] をクリック

スクリーンショット 2025-01-04 15.00.08.png

  • [削除] をクリック

スクリーンショット 2025-01-04 15.05.29.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?