山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

【Spring MVC】簡単なアンケートアプリで学習する。

Spring MVC でいろいろ勉強していきたいので、ベースとなるアプリを作った。

一応動くが、まだ実装は不十分である。今後、少しずつ不足している箇所を実装していきたい。

アプリの動き

3 画面でできている。

トップ画面はアンケートの入力画面。

f:id:yyama1556:20160910145136p:plain

ユーザに「年齢」と「知ったきっかけ」を入力してもらう。以降「入力画面」と呼ぶ。

「確認画面へ」ボタンをクリックすると、入力内容が確認できる画面に遷移する。

f:id:yyama1556:20160910145501p:plain

ユーザは自分が入力した内容を確認し、「完了画面へ」ボタンを押下する。「入力画面へ戻る」ボタンはまだ実装していない。今はブラウザの戻るボタンで戻ってもらうしかない。これくらいの小さなアプリではあまり気にすることはないが、一般的なWEBアプリでは戻るボタンを使用した操作をすべての画面で想定することはほぼ不可能である(操作パターンが多くなりすぎるため)。ちゃんと「戻る」ボタンを実装しておくのがセオリーだ。

この画面を以降「確認画面」と呼ぶ。

完了画面ではお礼のメッセージと入力画面に戻るリンクを提供している。

f:id:yyama1556:20160910150244p:plain

以降「完了画面」と呼ぶ。

フォルダ構成

フォルダ構成は次のとおり。

f:id:yyama1556:20160910150424p:plain

次の記事を参考にして Eclipse で Spring MVC プロジェクトを作成し、いくつかのファイルを追加する。

yyama1556.hateblo.jp

ルートパス"/"で入力画面に遷移できるように、コンテキストルートを修正した。

プロジェクトを右クリックして「Properties」を選択し、「Web Project Settings」の「Context root」を"/"に修正する。

f:id:yyama1556:20160910151331p:plain

各ファイルの内容

SampleController は自作のコントローラである。

package org.yyama.sample.cntrl;

import static org.springframework.web.bind.annotation.RequestMethod.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.yyama.sample.form.UserForm;

@Controller
public class SampleController {

	@RequestMapping(value = "/", method = GET)
	public String input(UserForm userForm, Model model) {
		model.addAttribute("ageList", getAgeList());
		model.addAttribute("triggerMap", getTriggerCheckbox());
		return "input";
	}

	@RequestMapping(value = "/confirm", method = POST)
	public String confirm(UserForm userForm) {
		return "confirm";
	}

	@RequestMapping(value = "/send", method = POST)
	public String send() {
		return "completion";
	}

	/**
	 * 年齢セレクトボックス用のリストを作成し返す
	 */
	private List<Integer> getAgeList() {
		List<Integer> list = new ArrayList<>();
		for (int i = 18; i < 100; i++) {
			list.add(i);
		}
		return list;
	}

	/**
	 * きっかけチェックボックス用のマップを作成し返す。
	 */
	private Map<Integer, String> getTriggerCheckbox() {
		Map<Integer, String> map = new HashMap<>();
		map.put(1, "チラシを見て");
		map.put(2, "CM を見て");
		map.put(3, "友人に進められて");
		map.put(4, "ググったら出たから");
		map.put(5, "その他");
		return map;
	}

}

@RequestMapping がついているメソッドでリクエストを受け付ける。詳細は次の記事を参照して欲しい。

yyama1556.hateblo.jp

UserForm はユーザが入力した内容を保持するためのフォームクラスだ。これも自作。

package org.yyama.sample.form;

public class UserForm {

	/** 年齢 */
	private String age;

	/** サイトを知ったきっかけ */
	private String[] trigger;

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String[] getTrigger() {
		return trigger;
	}

	public void setTrigger(String[] trigger) {
		this.trigger = trigger;
	}
}

次に JSP 3種類を紹介する。難しいことはしていないので、不明な記述があったら Google で調べればすぐに出てくるだろう。

入力画面の input.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
td, th {
	padding: 20px;
}
</style>
<title>入力画面</title>
</head>
<body>
	<h1>サンプルアンケート</h1>
	<form:form action="confirm" modelAttribute="userForm">
		<table cellpadding="3">
			<tr>
				<th valign="top" align="right">年齢:</th>
				<td><form:select path="age" items="${ageList}" /></td>
			</tr>
			<tr>
				<th valign="top" align="right">知ったきっかけ(複数選択可):</th>
				<td><form:checkboxes path="trigger" items="${triggerMap}"
						delimiter="<br />" /></td>
			</tr>
			<tr >
				<td colspan="2" align="center"><input type="submit" value="確認画面へ" /></td>
			</tr>
		</table>
		<p></p>
	</form:form>
</body>
</html>

確認画面の confirm.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
td, th {
	padding: 20px;
}
</style>
<title>確認画面</title>
</head>
<body>
	<h1>サンプルアンケート</h1>
	<form:form action="/send" modelAttribute="userForm">
		<table cellpadding="3">
			<tr>
				<th valign="top" align="right">年齢:</th>
				<td><c:out value="${userForm.age}" /></td>
			</tr>
			<tr>
				<th valign="top" align="right">知ったきっかけ(複数選択可):</th>
				<td>
				<c:forEach items="${userForm.trigger}" var="t">
				<c:out value="${t}" /><br />
				</c:forEach>
			</tr>
			<tr >
				<td colspan="2" align="center"><input type="submit" value="完了画面へ" /></td>
			</tr>
		</table>
		<p></p>
	</form:form>
</body>
</html>

完了画面の completion.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>完了画面</title>
</head>
<body>
	<h1>ご協力ありがとうございました。</h1>
</body>
<a href="/">top画面へ</a>
</html>

servlet-context.xml はデフォルトのものを使用するが、わかりやすくコメントを変更した。

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

	<!-- アノテーションでBeanを定義する -->
	<annotation-driven />

	<!-- org.yyama.sample パッケージ配下で Spring のアノテーション( @Controller など )が 、-->
	<!-- 付けられたクラスを Bean 定義する -->
	<context:component-scan base-package="org.yyama.sample" />
	
	<!-- jspの設定 -->
	<beans:bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

</beans:beans>

そのほか、 log4j.xml 、 root-context.xml 、 web.xmlEclipse でプロジェクトを作成したときのまま修正していない。

最後に、pom.xml 。ライブラリのバージョンだけを変更している。

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.yyama</groupId>
	<artifactId>sample</artifactId>
	<name>Sample</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>4.3.2.RELEASE</org.springframework-version>
		<org.aspectj-version>1.8.9</org.aspectj-version>
		<org.slf4j-version>1.7.21</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

私の説明不足などで動かない場合、コメントしていただけると大変ありがたい。

今日はここまで。


Spring 関連記事へのリンク集つくりました。