はじめに
今更感強いタイトルですが、基本から押さえたかったので・・・。
Eclipseでmavenを使ったWebアプリケーションを構築するときにやったことをまとめてみました。大まかには、
①Eclipseでmavenプロジェクトの作成
↓
②Webアプリケーションサーバの設定(Tomcat)
↓
③jstlを使用してjspを記述
↓
④EL式を使ってjspを記述
↓
⑤画像やcssをjspに適用
という流れです。
①~⑤までを一つの記事でまとめているものは見つからなかったので書いてみました。
(①~⑤それぞれ独立して記載している記事が多く、一連の流れで書いているような記事を見かけなかった)
やったこと
Eclipseでmavenプロジェクトの作成
まずはEclpse上でプロジェクトを作成します。
Eclipseのファイル→New→projectを選択。
Maven Projectを選択してNext
特に何も変更せずに次へ
以下のArchetypeを選択して次へ
Group Id:org.apache.maven.archetypes
Artifact Id:maven-archetype-webapp
Group IdとArtifact Idに任意の名前を入力してNext
以下のようなプロジェクトが作られるが、コンパイルエラーが発生しているので直していく。
修正点①:src/main/java, src/test/javaフォルダの作成
プロジェクトのプロパティを見ると、src/main/java, src/test/javaが見つからないといわれているのでフォルダを作っていく。
普通にEclipseを右クリックして、src/main/java, src/test/javaフォルダを作る。
修正点②:pomの修正
The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
と言われているので、pomの<dependencies>
に以下を追記する。
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
※上記をコピペしてもいいですが、pom.xmlに記載すべき内容はMaven Central Repositoryから探してください。javax.servlet-apiならこちらに書いています。
pom.xmlの記述を追加したら、プロジェクト上で右クリックしてMaven→Update Projectを選択(Alt+F5でも可)
対象プロジェクトにチェックが入っていることを確認してOKボタンを押下
最後に、コンパイルエラーの原因とは関係ないが、JDKのバージョンを指定します。
mavenはデフォルトでJDKのバージョン1.5でコンパイルされるので、バージョンを明示的に指定する必要があります。
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
※こちらの記事もご参照ください
参考
[Eclipse/Tomcat] MavenのwebappプロジェクトでServlet+JSP
Webアプリケーションサーバの設定(Tomcat)
インストール
Tomcatをインストールし、Eclipseと連携します。
インストールに当たっては参考になる記事が大量にあるので詳細はそちらに委ねます。以下の記事が参考になると思います。
- Eclipse+Tomcat連携
- TomcatでHelloWorld
- Apache Tomcat
- eclipseにtomcatのプラグインを適用できない場合の対処
- Eclipseでwarファイルを作成し、Tomcatにデプロイする手順
Tomcat起動
対象のプロジェクトを選択し、Addボタンを押下。対象プロジェクトが右に移動することを確認。
http://127.0.0.1:8080/[プロジェクト名]/
をブラウザに入力し、Hello World!(index.jspの内容)が表示されることを確認する。
jstlを使用してjspを記述
Hello WorldだけだとWebアプリケーションとしては面白くない。折角Tomcatを使ってるんだし、サーブレットコンテナの機能を活用したものを作りたい。
というわけで、jstl (JavaServer Pages Standard Tag Library) を使ってjspを書いてみたいと思います。
jstlとは、一般によく利用されるカスタムタグをまとめ、Apache Taglibs Project (旧Jakarta Taglibs Project)が配布しているものです。
jspはスクリプトレットを使うことでJavaのコードを埋め込むことができます。しかし、あまり複雑なロジックをjspに埋め込むと可読性・保守性が悪くなってしまいます。このため、jspはjstlを使って記述するのがお勧めです。
jstlを使用できるようにするため、まずはtaglibsとjstlをpom.xmlに追加します。
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
※上記をコピペしてもいいですが、pom.xmlに記載すべき内容はMaven Central Repositoryから探してください。jstlならこちら、taglibs-standard-implならこちらに書いています。
Eclipseのmaven→プロジェクトの更新を押下。
jspの先頭(pageディレクティブ)に以下記述を追加します。
(全種類のjstlを書きましたが、使用するものだけ記載すればOKです)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
各タグで何ができるかはこのサイトがよくまとまっていると思います。
公式のリファレンスはこちら
jspにこの宣言をすることで、prefixで指定した文字を使用してjstlをjspに記述できるようになります。
具体的にはこんな感じ。CoreタグのforEachを使用した例です。
forEachのリファレンスはこちら
<%@ page language="java" contentType="text/html;charset=Windows-31J"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html><body>
<c:forEach begin="0" end="10">
こんにちは!<br>
</c:forEach>
</body></html>
0~10の11回「こんにちは!」が表示されます。
これを呼び出すServletはこんな感じ。
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/JspTest")
public class JspTest extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// WEB-INFからjspへのパスを文字列で指定
String path = "/WEB-INF/jsp/jsptest.jsp";
RequestDispatcher disp = request.getRequestDispatcher(path);
disp.forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Tomcatを起動してhttp://localhost:8080/[プロジェクト名]/JspTest
をブラウザのURLに入力するとこうなります。
※URLの「JspTest」は上記Servlet (JspTest.java) の先頭に記述しているアノテーション:@WebServlet("/JspTest")
から来ています。
うん。ちょっと狂気を感じますね。
jstl参考
- 忘れっぽいエンジニアのJakarta Strutsリファレンス
- JavaServer Pages Standard Tag Library 1.1 Tag Reference
- JSTL coreタグライブラリの利用
- JSTLの再入門
EL式を使ってjspを記述
次はEL式です。EL式とは、Expression Languageの略です。
jspをより簡単に書くためにJSP2.0より導入されており、jsp上で使用することができます。
EL式を使えば、jsp上に計算を埋め込んだり、リクエストスコープやセッションなどに格納されたオブジェクトをjspで簡単に使用することができるようになります。
El式を使用するためには、jspファイルのpageディレクティブに以下を記載します。
<%@ page isELIgnored="false" %>
これでEL式を使ってjspを記述することができるようになります。
EL式を使って計算を埋め込みたい場合は${式}
という形で記載します。具体的には、jsp上に${2 * 3}
と記載し、jspを実行すると6
が表示されます。
<%@ page isELIgnored="false" %>
<html><body>
${2 * 3}
</body></html>
リクエストスコープに格納されたオブジェクトを表示する場合は${式}
の式の部分にセッション名を記載します。
例えばServletで以下のようにしていればセッション名は「name」です。
request.setAttribute("name", "value");
この場合、jsp上に${name}
と記載し、jspを実行するとvalue
という文字が表示されます。
<%@ page language="java" contentType="text/html;charset=Windows-31J"%>
<%@ page isELIgnored="false" %>
<html><body>
${name}
</body></html>
JavaBeansの仕様に準拠したオブジェクトに格納された値を表示することも可能です。その場合は、"${[セッション名].[プロパティ名]}"
をjspに記載します。
セッション名については先ほどと同様です。
プロパティ名はJavaBeansの仕様に準拠している必要があります。
つまり、<propertyName>
という名前のプロパティのGetter/Setterはget<PropertyName>()
とset<PropertyName>(<PropertyType>)
となります。
ただし、型がbooleanであるプロパティについてはGetterとしてis<PropertyName>()
というメソッドでも良いことになっています。"is〜"と"get〜"が両方ある場合は"is〜"が優先されます。
具体的には以下のようになります。
public class SampleBean {
private String propertyA;
private boolean propertyB;
private boolean propertyC;
public String getPropertyA() {
return propertyA;
}
public void setPropertyA(String propertyA) {
this.propertyA = propertyA;
}
// getPropertyB()よりもisPropertyB()が優先される
public boolean isPropertyB() {
return propertyB;
}
// isPropertyB()メソッドがあるのでEL式からこちらは呼び出されない
public boolean getPropertyB() {
return !propertyB;
}
public void setPropertyB(boolean propertyB) {
this.propertyB = propertyB;
}
public boolean getPropertyC() {
return propertyC;
}
public void setPropertyC(boolean propertyC) {
this.propertyC = propertyC;
}
}
このSampleBeanを、以下のようにしてリクエストスコープに格納するServletがあるとします。
SampleBean sample = SampleBean();
sample.setPropertyA("propertyA");
sample.setPropertyB(true);
sample.setPropertyC(false);
request.setAttribute("name", sample);
この場合、SampleBeanのプロパティに格納された値をEL式で参照するには以下のように書きます。
EL式の記載 | 呼び出されるメソッド | jspに表示される値 |
---|---|---|
${name.propertyA} | SampleBean#getPropertyA() | propertyA |
${name.propertyB} | SampleBean#isPropertyB() | true (SampleBean#getPropertyB()は呼び出されないため、falseとはならない) |
${name.propertyC} | SampleBean#getPropertyC() (isPropertyC()メソッドがないのでgetPropertyC()が呼ばれます |
false |
先ほどのjstlとEL式を組み合わせてjspを記述するとこうなります。
まずServlet
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import data.SampleBean;
@WebServlet("/JspTest")
public class JspTest extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<SampleBean> list = new ArrayList<SampleBean>();
for (int i = 0; i < 10; i++) {
SampleBean sample = new SampleBean();
sample.setPropertyA("プロパティ―A" + i);
sample.setPropertyB(true);
sample.setPropertyC(false);
list.add(sample);
}
request.setAttribute("samplelist", list);
// WEB-INFからjspへのパスを文字列で指定
String path = "/WEB-INF/jsp/jsptest.jsp";
RequestDispatcher disp = request.getRequestDispatcher(path);
disp.forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
リクエスト名samplelist
でlistを格納しています。
続いてjspです。
<%@ page language="java" contentType="text/html;charset=Windows-31J"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page isELIgnored="false" %>
<html><body>
<table border="1">
<thead>
<tr>
<th>プロパティA</th>
<th>プロパティB</th>
<th>プロパティC</th>
</tr>
</thead>
<tbody>
<c:forEach items="${samplelist}" var="item">
<tr>
<td><c:out value="${item.propertyA}" /></td>
<td><c:out value="${item.propertyB}" /></td>
<td><c:out value="${item.propertyC}" /></td>
</tr>
</c:forEach>
<tbody>
</table>
</body></html>
リクエストに格納されたlistをEL式を使い、items="${samplelist}"
で取り出しています。
listに格納された要素:SampleBeanを「item」で参照できるようにしています(var="item"
の部分)。
jstlのCoreタグforEachを使用し、listをイテレートしながら、Coreタグoutで値を出力。出力する値はEL式"${item.propertyA}"
、"${item.propertyB}"
、"${item.propertyC}"
でSampleBeanから取り出しています。
Tomcatを起動してhttp://localhost:8080/[プロジェクト名]/JspTest
をブラウザのURLに入力するとこうなります。
参考
画像やcssをjspに適用
webアプリケーションを作るのであれば、やはりjspに画像を埋め込んだりcssを適用したりしたくなる。
その場合の手順。
Eclipseで作ったプロジェクトにwebappというフォルダがあり、その配下に以下のようにフォルダ、ファイルを作成していく。
webapp
├─WEB-INF
└─WebContent
├─css
│ ├─xxx1.css
│ └─xxx2.css
└─images
├─xxx1.jpg
└─xxx2.png
ここで新たに作成したフォルダがWebサーバのどこに配置されるかは、EclipseのプロジェクトのプロパティからDeployment Assemblyから確認することができる。
(以下の画像参照)
webapp配下に格納したファイルは、jsp上で以下のように指定することで参照できるようになります。
<%@ page contentType="text/html; charset=Windows-31J" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ page isELIgnored="false" %>
<html>
<link rel="stylesheet" href="<%= request.getContextPath() %>/WebContent/css/style.css">
<head>
<title>test</title>
</head>
<body>
・・・
</body>
</html>
<%= request.getContextPath() %>
でコンテキストパスを取得。あとはWebContentからのパスを記述してあげればよいです。
コンテキストパスをEL式で取得することもできます。
やってることは先ほどと同じで、requestスコープから「getContetPath()」でコンテキストパスを取得する。
それをEL式で書いただけです。
<%@ page contentType="text/html; charset=Windows-31J" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ page isELIgnored="false" %>
<html>
<link rel="stylesheet" href="${pageContext.request.contextPath}/WebContent/css/style.css">
<head>
<title>test</title>
</head>
<body>
・・・
</body>
</html>
参考
以上。