※当サイトの記事には、広告・プロモーションが含まれます。

Spring FrameworkのTag Libraryとは

www.watch.impress.co.jp

⇧ amazing...

Spring FrameworkのTag Libraryとは

調べたところ、

www.javainterviewpoint.com

Since Spring 2.0, Spring provides set of data binding-aware tags for handling form elements when using JSP and Spring Web MVC. Each tag provides support for the set of attributes of its corresponding HTML tag counterpart, making the tags familiar and intuitive to use.

https://www.javainterviewpoint.com/spring-mvc-form-tag-library/

The form tag library is bundled in spring.jar and the descriptor is called spring-form.tld. In order to use the tags in your form we need to include the below taglib in our JSP Page.

https://www.javainterviewpoint.com/spring-mvc-form-tag-library/

⇧ という感じで、JSPJava Server Pages)+ Spring Web MVCで利用するものがメジャーなんですかね?

公式のドキュメントを見ても、

github.com

docs.spring.io

⇧ よく分からんかったけど...

とりあえず、

spring.pleiades.io

JSPJava Server Pages)+ Spring Security用のTag Libraryもあるようで、Spring Frameworkが扱っているTag Libraryの全容が全く見えてこない...

ネットの情報だと、

qiita.com

road-to-tennis.sakura.ne.jp

⇧ 圧倒的に、JSPJava Server Pages)+ Spring Web MVCのTag Libraryの話が多い感じですかね。

で、

spring.pleiades.io

⇧ 残念過ぎるのが、JSTLの<c:foreach>みたいにloop処理が用意されていないというね...

なので、loop処理でフォームの要素を作りたい場合は、

stackoverflow.com

JSTLの<c:foreach>との併用していくしか無さそう..

Spring FrameworkのTag Libraryが何なのか結局はよく分からなかったけど、JSPJava Server Pages)+ Spring Web MVC用のTag Libraryを使ってみる

とりあえず、導入しやすそうなJSPJava Server Pages)+ Spring Web MVC用のTag Libraryを使ってみることに。

利用するプロジェクトは、

ts0818.hatenablog.com

⇧ 上記の記事のものになります。

Spring Web MVCの依存関係にTag Libraryが含まれてるらしいので、Maven使ってる場合は、pom.xmlに、Gradle使ってる場合は、build.gradleにSpring Web MVCの依存関係を追加しとけば良いようです。

一応、pom.xmlを掲載。(Mavenを使ってるので)

<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>com</groupId>
	<artifactId>spring-mvc-jsp</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<maven.compiler.target>${java.version}</maven.compiler.target>
		<maven.compiler.source>${java.version}</maven.compiler.source>
		<org.springframework-version>5.3.24</org.springframework-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- Servlet -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		
		<!-- Database -->
		<!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
		<dependency>
			<groupId>commons-dbutils</groupId>
			<artifactId>commons-dbutils</artifactId>
			<version>1.7</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc11 -->
		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc11</artifactId>
			<version>21.8.0.0</version>
		</dependency>
		
		<!-- Lombok -->
		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.24</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.3.2</version>
				<configuration>
					<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
					<warSourceDirectory>src/main/webapp</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project> 

で、Spring Web MVCでPOSTするデータで日本語が文字化けするのを防ぐために、

confrage.jp

⇧ 上記サイト様にあるように、web.xmlに追記が必要ということで、

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
	id="WebApp_ID" version="4.0">
	<display-name>spring-mvc-jsp</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.jsp</welcome-file>
		<welcome-file>default.htm</welcome-file>
	</welcome-file-list>
	<!-- spring.xml -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/spring.xml</param-value>
	</context-param>

	<!-- Start Spring -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>spring-dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring-dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<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>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>    

⇧ filterの設定を追加します。

 

Spring Web MVCのTag Libraryはform:がメジャーらしいので、フォーム送信を試してみる。

Spring Web MVCのTag Libraryのselect要素には、Java側の変数を設定しないといけないらしいので、まずは、Java側のControllerクラスでフォームに必要な変数を準備することにします。

今回、利用するファイルの配置は以下のような感じ。

■/spring-mvc-jsp/src/main/java/com/dto/FromDto.java

package com.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class FromDto {

	private Integer id;
	private String fromName;

}

■/spring-mvc-jsp/src/main/java/com/dto/GenderDto.java

package com.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class GenderDto {

	private Integer id;
	private String genderName;

}

■/spring-mvc-jsp/src/main/java/com/form/ExampleForm.java

package com.form;

import lombok.Data;

@Data
public class ExampleForm {

	private String lastName;
	private String firstName;
	private String from;
	private String gender;

}

■/spring-mvc-jsp/src/main/java/com/controller/HomeController.java

package com.controller;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.dto.FromDto;
import com.dto.GenderDto;
import com.entity.UserDetail;
import com.entity.ex.ExUserAndAddressDetail;
import com.form.ExampleForm;
import com.service.UserDetailServiceImpl;
import com.service.ex.ExUserAndAddressDetailServiceImpl;

@Controller
@RequestMapping("homeController")
public class HomeController {
	
	@Autowired
	private UserDetailServiceImpl userDetailServiceImpl;

	@Autowired
	private ExUserAndAddressDetailServiceImpl exUserAndAddressDetailServiceImpl;
	
	@ModelAttribute
	public ExampleForm initForm() {
		return new ExampleForm();
	}
	
	@GetMapping("home")
	public String index(Model model) {
		List<String> list = new ArrayList<>();
		list.add("リスト1");
		list.add("リスト2");
		list.add("リスト3");
		model.addAttribute("strList", list);
		return "home/index";
	}
	
	@GetMapping("find-all")
	public ModelAndView findAll() throws SQLException {
		List<UserDetail> userDetailList = userDetailServiceImpl.findAll();
		ModelAndView mv = new ModelAndView("home/index");
		mv.addObject("userDetailList", userDetailList);
		return mv;
	}
	
	@GetMapping("find-all-ex")
	public ModelAndView findAllEx() throws SQLException {
		List<ExUserAndAddressDetail> exUserAndAddressDetailList = exUserAndAddressDetailServiceImpl.findAll();
		ModelAndView mv = new ModelAndView("home/index");
		mv.addObject("exUserAndAddressDetailList", exUserAndAddressDetailList);
		return mv;
	}
	
	@GetMapping("init")
	public ModelAndView initialForm(ExampleForm exampleForm) {
		List<FromDto> fromDtoList = new ArrayList<>();
		fromDtoList.add(new FromDto(1, "北海道"));
		fromDtoList.add(new FromDto(2, "東北"));
		fromDtoList.add(new FromDto(3, "東京"));
		fromDtoList.add(new FromDto(4, "名古屋"));
		fromDtoList.add(new FromDto(5, "京都"));
		fromDtoList.add(new FromDto(6, "大阪"));
		fromDtoList.add(new FromDto(7, "九州"));

		List<GenderDto> genderDtoList = new ArrayList<>();
		genderDtoList.add(new GenderDto(0, "男性"));
		genderDtoList.add(new GenderDto(1, "女性"));
		
		ModelAndView mv = new ModelAndView("home/index");
		mv.addObject("fromDtoList", fromDtoList);
		mv.addObject("genderDtoList", genderDtoList);
		mv.addObject("exampleForm", exampleForm);
		return mv;
	}
	
	@PostMapping("send")
	public ModelAndView send(ExampleForm exampleForm) {
		ModelAndView mv = new ModelAndView("home/index");
		return mv;
	}
}

■/spring-mvc-jsp/src/main/webapp/WEB-INF/views/home/index.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Home</title>
</head>
<body>
	<c:forEach var="str" items="${strList}">
		<p>${str}</p>
	</c:forEach>
	<c:forEach var="userDetail" items="${userDetailList}">
		<p>
			<span>${userDetail.lastName}</span> <span>${userDetail.firstName}
			</span>
		</p>
	</c:forEach>

	<c:if test="${not empty exUserAndAddressDetailList }">
		<table>
			<thead>
				<tr>
					<th>Name</th>
					<th>Gender</th>
					<th>Birthday</th>
					<th>postCode</th>
					<th>Address</th>
				</tr>
			</thead>
			<tbody>
				<c:forEach var="exUserAndAddressDetail"
					items="${exUserAndAddressDetailList}">
					<tr>
						<td><span>${exUserAndAddressDetail.lastName}</span> <span>${exUserAndAddressDetail.firstName}</span>
						</td>
						<td><span>${exUserAndAddressDetail.gender}</span></td>
						<td><span>${exUserAndAddressDetail.birthday}</span></td>
						<td><span>${exUserAndAddressDetail.postCode}</span></td>
						<td><span>${exUserAndAddressDetail.prefecture}</span> <span>${exUserAndAddressDetail.cities}</span>
							<span>${exUserAndAddressDetail.address01}</span></td>
					</tr>
				</c:forEach>
			</tbody>
		</table>
	</c:if>

	<form:form method="post"
		action="${pageContext.request.contextPath}/homeController/send"
		modelAttribute="exampleForm">
		<div>
			<!-- inputタグ -->
			<label>Last Name</label>
			<form:input path="lastName" />
		</div>
		<div>
			<label>first Name</label>
			<form:input path="firstName" />
		</div>
		<div>
			<!-- radiobuttonタグ -->
			<c:forEach items="${genderDtoList}" varStatus="rowStatus"
				var="genderDto">
				<form:radiobutton path="gender" value="${ genderDto.id }"
					label="${ genderDto.genderName }" />
			</c:forEach>
		</div>
		<div>
			<!-- selectタグ -->
			<form:select path="from">
				<form:option value="" label="--未選択--"></form:option>
				<c:forEach items="${fromDtoList}" var="fromDto">
					<form:option value="${fromDto.id}" label="${fromDto.fromName}" />
				</c:forEach>
			</form:select>
		</div>
		<input type="submit" value="send" />
	</form:form>
</body>
</html>

⇧ path属性の値が、Java側で用意したフォーム用のクラスであるExampleForm.javaの各フィールド名と一致させる必要があるっぽいです、多分。

で、EclipseでControllerクラスのファイルでフォームのPOSTを受け取るメソッドにブレークポイントを付けときます。

プロジェクトをTomcatデバッグ起動。

ブラウザで、「http://localhost:8080/[プロジェクト名]/Controllerクラスのメソッドで設定したエンドポイント」にアクセスし、「send」ボタン押下。

Eclipse側で、ブレークポイントを付けた場所で処理が止まるので、フォームで送られてきた値を確認。

⇧ フォームの各要素のvalueの値がJava側に渡ってきているのが確認できました。

結局、Spring Frameworkで用意されているTag Libraryの一覧が全く分からなかったですが、Spring Web MVCでフォームの値を送ることができたようです。

ちなみに、

stackoverflow.com

⇧ 上記サイト様にあるように、Java側で@ModelAttributeでフォームの初期化を行っていると、jsp側でmodelAttributeの値はNULLや空になることはないようです、つまり値の存在チェックが意味をなさない。(なぜなら、リクエストでControllerクラスが呼ばれる度に、毎回modelAttributeの値が初期化されるので絶対にNULLや空になることはないため)

毎度モヤモヤ感が半端ない...

今回はこのへんで。