Spring Frameworkでのデータベース処理

1.データベース接続

Spring JDBCを使用してPostgreSQLにデータベース接続するため、ライブラリの定義を pom.xml に追加します。

  <properties>
     :
    <!-- PostgreSQL version -->
    <postgresql.version>9.4-1206-jdbc42</postgresql.version>
  </properties>
  <dependencies>
     :
    <!-- Spring JDBC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>
    <!-- PostgreSQL -->
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>${postgresql.version}</version>
    </dependency>
     :
  </dependencies>
</project>

続いて、データベースの接続設定を spring-mvc.xml に定義します。
データベースの接続パラメータは環境依存する情報のため、外部ファイルに定義し、その変数値をDB接続設定として定義します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     :
  <!-- DB設定(環境依存の外部化) -->
  <context:property-placeholder location="classpath:config/database.properties"/>

  <!-- DB接続設定 -->
  <bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>
</beans>

データベース構築時に設定した情報を外部ファイル(database.properties)へ定義します。

jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/studydb
jdbc.username=study
jdbc.password=xxxxxx

2.コネクションプーリング

コネクションプーリングを使用するには、Commons DBCP2などを使用して実装します。必要なライブラリを pom.xml に定義します。

  <properties>
     :
    <!-- Commons DBCP2 version -->
    <commons-dbcp2.version>2.1.1</commons-dbcp2.version>
  </properties>
  <dependencies>
     :
    <!-- Commons DBCP2 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>${commons-dbcp2.version}</version>
    </dependency>
  </dependencies>
</project>

spring-mvc.xml 定義したデータベース接続設定で使用するDataSourceをCommons DBCP2のクラスに変更します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     :
  <!-- DB設定(環境依存の外部化) -->
  <context:property-placeholder location="classpath:config/database.properties"/>

  <!-- DB接続設定 -->
  <bean id="dataSource"
      class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="maxTotal" value="${jdbc.maxTotal}" />
  </bean>
</beans>

外部ファイルに最大コネクションプール数を設定します。

jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/studydb
jdbc.username=study
jdbc.password=xxxxxx
jdbc.maxTotal=10

3.O/Rマッピング

O/RマッパーとしてMyBatisを使用するため、pom.xmlに必要なライブラリの定義を行います。

  <properties>
     :
    <!-- MyBatis version -->
    <mybatis.version>3.5.6</mybatis.version>
    <!-- MyBatis Spring version -->
    <mybatis-spring.version>2.0.0</mybatis-spring.version>
  </properties>
  <dependencies>
     :
    <!-- MyBatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis-spring.version}</version>
    </dependency>
</project>

MyBatisの設定を spring-mvc.xml に定義します。定義する内容は以下の通りです。

  • XMLのスキーマ情報
  • SQLを定義するXMLファイルのパス
  • アンダースコア区切りのテーブル定義からキャメル形式に変換するかどうかの設定
  • Mapperクラスをスキャンするパッケージの設定
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     :
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
     :
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
     :
  <!-- MyBatis マッピング設定 -->
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" value="classpath*:config/mappers/**/*.xml" />
    <property name="configuration">
      <bean class="org.apache.ibatis.session.Configuration">
        <property name="mapUnderscoreToCamelCase" value="true" />
      </bean>
    </property>
  </bean>

  <!-- Mapperクラススキャン対象パッケージ -->
  <mybatis:scan base-package="org.miyadai.app.study.mapper" />
</beans>

エンティティ(テーブル)ごとのSQLをXMLに定義します。XMLはspring-mvc.xmlに定義したパス(例:src/main/resources/config/mappers/)配下にテーブル名.xmlで作成します(テーブル名ITEMの場合、item.xml)。

namespaceにはMapperクラス、resultTypeにはEntityクラスを指定します。
SELECT、INSERT、UPDATE、DELETEのSQLを必要に応じて定義します。
#{xxxxXxxx}の部分はEntityのプロパティ名を設定します。

<?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.miyadai.app.study.mapper.ItemMapper">
  <select id="findAll" resultType="org.miyadai.app.study.entity.Item">
    select ITEM_CODE, ITEM_NAME, NOTE, ITEM_TYPE, LOT_MNG, VALID_FLG, INS_DATE, INS_USER, UPD_DATE, UPD_USER from ITEM
  </select>
  <select id="findOne" resultType="org.miyadai.app.study.entity.Item">
    select ITEM_CODE, ITEM_NAME, NOTE, ITEM_TYPE, LOT_MNG, VALID_FLG, INS_DATE, INS_USER, UPD_DATE, UPD_USER from ITEM where ITEM_CODE = #{itemCode}
  </select>
  <insert id="save">
    insert into ITEM (ITEM_CODE, ITEM_NAME, NOTE, ITEM_TYPE, LOT_MNG, VALID_FLG, INS_DATE, INS_USER, UPD_DATE, UPD_USER)
      values (#{itemCode}, #{itemName}, #{note}, #{itemType}, #{lotMng}, #{validFlg}, #{insDate}, #{insUser}, #{updDate}, #{updUser})
  </insert>
  <update id="update">
    update ITEM set ITEM_CODE = #{itemCode}, ITEM_NAME = #{itemName}, NOTE = #{note}, ITEM_TYPE = #{itemType}, LOT_MNG = #{lotMng}, VALID_FLG = #{validFlg}, INS_DATE = #{insDate}, INS_USER = #{insUser}, UPD_DATE = #{updDate}, UPD_USER = #{updUser} where ITEM_CODE = #{itemCode}
  </update>
  <delete id="delete">
    delete from ITEM where ITEM_CODE = #{itemCode}
  </delete>
</mapper>

Entityクラスを作成します。
Entityクラスはテーブル定義に沿ってフィールとおよびGetterメソッド、Setterメソッドを定義します。

public class Item {

	/* 品目コード. */
	String itemCode;

	/* 品目名. */
	String itemName;
     :
	/**
	 * 品目コードを取得します.
	 * @return 品目コード
	 */
	public String getItemCode() {
		return itemCode;
	}

	/**
	 * 品目コードを設定します.
	 * @param itemCode 品目コード
	 */
	public void setItemCode(String itemCode) {
		this.itemCode = itemCode;
	}
     :
}

Mapperインターフェースを作成します。
Mapperインタフェースには@Mapperアノテーションを付加します。
SQLを定義したXMLに沿ってメソッドを定義します。

@Mapper
public interface ItemMapper {

	List<Item> findAll();

	Item findOne(String itemCode);

	void save(Item item);

	void update(Item item);

	void delete(Item item);
}

Serviceクラス(ビジネスロジックを実装するクラス)を作成します。
Serviceクラスには@Serviceアノテーションを付加します。
MapperクラスをDIし、各業務処理内でMappertクラスの処理を実行します。

@Service
public class ItemService {

	@Autowired
	private ItemMapper itemMapper;

	public List<Item> findAll() {
		return itemMapper.findAll();
	}

	public Item findAll(String itemCode) {
		return itemMapper.findOne(itemCode);
	}

	public void save(Item item) {
		itemMapper.save(item);
	}

	public void update(Item item) {
		itemMapper.update(item);
	}

	public void delete(Item item) {
		itemMapper.delete(item);
	}
}

4.トランザクション制御

ビジネスロジックごとにトランザクション制御を自動で行うため、アノテーションおよびAOPでの制御を行います。Spring Aspectsを使用するため、pom.xmlにライブラリを定義します。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     :
  <dependencies>
     :
    <!-- Spring Aspects -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring-framework.version}</version>
    </dependency>
  </dependencies>
</project>

アノテーションおよびAOPでのトランザクション制御を行う設定を spring-mvc.xmlに定義します。定義する内容は以下の通りです。

  • XMLのスキーマ情報にAOPとTX(Transaction)の定義を追加
  • アノテーションで制御する旨の宣言
  • AOPでServiceクラスのどのメソッドがトランザクション対象か定義
  • AOPでどのクラスがトランザクション制御対象かPointcutで定義
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     :
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
     :
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
     :
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
     :
  <!-- アノテーションでトランザクションを制御 -->
  <tx:annotation-driven />
  <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <!-- AOPでトランザクションを制御 -->
  <tx:advice id="txAdv" transaction-manager="transactionManager">
    <tx:attributes>
      <tx:method name="save*" />
      <tx:method name="update*" />
      <tx:method name="delete*" />
    </tx:attributes>
  </tx:advice>
  <aop:config>
    <aop:advisor advice-ref="txAdv" pointcut="execution(* org.miyadai.app.study.service.*Service.*(..))" />
  </aop:config>
     :
</beans>

Serviceクラスの対象メソッドに@Transactionalアノテーションを付加します。AOPと併用し、AOPの対象となっている場合はアノテーションは不要です。

@Service
public class ItemService {

	@Autowired
	private ItemMapper itemMapper;

	public List<Item> findAll() {
		return itemMapper.findAll();
	}

	public Item findAll(String itemCode) {
		return itemMapper.findOne(itemCode);
	}

	@Transactional
	public void save(Item item) {
		itemMapper.save(item);
	}

	public void update(Item item) {
		itemMapper.update(item);
	}

	public void delete(Item item) {
		itemMapper.delete(item);
	}
}

Spring Frameworkでの画面開発基礎

1.画面遷移(GET、POST)

Springでの画面遷移は、Controllerのメソッドに@RequestMappingを設定します。フォーム送信時のGET/POSTはアノテーションのパラメータで指定します。

@Controller
public class HogeController {

	@RequestMapping(value = "/hoge/input", method = RequestMethod.GET)
	public String input(Model model) {
		return "hoge/input";
	}

	@RequestMapping(value = "/hoge/confirm", method = RequestMethod.POST)
	public String confirm(Model model) {
		return "hoge/confirm";
	}
}

ThymeleafでのURL指定例は以下の通りです。

<a th:href="@{/hoge/input}">
<form th:action="@{/hoge/confirm}" method="post">

2.パラメータの受け渡し(フォーム)

画面間のパラメータ受け渡しは、アクションフォームを介して行います。

アクションフォームを作成し、フィールドを追加します。Thymeleafの仕様により、getter/setterは必須となります。

public class HogeForm implements Serializable {

	private String hogeName;

	public String getHogeName() {
		return hogeName;
	}

	public void setHogeName(String hogeName) {
		this.hogeName = hogeName;
	}
}

メソッドの引数にアクションフォームを追加します。アクションフォームには@ModelAttributeを設定します。

@Controller
public class HogeController {

	@RequestMapping(value = "/hoge/input", method = RequestMethod.GET)
	public String input(@ModelAttribute HogeForm form, Model model) {
		return "hoge/input";
	}

	@RequestMapping(value = "/hoge/confirm", method = RequestMethod.POST)
	public String confirm(@ModelAttribute HogeForm form, Model model) {
		return "hoge/confirm";
	}
}

3.入力チェック(バリデーション)

SpringでのバリデーションはBean Validationを使用して実装するのが一般的です。

まずはBean ValidationおよびHibernate Validatorを使用するため、pom.xmlに定義を追加します。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.miyadai.app</groupId>
  <artifactId>study-spring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
            :
    <!-- Bean Validation API version -->
    <validation-api.version>2.0.1.Final</validation-api.version>
    <!-- Hibernate Validator version -->
    <hibernate-validator.version>5.3.4.Final</hibernate-validator.version>
            :
  </properties>
  <dependencies>
            :
    <!-- Bean Validation API -->
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>${validation-api.version}</version>
    </dependency>
    <!-- Hibernate Validator -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>${hibernate-validator.version}</version>
    </dependency>
            :
  </dependencies>
</project>

アクションフォームの各フィールドにアノテーションを設定することでチェックを追加します。

public class HogeForm implements Serializable {

	@NotBlank
	@Size(min = 1, max = 256)
	private String hogeName;

	public String getHogeName() {
		return hogeName;
	}

	public void setHogeName(String hogeName) {
		this.hogeName = hogeName;
	}
}

コントローラのメソッド引数のアクションフォームに@Validatedを設定し、さらにチェック結果を取得するための引数を追加します。また、チェック結果を判定し、表示する画面を切り替えるなどの処理を追加します。

@Controller
public class HogeController {

	@RequestMapping(value = "/hoge/input", method = RequestMethod.GET)
	public String input(@ModelAttribute HogeForm form, Model model) {
		return "hoge/input";
	}

	@RequestMapping(value = "/hoge/confirm", method = RequestMethod.POST)
	public String confirm(
			@ModelAttribute @Validated HogeForm form, BindingResult result, Model model) {

		if (result.hasErrors()) {
			return input(form, model);
		}

		return "hoge/confirm";
	}
}

HTML(Thymeleaf)ではエラーメッセージを表示させる処理を記述します。

<form th:action="@{/hoge/confirm}" th:object="${hogeForm}" method="post">
    <input type="text" th:field="*{hogeName}">
    <p th:if="${#fields.hasErrors('hogeName')}" th:errors="*{hogeName}"></p>
</form>

メッセージを日本語化及びカスタマイズするため、WebMvcで使用するバリデータをオーバーライドします。

@Configuration
@EnableWebMvc
public class AppConfig implements WebMvcConfigurer {

	@Bean
	public MessageSource messageSource() {
		ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
		// ValidationMessage.propertiesを使用
		messageSource.setBasename("classpath:ValidationMessages");
		// メッセージプロパティの文字コードを指定
		messageSource.setDefaultEncoding("UTF-8");
		return messageSource;
	}

	@Bean
	public LocalValidatorFactoryBean validator() {
		LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
		localValidatorFactoryBean.setValidationMessageSource(messageSource());
		return localValidatorFactoryBean;
	}

	@Override
	public Validator getValidator() {
		return validator();
	}
}

hibernate-validator-x.x.x.Final.jar内に含まれるValidationMessages.propertiesを取り出し、src/main/resources配下にコピーします。

メッセージを適宜日本語化し、メッセージに埋め込むフィールド名も定義します。メッセージ内の{0}の部分にフィールド名を差し込むことができます。

# Message.

javax.validation.constraints.AssertFalse.message = must be false
javax.validation.constraints.AssertTrue.message  = must be true
javax.validation.constraints.DecimalMax.message  = must be less than ${inclusive == true ? 'or equal to ' : ''}{value}
javax.validation.constraints.DecimalMin.message  = must be greater than ${inclusive == true ? 'or equal to ' : ''}{value}
javax.validation.constraints.Digits.message      = numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Future.message      = must be in the future
javax.validation.constraints.Max.message         = must be less than or equal to {value}
javax.validation.constraints.Min.message         = must be greater than or equal to {value}
javax.validation.constraints.NotNull.message     = may not be null
javax.validation.constraints.Null.message        = must be null
javax.validation.constraints.Past.message        = must be in the past
javax.validation.constraints.Pattern.message     = {0}には不正な値が設定されています。
javax.validation.constraints.Size.message        = {0}は{min}文字以上、{max}文字以内で入力してください。

org.hibernate.validator.constraints.CreditCardNumber.message        = invalid credit card number
org.hibernate.validator.constraints.EAN.message                   = invalid {type} barcode
org.hibernate.validator.constraints.Email.message                   = not a well-formed email address
org.hibernate.validator.constraints.Length.message                  = length must be between {min} and {max}
org.hibernate.validator.constraints.LuhnCheck.message               = The check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed
org.hibernate.validator.constraints.Mod10Check.message              = The check digit for ${validatedValue} is invalid, Modulo 10 checksum failed
org.hibernate.validator.constraints.Mod11Check.message              = The check digit for ${validatedValue} is invalid, Modulo 11 checksum failed
org.hibernate.validator.constraints.ModCheck.message                = The check digit for ${validatedValue} is invalid, ${modType} checksum failed
org.hibernate.validator.constraints.NotBlank.message                = {0}を入力してください。
org.hibernate.validator.constraints.NotEmpty.message                = {0}を入力してください。
org.hibernate.validator.constraints.ParametersScriptAssert.message  = script expression "{script}" didn't evaluate to true
org.hibernate.validator.constraints.Range.message                   = must be between {min} and {max}
org.hibernate.validator.constraints.SafeHtml.message                = may have unsafe html content
org.hibernate.validator.constraints.ScriptAssert.message            = script expression "{script}" didn't evaluate to true
org.hibernate.validator.constraints.URL.message                     = must be a valid URL

org.hibernate.validator.constraints.br.CNPJ.message                 = invalid Brazilian corporate taxpayer registry number (CNPJ)
org.hibernate.validator.constraints.br.CPF.message                  = invalid Brazilian individual taxpayer registry number (CPF)
org.hibernate.validator.constraints.br.TituloEleitoral.message      = invalid Brazilian Voter ID card number

# Field Name.
hogeName=ほげ名

4.例外処理(エラー画面制御)

Webシステムで予期せぬエラーが発生した場合、デフォルトのエラー画面ではセキュリティ上脆弱となるため、エラー画面はカスタマイズする必要があります。

デフォルトのエラー画面では、アプリケーションサーバのバージョンが表示されているケースがあり、攻撃者はこのバージョンのアプリケーションサーバの脆弱性をついて攻撃することができてしまいます。

web.xmlのエラーページ設定でエラー時のURLを定義し、URLに応じたページを用意することでエラー画面をカスタマイズすることが可能です。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
        :
  <error-page>
    <location>/errors</location>
  </error-page>
</web-app>

コントローラではエラー時のURLに沿ったRequestMappingを設定します。

@Controller
public class ErrorController {

	@RequestMapping(value = "errors", method = RequestMethod.GET)
	public String renderErrorPage() {
		return "error";
	}
}

エラー画面用のHTML(Thymeleaf)を用意します。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <title>エラー</title>
  </head>
  <body>
    <h1>エラー</h1>
    <h3>予期せぬエラーが発生しました。</h3>
    <p>しばらく経ってから再度アクセスしてください。<br>
    問題が解消しない場合は、管理者までご連絡ください。</p>
    <a th:href="@{/}">トップへ戻る</a>
  </body>
</html>

Spring Frameworkの環境構築

1.はじめに

以下の通り、開発環境を構築します(まずは★の部分のみ構築します)。

  • OS:Windows10 Home 64bit
  • Pleiades All in One Eclipse 2020-12 (4.18.0) ★
    • OpenJDK
    • Tomcat 9.0.41
    • Maven 3.6
  • Spring ★
    • Spring Framework 5.2.4.RELEASE
    • Spring WebMVC 5.2.4.RELEASE
  • View Engine ★
    • Thymeleaf 3.0.11.RELEASE
  • Database
    • PostgreSQL
    • MyBatis
  • Logging
    • Logback
  • Test
    • JUnit

2.Eclipseのインストール

Pleiades 日本語プラグインのサイト(https://mergedoc.osdn.jp/)にアクセスし、Pleiades All in Oneをダウンロードします。

(1) サイトにアクセスしたら「Eclipse 2020」をクリックします。

(2) Windows 64bitのJava、Full Editionをクリックします。

(3) ダウンロードしたzipファイルを任意の場所に解凍します。

3.mavenプロジェクトの作成

(1) Eclipseを起動し、メニューから「ファイル」→「新規」→「Maven プロジェクト」を選択します。

(2) 新規 Maven プロジェクトダイアログで「シンプルなプロジェクトの作成」をチェックし、次へボタンをクリックします。

(3) グループId(Javaパッケージ)、アーティファクトId(プロジェクト名)を入力し、完了ボタンをクリックします。

4.pom.xmlの編集

(1) pom.xmlを開き、ソースのエンコーディング、コンパイルJavaバージョンを指定します。各ライブラリのバージョンも定義しておきます。

<properties>
  <!-- Generic properties -->
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>11</maven.compiler.source>
  <maven.compiler.target>11</maven.compiler.target>
  <!-- Servlet version -->
  <servlet.version>4.0.1</servlet.version>
  <!-- Spring framework version -->
  <spring-framework.version>5.2.4.RELEASE</spring-framework.version>
  <!-- Thymeleaf -->
  <thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
</properties>

(2) 続いて、Spring MVCに必要なJarファイルの依存関係をdependenciesディレクティブの中に定義します。

<dependencies>
  <!-- Servlet -->
  <dependency>
    <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <!-- コンパイル時のみ依存 -->
      <!-- 実行時はTomcatライブラリを使用するため -->
      <scope>provided</scope>
  </dependency>
  <!-- Spring MVC -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring-framework.version}</version>
  </dependency>
</dependencies>

(3) 次に、Thymeleafに必要なJarファイルの依存関係をdependenciesディレクティブの中に定義します。

<!-- Thymeleaf -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>${thymeleaf.version}</version>
</dependency>
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>${thymeleaf.version}</version>
</dependency>

(4) pom.xmlの編集か完了したら、変更を保存し、プロジェクトの上で右クリック、「Maven」→「プロジェクトの更新」をクリックします。

(5) Maven プロジェクトの更新ダイアログが表示されたらOKボタンをクリックします。

(6) Maven 依存関係に定義したSpring MVC関連のライブラリが追加されます。

5.HelloWorldプログラムの作成

5-1.Bean定義ファイルの作成

(1) src/main/resourcesフォルダ配下にconfigフォルダを作成し、「spring.xml」を作成します。

(2) spring.xmlにビジネスロジックのBean定義を記述します。
※HelloWorldプログラムではビジネスロジックは不要なので、空の定義にします。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
</beans>

(3) configフォルダ配下に「spring-mvc.xml」を作成します。

(4) spring-mvc.xmlにプレゼンテーション層のBean定義を記述します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
  <!-- Spring MVCの使用を宣言 -->
  <mvc:annotation-driven />
  <!-- Beanクラスが格納されるパッケージのルートを宣言 -->
  <context:component-scan base-package="org.miyadai.app.common" />
  <context:component-scan base-package="org.miyadai.app.study" />
</beans>

5-2.コントローラの作成

(1) src/main/javaフォルダ配下にパッケージ「org.miyadai.app.study.controller」を作成します。

(2) 作成したパッケージ配下に「TopController.java」を作成します。

package org.miyadai.app.study.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class TopController {
  @RequestMapping(value = "/", method = RequestMethod.GET)
  public ModelAndView top(ModelAndView model) {
    model.setViewName("top");
    model.addObject("message", "Hello World!!");
    return model;
  }
}

5-3.ビューの作成

(1) パッケージ「org.miyadai.app.common.config」を作成し、作成したパッケージ配下に「ThymeleafConfig.java」を作成します。

package org.miyadai.app.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
@Configuration
public class ThymeleafConfig {
  @Bean
  public ITemplateResolver templateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setPrefix("/WEB-INF/view/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode("HTML");
    resolver.setCharacterEncoding("UTF-8");
    return resolver;
  }
  @Bean
  public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine templateEngine = new SpringTemplateEngine();
    templateEngine.setTemplateResolver(templateResolver());
    return templateEngine;
  }
  @Bean
  public ViewResolver viewResolver() {
    ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
    thymeleafViewResolver.setTemplateEngine(templateEngine());
    thymeleafViewResolver.setCharacterEncoding("UTF-8");
    return thymeleafViewResolver;
  }
}

(2) プロジェクトフォルダ直下に「WebContent/WEB-INF/view」というフォルダを作成します。

(3) 作成したフォルダ配下に「top.html」を作成します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8">
    <title>Spring サンプル</title>
  </head>
  <body>
    <span th:text="${message}"></span>
  </body>
</html>

5-4.web.xmlの作成

(1) WebContent/WEB-INFフォルダ配下に「web.xml」を作成します。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
</web-app>

(2) web.xmlにビジネスロジックのBean定義ファイルの定義を追加します。

<!-- ビジネスロジックのBean定義ファイル -->
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:/config/spring.xml</param-value>
</context-param>

(3) web.xmlにリスナーの定義を追加します。

<!-- リスナーを登録 -->
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

(4) web.xmlにエンコーディングフィルタの定義を追加します。

<!-- エンコーディングフィルタ  -->
<filter>
  <filter-name>characterEncodingFilter</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>characterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

(5) web.xmlにSpring MVCで処理をするためのディスパッチャーサーブレットの定義を追加します。

<!-- ディスパッチャーサーブレット -->
<servlet>
  <servlet-name>dispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <!-- Spring MVCのBean定義ファイル -->
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:/config/spring-mvc.xml</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>dispatcherServlet</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

5-5.Webサービスの起動

(1) Eclipseにサーバービューを表示させます。「ウィンドウ」→「ビューの表示」→「その他」をクリックしてください。

(2) ビューの表示ダイアログで「サーバー」→「サーバー」を選択し、開くボタンをクリックします。

(3) サーバーウィンドウの上で右クリックし、「新規」→「サーバー」を選択してください。

(4) 新規サーバーの定義ダイアログが表示されたら、「Tomcat v9.0 サーバー」を選択し、完了ボタンをクリックします。

(5) プロジェクトの上で右クリックし、プロパティを選択します。

(6) プロジェクト・ファセットを選択し、「ファセット・フォームへ変換…」をクリックします。

(7) 「動的 Web モジュール」をチェックし、適用して閉じるボタンをクリックします。

(8) サーバーウィンドウの追加したサーバーの上で右クリックし、「追加および除去」をクリックします。

(9) 追加および除去ダイアログが表示されたら、アプリケーションを構成済みに追加し、完了ボタンをクリックします。

(10) プロジェクトの上で右クリックし、プロパティを選択します。

(11) デプロイメント・アセンブリーを選択し、追加ボタンをクリックします。

(12) ディレクティブ・タイプの選択ダイアログが表示されたら、「Java ビルド・パス・エントリー」を選択し、次へボタンをクリックします。

(13) Java ビルド・パス・エントリーダイアログが表示されたら、「Maven 依存関係」を選択し、完了ボタンをクリックします。

(14) サーバーウィンドウの追加したサーバーの上で右クリックし、「開始」をクリックします。

(15) サーバー起動途中でファイアウォールの警告が出たらアクセスを許可するボタンをクリックします。

(16) サーバーが起動したら、ブラウザから「http://localhost:8080/study/」にアクセスします。Hello World画面が出たら成功です。