SpringMVC + JSP の環境構築とサンプル実装
前置き
- この記事は、ローカルPCに開発環境構築をすること、サンプルプログラムを実装することを焦点にあてた記事です。
- 実際にアプリケーション開発しサーバーで稼働させるには、セキュリティ観点や開発をスケールさせるための設計のために いくつか留意すべきことがあります。そちらについては、別途文献をご参照ください。
構築する開発環境
ゴール:下記構成のSpringBootを用いたWebアプリケーションの開発環境構築.
なお、できるのであれば lombok も導入するとコーディングが捗ります。
実行構成について
Oracle DB インスタンスについて
Oracleのローカル開発環境構築は割愛。 なお、この環境構築時にはDockerForWindows、およびOracle公式のDockerImageを用いて、ローカルPC上に構築した。
https://itedge.stars.ne.jp/docker_image_oracle_database_19c/
Oracleの単体稼働に2GBのメモリが必要なため、8GBのPCで開発するには若干パワー不足になる。
必要なソフトウェアのダウンロード
JDK 11
Javaの実行ランタイムと開発用のライブラリ・ツールがまとまったセット。 自分の環境用のインストーラを入手。今回は、Windows向けのものを想定する。
https://www.oracle.com/java/technologies/javase-jdk11-downloads.html
STS
統合開発環境。アプリケーション開発に必要。 予めプラグインを組み込んでセットアップ済みのEclipseが配布されている。 自分の環境用のzipファイルを入手。今回は、Windows向けのものを想定する。
Tomcat 9
JavaServlet用のWebサーバー。 自分の環境用のzipファイルを入手。今回は、Windows向けのものを想定する。
https://tomcat.apache.org/download-90.cgi
JDKのインストールとセットアップ
> java -version java version "11.0.6" 2020-01-14 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.6+8-LTS) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.6+8-LTS, mixed mode)
Tomcatのインストールとセットアップ
開発環境の環境変数を変更し「JAVA_HOME」にJDKのインストールパスを設定する。 ここでは、
C:\Program Files\Java\jdk-11.0.6
を設定したとする。 設定は、Windowsであれば設定
>環境変数を編集
を検索し、ユーザー環境変数に設定する。入手したTomcatのバイナリを解凍する。ここでは、解凍し
C:\opt\apache-tomcat-9.0.34
に配置したとする。解凍したディレクトリのbin配下にコマンドプロンプトやターミナルを起動し、 下記コマンドを実行してTomcatをデバッグ用ポートありで起動する。
./catalina jpda start
- ブラウザを起動し、http://localhost:8080 にアクセスしてTomcatの管理画面が表示されるか確認する。
STSのインストールとセットアップ
STSの解凍と起動
STSを解凍し、配置しておきたいフォルダに配置する。
SpringToolSuite4.exe
を実行する。
Note:メモリ不足の場合、 SpringToolSuite4.ini
からJVM引数を編集する。
- workspace(ファイル配置場所)を聞かれたら、とりあえず新しいフォルダ先を指定する。
Eclipseのデフォルトに従うなら、
(SpringToolSuite4.exeがあるフォルダ)/workspace
Gradleプラグインのインストール
- STS上部メニュー
Help
>Eclipse Marketplace...
をクリック - Eclipse MarcketPlaceウィンドウの
Search
タブで、Find:
にGradle
を入力してEnter Gradle ID Pack x.x.x ~
をInstall
。- ライセンスの確認ダイアログが表示されたら、「~Agree All~」みたいなラジオボタンを選択して「Finish」
- STSを再起動する
文字コードの設定
デフォルトのエンコーディングを、Java標準の UTF-8
に設定する。
- STS上部メニュー
Window
>Preferences
をクリック General
>Workspace
をクリックText file encoding
から、Other
: UTF-8 を選択Apply and Close
をクリック
オプション:STSの設定
下記、設定しておくと便利なもの。 もし、開発プロジェクトで標準の環境を作りたい場合、これらを事前設定する手順を追加しておくとよいです。
STS日本語化
保管アクション
- https://lifeinprogram.com/2018/11/25/post-355/
- Javaでは、「Organize imports」(自動インポート)や「Format all lines」 + GoogleStyleフォーマッターによる 自動フォーマットがあればだいたい標準化できる。
- checkStyle は静的解析ツールで、小うるさいことが多い。 新規プロジェクトでレビュー負荷を何がなんでも下げるんだ、という意志を貫きとおす自信がなければ、温かみのある手法に準じるのも一興。
サンプルプロジェクトの作成
サンプルプロジェクト作成
Service URL:任意 Name: プロジェクト名。ここでは「sample」とする Type:「Gradle(Buildship3.x)」 Packaging:「War」 Java Version:「11」 Language:「Java」 Group: mavenがらみの設定。例えば google なら com.google となっている。「org.pack」とする。 Artifact: mavenがらみの設定。通常プロジェクト名をいれる。ここは「sample」とする Version: ビルドスクリプトで参照できる。とりあえず0.0.1-SNAPSHOT でよい。 Description: 説明文。 Package: Javaパッケージの接頭辞。ここでは「org.pack.sample」とする。
- 定番のフレームワーク依存関係の入力し、
Finish
ここでは、下記をチェック。この内容は、 build.gradle
に反映される。
SQL
>MyBatis Framework
SQL
>Oracle Driver
Web
>Spring Web
サンプルアプリケーションの実装(共通部分、Mybatis用設定)
下記に従って、ソースコードを変更、または新規作成する。
編集: src/main/java/org/pack/sample/SampleApplication.java
アプリケーションのエントリーポイント(実行起点)となるソースコード。
- @ComponentScan を追加、サブパッケージをスキャンしてDIできるようにする
- @EnableAutoConfiguration を追加、JavaConfig機能を有効にする。
package org.pack.sample; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class }) @SpringBootApplication public class SampleApplication { public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); } }
新規: src/main/java/org/pack/sample/config/MyBatisConfiguration.java
DI時にマニュアルでインスタンス作成することでいろいろカスタマイズするため設定コード。 このコードはMyBatisに特化。
- MyBatisの定義クラス Mapper のパッケージを指定
- ついでに色々要求されたので、いい感じのを記述
package org.pack.sample.config; import java.sql.Driver; import java.util.Properties; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.SimpleDriverDataSource; @Configuration public class MyBatisConfiguration { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage("org.pack.sample.mapper"); configurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return configurer; } @Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); return factoryBean.getObject(); } @SuppressWarnings("unchecked") @Bean public DataSource dataSource(DataSourceProperties properties) throws ClassNotFoundException { SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); dataSource.setDriverClass((Class<? extends Driver>) Class.forName(properties.determineDriverClassName())); dataSource.setUrl(properties.determineUrl()); dataSource.setUsername(properties.determineUsername()); dataSource.setPassword(properties.determinePassword()); Properties connectionProperties = new Properties(); connectionProperties.setProperty("autoCommit", "false"); dataSource.setConnectionProperties(connectionProperties); return dataSource; } }
編集:src/main/resources/application.properties
全体の設定ファイル。
spring.profiles.active=local spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp mybatis.mapper-locations=classpath*:/com/example/demo/mapper/**/*.xml
編集:src/main/resources/application.properties
ローカル環境用の設定ファイル。Tomcatのcontext.xmlの記述で切り替え可能。
参考: https://exceptionblend.wordpress.com/2013/02/11/springframework-profile/
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl spring.datasource.username=system spring.datasource.password=password spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
サンプルアプリケーションの実装(個別実装)
新規:src/main/resources/org/pack/sample/mapper/HealthCheckMapper.xml
MyBatisのMapper向けのSQL定義ファイル。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.pack.sample.mapper.HealthCheckMapper"> <select id="select" resultType="Long"> SELECT 1 FROM dual </select> </mapper>
新規:src/main/resources/org/pack/sample/mapper/HealthCheckMapper.xml
MyBatisのMapper向けのJavaファイル。
package org.pack.sample.mapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface HealthCheckMapper { long select(); }
新規:src/main/java/org/pack/sample/controller/LoginController.java
Webアプリケーションのリクエストを直接処理する。
package org.pack.sample.controller; import org.jboss.logging.Logger; import org.pack.sample.mapper.HealthCheckMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/login") public class LoginController { Logger logger = Logger.getLogger(LoginController.class); @Autowired private HealthCheckMapper healthCheck; @RequestMapping(value = "", method = RequestMethod.GET) public String index() { long n = healthCheck.select(); logger.info("helthckeck:" + n); return "login"; } @RequestMapping(value = "", method = RequestMethod.POST) public String login(LoginForm form, Model model) { LoginModel loginModel = new LoginModel(); final String loginid = "user"; final String password = "pass"; if (loginid.equals(form.loginid) && password.equals(form.password)) { loginModel.message = "ログインできました."; } else { loginModel.message = "ユーザーまたはパスワードが違います."; } loginModel.loginid = form.loginid; loginModel.password = form.password; model.addAttribute("loginModel", loginModel); return "login"; } /** * ログインフォームのリクエストパラメータ。本当は別ファイルに書くべき */ public class LoginForm { private String loginid; private String password; public String getLoginid() { return loginid; } public void setLoginid(String loginid) { this.loginid = loginid; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } /** * ログインフォームのレンダリングに利用するパラメータ。本当は別ファイルに書くべき */ public class LoginModel { private String message; private String loginid; private String password; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getLoginid() { return loginid; } public void setLoginid(String loginid) { this.loginid = loginid; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } }
新規:src/main/webapp/WEB-INF/views/login.jsp
HTMLテンプレート。
webappディレクトリが、WARファイルを配置した時のルートになる。この下に、jsやcssなどを配置する。
また、WEB-INF配下はTomcatの仕様でブラウザから直接アクセスできなくなる。
<%@ page contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <form action="login" method="POST"> <div>${loginModel.message}</div> <table> <tr> <td>ユーザ</td> <td><input type="text" name="loginid" value="${loginModel.loginid}"></td> </tr> <tr> <td>パスワード</td> <td><input type="password" name="password" value=""></td> </tr> </table> <button type="submit">ログイン</button> </form> </body> </html>
Gradleの依存関係更新
build.gradle または プロジェクト自体 を右クリック > Gradle
> Reflesh Gradle Project
で build.gradle の解析と Maven central リポジトリからの依存ライブラリの取得を実施する。
ビルドスクリプトの修正とTomcatへの配備
- build.gradleを編集し、下記とおりにする
plugins { id 'org.springframework.boot' version '2.2.6.RELEASE' id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'java' id 'war' } group = 'org.pack' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' // ▽追加 def warName = 'sample.war' def localTomcatWebapps = 'C:\\opt\\apache-tomcat-9.0.34\\webapps' // △追加 repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.2' runtimeOnly 'com.oracle.ojdbc:ojdbc8' providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } } // ▽追加 war { enabled = true archiveName "${warName}" } task deployLocal(type: Copy) { from "build/libs/${warName}" into "${localTomcatWebapps}" } // △追加 test { useJUnitPlatform() }
- コマンドプロンプトまたはターミナルを起動してサンプルプロジェクト直下に移動、下記コマンドを実行する
gradlew war deployLocal
動作確認
- STSでLoginController.java を開き、止めたい場所の行番号をダブルクリックしてブレイクポイントを設定する。
- STSでプロジェクトを右クリック>Debug>Debug Configuration.. を選択。
Remote Java Application
の新しい構成を追加し、Project
sample
、Host
localhost
、Port
8000
で起動。- http://localhost:8080/sample/login にアクセスし動作確認する。
参考委文献
- Spring Boot をはじめてみるよ(Gradle 編) - Multi Vitamin & Mineral https://hiranoon.hatenablog.com/entry/2015/12/30/160215
- Spring Tool Suite インストールと日本語化 for Windows https://qiita.com/andna0410/items/e9cc07c9e2e34a542245
- Mapper の注入 - mybatis-spring https://mybatis.org/spring/ja/mappers.html
- Spring MVC MyBatis - トッカンソフトウェア https://tokkan.net/spring/mybatisweb.html
- springframework profile機能について - Exception Blend https://exceptionblend.wordpress.com/2013/02/11/springframework-profile/
- Spring Boot でjspにページ遷移ができない - teratail https://teratail.com/questions/50904
- Spring MVC + JSP で検索画面の検索条件やページ情報を引き継ぐ方法@yoshikawaa https://qiita.com/yoshikawaa/items/0079c3a6c41e5b3b1fe3
- Tomcatのリモートデバッグの実行方法 - TECHSCHORE BLOG https://www.techscore.com/blog/2012/12/25/tomcat%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%AE%E5%AE%9F%E8%A1%8C%E6%96%B9%E6%B3%95/
- Eclipseでリモートデバッグする方法 - ラクス エンジニアブログ https://tech-blog.rakus.co.jp/entry/20190930/eclipse
- 第16章 ファイルを取り扱う - Gradle http://gradle.monochromeroad.com/docs/userguide/working_with_files.html