spring bootとは
昨年の新人研修でこれからはspring bootですよと言っていた生徒がいましたが、まったく手つかずでした。 今年もVscCodeでmavenとかやってましたが、もう少し開発が楽にならないかとspring bootをやってみることにしました
Springは多数のフレームワークから構成されているようで、spring Frameworkをベースとしたアプリケーション構築のためのフレームワークだそうです。 Springで開発するときのスターターキットのようなもので、この機能が欲しいから別のフレームワークを追加して、今度はこれと、自分で選んで追加できます。
Spring frameworkの基盤の上に、WebとSecurityを追加して、ログイン機能を作るような感じでできるようです。
構成要素
spring bootをVsCodeでやってみる
例によって、VsCodeでやってみようと思います。実はその前にEclipseでもやってみましたが、同じことがVsCodeでできたので こちらでやることにしました
すでにVsCodeはインストール済みとしてMavenまで入れておきましょう。VsCode MavenでJavaを参考にしてください。
Vscodeの左の列の拡張機能からspringを検索して「Spring boot extension pack」を選んでインストールします。必要な4つほどの物が自動でインストールされます。VsCodeを再起動するのがいいでしょう。
				また前述のようにMavenまたはgradleが使える環境にしておいてください。これから使用するSpring initializrはこの両方のコンパイル環境を作ってくれます。
Mavenの解説をします。Mavenでは「src」フォルダーと「target」フォルダー以下にそれぞれのファイルがまとめられます。最初はsrcの配下にソースを入れて、compileすることでtargetにclassやjarが出来ていきます。
またどのようなライブラリーを使用するのかを、srcやtargetの上のフォルダーにpom.xmlファイルを宣言して置いておきます。この中身はウイザードに答えると自動で生成されます。
今度作る予定のアプリ
Webなしのコマンドプロンプトアプリ
まずは単純なコマンドプロンプトを使ったアプリを作ります。
「CTRL+SHIFT+P」を押してコマンドパレットを表示します。Spring initializr:Create a Maven projectを選びます。
				適当なバージョンを選びます。(2024/6/25現在 3.3.1)。
				今回はjavaでいきます
				groupidをドメインの逆さまを小文字で入力します
				artifactIdはプロジェクトの認識名でこれもスペースなしの小文字で入れます
				パッケージで作製するものを選びます。今回はjarにします。複数のクラスができても一つにまとめてくれます。
				javaのバージョンを入れます。17以降であればなんでも、結局eclipseのjavaが使用されました。
				最後にspringのどの機能を追加するのか決めますが、今回はなんにも使わないので0selectをクリックしましょう。
				自分できめたworkspaceの中にフォルダーを作成して、「select folder」します。
				フォルダー群が自動で作成され、画面右下に色々質問が流れてきますが、私は全部「Yes」「Open」「Enable」で受け入れました。そうすると実行環境ができます。
				
				「src」フォルダー以下を展開していくとjavaのソースファイルが見えます。
	package com.example.springcmd;
	import org.springframework.boot.SpringApplication;
	import org.springframework.boot.autoconfigure.SpringBootApplication;
	
	@SpringBootApplication
	public class SpringcmdApplication {
	
		public static void main(String[] args) {
			SpringApplication.run(SpringcmdApplication.class, args);
		}
	
	}
				これがspringで生成されるデフォルトのソースファイルです。これをただのprintlnに変更します。
		public static void main(String[] args) {
			System.out.println("Hello spring world!");
		}
				これではspringではありませんが、まずは開発の流れの確認です。
左下にあるMavenのメニューから自分のプロジェクトを右クリックして「run maven command」でinstallをします
				下にメッセージが出て止まるまで待ちます
				同様にcompileしてBUILD SUCCESSが出るまで待ちます
				mainのすぐ上にある「run」をクリックします。
				結果が出ます
				packageまでするとtargetの下にjarファイルができるので、コマンドプロンプトで実行もできます
				Modelを使用する
次にservletからhtmlへパラメータを渡すサンプルを作ります。まずはModelクラスとThymeleaf(タイムリーフ)テンプレートを使います。
Thymeleafを使うとjspファイルのようにhtmlとjavaを混在したものが書けますが、jspと違ってパラメータの受け取り部分などを書く必要がなく、直接表示できるような記述が可能です。
そこに向けて変数をパラメータ渡しするのにModelクラスを使用します。jspではタグのコンテンツ部分に<%= md.getSmemo() %>のように変数や関数を記述しますが、 thymeleafでは、タグの属性(attribute)として特殊な記述をします。<p th:text="${message}"></p>とすると、コンテンツとしてmessage変数の内容が表示されます。
作り始めはコマンドプロンプトの時と同じで「CTRL+SHIFT+P」で「spring init」からspring initializr:create a maven projectを選択します。
そして「select dependencies」のところで「Spring Web web」と「Thymeleaf template engines」を選択しておきます。
				このようにしてプロジェクトを作成するとそれなりのpom.xmlができます。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
ウィザードでwebとthymeleafを追加したのでそれらが入っています。また-testはすべてに追加されています。
ところでいつものようにBootstrap5を入れたいのですが、springでも対応しているので次のdependencyを追加してください。
<dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>5.3.0</version> </dependency>
さて、これで準備ができたので、ソースを作ってきます。今回作るのは、日付を指定して、その前後の日付を計算するという簡単なアプリです。
では、index.htmlを作っていきましょう。jspではありません。thymeleafではhtmlで作成します。
resources配下のtempletes配下に新しいファイルを追加します。名前はindex.htmlとします。
				内容としては、input type="date"で入力したsdate変数とinput type="number"で入力したdplus変数を受け取って、結果を計算して次のresult.htmlのmessageに渡すというものです。
	<!doctype html>
	<html lang="ja" xmlns:th="http://www.thymeleaf.org">
	  <head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Bootstrap demo</title>
		<link th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}" rel="stylesheet">
	  </head>
	  <body>
		<div class="container">
		  <main>
			<div class="py-5 text-center">
			  <h2>Model test</h2>
			  <p class="lead" th:text="${message}"></p>
			</div>
			<div class="text-center">
			  <h4 class="mb-3">日付計算</h4>
			  <form class="needs-validation" th:action="@{/result}" method="POST">
				  <div class="row g-12">
					<div class="col-sm-6">
					  <label for="sdate" class="form-label">日付</label>
					  <input type="date" class="form-control" id="sdate" name="sdate" placeholder="yyyy-MM-ddで日付を記述してください" value="" required>
					</div>
		
					<div class="col-sm-6">
					  <label for="dplus" class="form-label">前後日付</label>
					  <input type="number" class="form-control" id="dplus" name="dplus" placeholder="+ -付きで日付を入力してください" value="" required>
					</div>
				  </div>
		
				  <hr class="my-4">
		
				  <button class="w-100 btn btn-primary btn-lg" type="submit">計算実行</button>
			  </form>
			</div>
		  </main>
		
		  <footer class="my-5 pt-5 text-body-secondary text-center text-small">
			<p class="mb-1">© 2024 Etlab</p>
		  </footer>
		</div>
		<script th:src="@{/webjars/bootstrap/5.3.0/js/bootstrap.min.js}"></script>
	  </body>
	</html>
				最初に、index.htmlの先頭でthymeleafの宣言をしています。またbootstrapはwebjarsフォルダー以下にインストール済みなので、それを利用します。bootstrapで画面を作成しています。
				この画面が呼ばれるのがリクエストが localhost:8080/ の時です。そこで呼び出しの部分を作成します。
パッケージのspmodeltestフォルダーで右クリックして、「new java file」 「class」で「DateController.java」を作ります。
				先に作ってあった「SpmodeltestApplication.java」ソースは何も触りません。触らなくても@アノテーションを付けることによって自動的に検索して連動してくれるようになります。
	package jp.co.etlab.spmodeltest;
	import org.springframework.stereotype.Controller;
	import org.springframework.ui.Model;
	import org.springframework.web.bind.annotation.RequestMapping;
	import org.springframework.web.bind.annotation.RequestMethod;
	import org.springframework.web.bind.annotation.RequestParam;
	
	
	@Controller
	public class DateController {
		@RequestMapping(value="/", method=RequestMethod.GET)
		public String index(Model model) {
			model.addAttribute("message", "日付の計算を行います。日付と差分を入力してください。");
			return "index";
		}
	}
				クラスにつけた@Controllerアノテーションを付けることで、このクラスがMVC機能のコントローラー機能を持つことになります。 そして@RequestMappingアノテーションでどのURLの時にどのモジュールが呼ばれるかを指定します。今回はindex()関数がGETでリクエストを受けた時のエントリーポイントとなります。
関数名はなんでも構いません。そして今回の目的であるModelクラスを引数に記述します。オブジェクトのmodelにaddAttributeする形でmessage変数に文字列を代入しています。これが先ほどのindex.htmlの@{message]に渡ります。
そしてreturnがString型のhtmlファイル名になります。htmlは省略できるので、"index"で大丈夫です。
これでindex.htmlを呼び出して入力画面を出すところまでできました。
続いて、index.htmlでsubmitボタンが押された時の行先の設定の部分のプログラムをこのクラスの後方に連続して記述します。
    @RequestMapping(value="/result", method=RequestMethod.POST)
    public String datecalc(@RequestParam("sdate") String ssdate,
                        @RequestParam("dplus") String splusd, Model model) {
        DateModel dm = new DateModel();
        dm.setSdate(ssdate);
        dm.setDplus(splusd);
        //計算
        dm.calcDate();
        model.addAttribute("message", dm.getSdate() + " の" + Math.abs(dm.getDplus()) +
            "日" + (dm.getDplus()>0 ? "後" : "前") + "は " + dm.getCdate() + "です");
        return "result";
    }
				index()関数の兄弟としてdatecalc()関数を記述します。@RequestMappingアノテーションの働きにより、URL localhost:8080/result のPOSTの時に起動されるように指定されます。
datecalc()関数の引き数として、@RequestParamアノテーションでsdateとdplusが指定されています。これによってindex.htmlで入力された値はここで受信されます。そしてここにもModelクラスがあり、result.htmlへのパラメータ渡し用に準備されています。
ここで少しこのソースから離れて、今回必須ではないDateModel.javaに関して説明します。これがなくてもパラメータのやり取りはできます。ただ今後の流れの関係でここで宣言しています。
このDateModelクラスに受け渡しする変数と計算を入れておきます。さきほどDateController.javaファイルを作ったのと同じ流れでDateModel.javaを追加してください。
	package jp.co.etlab.spmodeltest;
	import java.time.LocalDate;
	import java.time.format.DateTimeFormatter;
	
	public class DateModel {
		DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	
		/* 日付 */
		private LocalDate sdate;
	
		/* 前後日数 */
		private int dplus;
	
		/* 計算日付 */
		private LocalDate cdate;
	
		public LocalDate getSdate() {
			return sdate;
		}
	
		public void setSdate(LocalDate sdate) {
			this.sdate = sdate;
		}
		public void setSdate(String ssdate) {
			this.sdate = LocalDate.parse(ssdate,fmt);
		}
	
		public int getDplus() {
			return dplus;
		}
	
		public void setDplus(int dplus) {
			this.dplus = dplus;
		}
		public void setDplus(String sdplus) {
			this.dplus = Integer.parseInt(sdplus);
		}
	
		public LocalDate getCdate() {
			return cdate;
		}
		public String getScdate() {
			return this.cdate.format(fmt);
		}
	
		/* 日付計算 */
		public void calcDate() {
			LocalDate tmp = this.sdate.plusDays(this.dplus);
			this.cdate = tmp;
		}
		
	}
				このクラスのオブジェクトをdatecalc()関数で作成し、パラメータを格納し、計算しています。計算ができたらresult.htmlへmessage変数として送っています。
さて今度はそのresult.htmlです
	<!doctype html>
	<html lang="ja" xmlns:th="http://www.thymeleaf.org">
	  <head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Bootstrap demo</title>
		<link th:href="@{/webjars/bootstrap/5.3.0/css/bootstrap.min.css}" rel="stylesheet">
	  </head>
	  <body>
		<div class="container">
		  <main>
			<div class="py-5 text-center">
			  <h2>Model test</h2>
			  <p class="lead">日付計算の結果です</p>
			  <p class="my-5" th:text="${message}"></p>
			  <hr class="my-4">
			  <a href="/" class="btn btn-outline-primary" role="button">再計算</a>
			</div>
		  </main>
		
		  <footer class="my-5 pt-5 text-body-secondary text-center text-small">
			<p class="mb-1">© 2024 Etlab</p>
		  </footer>
		</div>
		<script th:src="@{/webjars/bootstrap/5.3.0/js/bootstrap.min.js}"></script>
	  </body>
	</html>
				では、これをコンパイルしていきましょう。mavenを使用します。先ほどコマンドプロンプトでやったのと同じ手法でinstall,compileを行ってください。
実行方法が少し違います。今度はWebになりますので、springで起動するとserverが起動されてそこに今作成したアプリが登録されます。
mainの上のrunをクリックして起動してください。
				このようにtomcatにspmodeltestが登録されます。そしてブラウザを起動してurlを入力します。
				日付と差分を入力して、計算実行をクリックすると、
				計算結果がresult.htmlで表示されます。「再計算」をクリックすれば、GETで/に飛んでいくのでまた計算できます。
最後に終了の仕方です。tomcatが起動されてますが、これはプログラムの実行とは関係なく動いています。 なので、tomcatは別に止める必要があります。
				停止ボタンで留めるとtomcatが停止します。