Spring Boot によるWebアプリ開発

2021システム開発実習

SpringBoot

MusicPlayerをWebアプリにする

更新日:

データベースを用意する

配布フォルダの hsqldb をコピーして、自分の領域に保存する。

bin フォルダの runServer.bat をコピーして runServerMp.bat を作成する。

cd ..\data
@java -classpath ../lib/hsqldb.jar org.hsqldb.server.Server --database.0 db/mp --dbname.0 mp

runServerMp.bat をダブルクリックすると、コマンドプロンプトの画面が開いてデータベースサーバーが起動する。

bin フォルダの runManager.bat をダブルクリックする。
Connectのダイアログを表示するので、Type で HSQL Database Engine Server を選択し、
URL の最後に mp を追加すると、データベースインスタンスにアクセスできる。

MusicPlayerプロジェクトを作成

新規プロジェクトを作成する。

プロジェクトの種類は、Springスターター・プロジェクト
名前: MusicPlayer
グループ: jp.kpc
成果物: MusicPlayer
パッケージ: jp.kpc

プロジェクト依存関係で、以下のものを追加する。

  • HyperSQL Database
  • Spring Data JPA
  • Spring Web
  • Thymeleaf

pom.xmlを修正

pom.xml を開いて8行目の 2.5.6 を 2.2.1.RELEASE に変更して保存する。

自作HTMLページを表示する

URL=”/” にアクセスしたときに何かを表示できるようにする。

IndexControllerを作成する。
src/main/java の中にある jp.kpc を右クリックし[新規]-[クラス]を選択する。
名前に「IndexController」と入力し「完了」をクリック。

SpringBoot に対して、このクラスがコントローラであることを教えるために、@Controller アノテーションを追加する。
public class の前の行で「@Cont」を入力してCtrl+スペースを入力すると候補がリストアップされる。
org.springframework.stereotype のControllerを選択する。

package jp.kpc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}

}

HTMLを用意する

src/main/resources の下にある templates を右クリックして[新規]-[その他]を選択する。
「HTMLファイル」を選択し「次へ」をクリック。
ファイル名を index.html にして「次へ」をクリック。
「新規HTMLファイル(5)」を選択して「完了」をクリック。

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>

<h1>MusicPlayer</h1>

</body>
</html>

SpringBoot アプリケーションを再起動して http://localhost:8080/ にアクセスすると、「MusicPlayer」と表示される。

入力フォームを追加

index.html に、音楽を登録するための入力フォームを追加する。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>

<h1>MusicPlayer</h1>

<h3>曲を追加する</h3>
<form action="/addmusic" method="post">
	<table>
		<tr>
			<td>タイトル</td>
			<td><input type="text" name="title" /></td>
		</tr>
		<tr>
			<td>アーティスト</td>
			<td><input type="text" name="artist" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>

</body>
</html>

SpringBoot アプリケーションを再起動して http://localhost:8080/ にアクセスすると、入力フォームが表示される。

データベースにMusicを保存するために、Musicクラスを作成する。

package jp.kpc;

import javax.persistence.Entity;

@Entity
public class Music {
	private long id;
	private String title;
	private String artist;
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getArtist() {
		return artist;
	}
	public void setArtist(String artist) {
		this.artist = artist;
	}
}

SpringBootのシステムに、各フィールドがデータベースのカラムであることを知らせるためのアノテーションを追加する。

package jp.kpc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class Music {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String title;

	@Column
	@NotEmpty
	private String artist;

	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getArtist() {
		return artist;
	}
	public void setArtist(String artist) {
		this.artist = artist;
	}
}

MusicRepository を作成する。

jp.kpc を右クリックして[新規]-[インターフェース] を選択する。

名前は MusicRepository を指定。
拡張インターフェースの右の追加をクリックし、JpaRepository を選択してOKする。
extends JpaRepository の T を Music に、ID を Long に修正するとエラーが消える。

package jp.kpc;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MusicRepository extends JpaRepository<Music, Long> {

}

データベースとの接続設定を application.properties ファイルに記述する。

spring.datasource.url=jdbc:hsqldb:hsql://localhost/mp
spring.datasource.username=SA
spring.datasource.password=
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.hibernate.ddl-auto=update

IndexController に、URL /addmusic に対するPOSTメソッドでのアクセスを受け取るためのコードを追加する。

package jp.kpc;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {
	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		return new ModelAndView("redirect:/");
	}
}

MusicRepositoryを使用して、Musicをデータベースに保存する。

package jp.kpc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

	@Autowired
	private MusicRepository repository;

	@RequestMapping("/")
	public String index() {
		return "index";
	}

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		System.out.println("title=" + title + ", artist=" + artist);
		Music music = new Music();
		music.setTitle(title);
		music.setArtist(artist);
		repository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}
}

index.html に、Musicリストを追加する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>

<h1>MusicPlayer</h1>
<h3>Musicリスト</h3>
<table>
	<tr>
		<th>ID</th>
		<th>タイトル</th>
		<th>アーティスト</th>
	</tr>
	<tr th:each="music : ${list}">
		<td th:text="${music.id}"></td>
		<td th:text="${music.title}"></td>
		<td th:text="${music.artist}"></td>
	</tr>
</table>


<h3>曲を追加する</h3>
<form action="/addmusic" method="post">
	<table>
		<tr>
			<td>タイトル</td>
			<td><input type="text" name="title" /></td>
		</tr>
		<tr>
			<td>アーティスト</td>
			<td><input type="text" name="artist" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>

</body>
</html>

IndexControllerから、Musicリストをテンプレートに渡すようにする。

package jp.kpc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

	@Autowired
	private MusicRepository repository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		List<Music> list = repository.findAll();
		mav.addObject("list", list);
		return mav;
	}

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		System.out.println("title=" + title + ", artist=" + artist);
		Music music = new Music();
		music.setTitle(title);
		music.setArtist(artist);
		repository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}
}

プレイリストを追加できるようにする。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>

<h1>MusicPlayer</h1>
<h3>Musicリスト</h3>
<table>
	<tr>
		<th>ID</th>
		<th>タイトル</th>
		<th>アーティスト</th>
	</tr>
	<tr th:each="music : ${list}">
		<td th:text="${music.id}"></td>
		<td th:text="${music.title}"></td>
		<td th:text="${music.artist}"></td>
	</tr>
</table>



<h3>曲を追加する</h3>
<form action="/addmusic" method="post">
	<table>
		<tr>
			<td>タイトル</td>
			<td><input type="text" name="title" /></td>
		</tr>
		<tr>
			<td>アーティスト</td>
			<td><input type="text" name="artist" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>

<h3>プレイリストを追加する</h3>
<form action="/addplaylist" method="post">
	<table>
		<tr>
			<td>名前</td>
			<td><input type="text" name="name" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>


</body>
</html>

PlayListクラスを作成する。

package jp.kpc;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

@Entity
public class PlayList {
	@Id
	@GeneratedValue
	@Column
	@NotNull
	private long id;

	@Column
	@NotEmpty
	private String name;

	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

PlayListRepository を、MusicRepository同様に作成する。

package jp.kpc;

import org.springframework.data.jpa.repository.JpaRepository;

public interface PlayListRepository extends JpaRepository<PlayList, Long> {

}

IndexController で、プレイリストの追加を受け取ってDBに保存するようにする。

package jp.kpc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

	@Autowired
	private MusicRepository musicRepository;

	@Autowired
	private PlayListRepository playListRepository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		List<Music> list = musicRepository.findAll();
		mav.addObject("list", list);
		return mav;
	}

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		System.out.println("title=" + title + ", artist=" + artist);
		Music music = new Music();
		music.setTitle(title);
		music.setArtist(artist);
		musicRepository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}

	@RequestMapping(value="/addplaylist", method=RequestMethod.POST)
	public ModelAndView addPlayList(ModelAndView mav,
			@RequestParam("name") String name) {
		PlayList playList = new PlayList();
		playList.setName(name);
		playListRepository.saveAndFlush(playList);
		return new ModelAndView("redirect:/");
	}
}

index.html にプレイリストの一覧を表示する。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>MusicPlayer</title>
</head>
<body>

<h1>MusicPlayer</h1>
<h3>Musicリスト</h3>
<table>
	<tr>
		<th>ID</th>
		<th>タイトル</th>
		<th>アーティスト</th>
	</tr>
	<tr th:each="music : ${musics}">
		<td th:text="${music.id}"></td>
		<td th:text="${music.title}"></td>
		<td th:text="${music.artist}"></td>
	</tr>
</table>

<h3>プレイリスト</h3>
<table>
	<tr>
		<th>ID</th>
		<th>名前</th>
	</tr>
	<tr th:each="playlist : ${playlists}">
		<td th:text="${playlist.id}"></td>
		<td th:text="${playlist.name}"></td>
	</tr>
</table>


<h3>曲を追加する</h3>
<form action="/addmusic" method="post">
	<table>
		<tr>
			<td>タイトル</td>
			<td><input type="text" name="title" /></td>
		</tr>
		<tr>
			<td>アーティスト</td>
			<td><input type="text" name="artist" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>

<h3>プレイリストを追加する</h3>
<form action="/addplaylist" method="post">
	<table>
		<tr>
			<td>名前</td>
			<td><input type="text" name="name" /></td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" value="追加" />
		</td>
	</table>
</form>


</body>
</html>

IndexController で、プレイリストの一覧を取得してテンプレートに渡す。

package jp.kpc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

	@Autowired
	private MusicRepository musicRepository;

	@Autowired
	private PlayListRepository playListRepository;

	@RequestMapping("/")
	public ModelAndView index(ModelAndView mav) {
		mav.setViewName("index");
		List<Music> musics = musicRepository.findAll();
		mav.addObject("musics", musics);
		List<PlayList> playlists = playListRepository.findAll();
		mav.addObject("playlists", playlists);
		return mav;
	}

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		System.out.println("title=" + title + ", artist=" + artist);
		Music music = new Music();
		music.setTitle(title);
		music.setArtist(artist);
		musicRepository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}

	@RequestMapping(value="/addplaylist", method=RequestMethod.POST)
	public ModelAndView addPlayList(ModelAndView mav,
			@RequestParam("name") String name) {
		PlayList playList = new PlayList();
		playList.setName(name);
		playListRepository.saveAndFlush(playList);
		return new ModelAndView("redirect:/");
	}
}

Musicを削除できるようにする。

index.html に削除用のリンクを配置する。リンクには、Musicのidを埋め込んでおく。

<h3>Musicリスト</h3>
<table>
	<tr>
		<th>ID</th>
		<th>タイトル</th>
		<th>アーティスト</th>
		<th>操作</th>
	</tr>
	<tr th:each="music : ${musics}">
		<td th:text="${music.id}"></td>
		<td th:text="${music.title}"></td>
		<td th:text="${music.artist}"></td>
		<td><a th:href="@{'/deletemusic/' + ${music.id}}">削除</a></td>
	</tr>
</table>

IndexController に、削除用リンクに対応するマッピングを追加する。

	@RequestMapping(value="/addmusic", method=RequestMethod.POST)
	public ModelAndView addMusic(ModelAndView mav,
			@RequestParam("title") String title,
			@RequestParam("artist") String artist) {
		System.out.println("title=" + title + ", artist=" + artist);
		Music music = new Music();
		music.setTitle(title);
		music.setArtist(artist);
		musicRepository.saveAndFlush(music);
		return new ModelAndView("redirect:/");
	}

	@RequestMapping(value="/deletemusic/{id}", method=RequestMethod.GET)
	public ModelAndView deleteMusic(ModelAndView mav,
			@PathVariable long id) {
		musicRepository.deleteById(id);
		return new ModelAndView("redirect:/");
	}

-SpringBoot

Copyright© 2021システム開発実習 , 2025 All Rights Reserved Powered by STINGER.