サーブレットとは?
- Javaの代表的なアプリケーション
- アプリケーションサーバーで動作するjavaアプリケーション
- ブラウザのwebアプリケーションでよく使われる
サーブレットの仕組み
サーブレットのタイプ
- サーブレットだけで動作(Javaのプログラム)
➡︎ 最もシンプルなサーブレット - JSP(Java Server Pages)(実行時にJavaに変換)
➡︎ HTMLと一体化したサーブレット、画面を作るのに便利 - サーブレット+JSP(組み合わせて使用)
➡︎ スタンダードなサーブレット
サーブレットの動くシステムの構成
- 静的ページ
予め用意されたページ。いつも同じ内容を表示する。 - 動的ページ
サーブレットが作ったページ。処理によって内容が変わる。
①処理全体の流れ
⚫︎ブラウザ
▶︎リクエスト
-
http://server/testWeb/app1
⬇︎
⚫︎Webサーバ
▶︎HTMLを返す方法を選択 - アプリケーションサーバに依頼
- 静的ページを返す
⬇︎
⚫︎静的ページ - HTMLファイル
⬇︎
⚫︎Webサーバ
▶︎HTMLを受け取り - 画面に表示
②処理全体の流れ
⚫︎ブラウザ
▶︎リクエスト
-
http://server/testWeb/app1
⬇︎
⚫︎Webサーバ
▶︎HTMLを返す方法を選択 - アプリケーションサーバに依頼
- 静的ページを返す
⬇︎
⚫︎アプリケーションサーバ
▶︎サーブレットを呼び出す - URLに対応したサーブレット
- メソッドを呼び出し
⬇︎
⚫︎サーブレット
▶︎メソッドを実行(service)
- HTMLを出力
サーブレットの動作を始める仕組み
⚫︎コンテキスト
- Javaのクラスファイルや設定ファイルをまとめたもの
- アプリケーションの実行に必要な一通りのものが揃っている
- 1つのシステム(小さなシステムでは1つ。複数ある場合もあります)
- コンテキストのファイル
tomcat
└ webapps
└ testWeb
プログラム(.class)設定ファイルなど
testWebのコンテキストのファイル
└ bunseki
プログラム(.class)設定ファイルなど
bunsekiのコンテキストのファイル
サーブレットのプログラムの動き
- HttpServletを継承してサーブレットを作る
シンプルなサーブレットを作る
サーブレットを作る手順
①サーブレットのクラスを作る
- 継承の記述 ⇨ HttpServletを継承して作る
- コンストラクタ ⇨ スーパークラス(HttpServlet)のコンストラクタを呼び出す
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App1Servlet extends HttpServlet {
// スーパークラス(HttpServlet)のコンストラクタを呼び出す
public App1Servlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
}
}
②処理を記述するメソッド ⇨ doGet、doPostのどちらかに処理が始まるコードを記述
- サーブレットの処理はdoGet、またはdoPostから開始 ⇨ doGet、doPostのどちらかに処理が始まるコードを記述
- ブラウザのアクセス方法 ⇨ GETメソッドとPOSTメソッド
- GETメソッド ⇨ ブラウザにURLを直接入力した場合、リンクをクリックした場合
- POSTメソッド ⇨ フォームからリクエストを送信した場合
| 区分 | GETリクエスト | POSTリクエスト |
|---|---|---|
| アクセス例 | ⚫︎URLを指定 ⚫︎リンクをクリック |
⚫︎フォームから送信 |
| ブラウザの アクセスメソッド |
⚫︎GETメソッド | ⚫︎POSTメソッド |
| サーブレットの 開始メソッド |
⚫︎doGetメソッド | ⚫︎doPostメソッド |
③パラメータを取り出す記述
⚫︎パラメータの取り出し
- HttpServletRequestからパラメータを取り出す
⇨ ブラウザから送ってきたパラメータを格納するオブジェクト
⇨ アクセスに関する情報を格納
⇨ doGet、doPostメソッドの引数として渡される - 取り出すメソッド
⇨ doGet、doPostメソッドとも同じ(どちらもHttpServletRequest)
⇨ getParameter(パラメータ名): パラメータの値を取り出す
⇨ getParameterValue(パラメータ名): 同じパラメータの複数の値を取り出す
⇨ getParameterMap(): 全てのパラメータを取り出す
④処理結果をブラウザに返す記述
⚫︎処理結果をHttpServletRequestに出力
- HttpServletRequestオブジェクト
⇨ ブラウザに返すドキュメントを出力するオブジェクト
⇨ ドキュメント ➡︎ HTML、テキスト
⇨ doGet、doPostメソッドの引数として渡される
⚫︎HttpServletRequestオブジェクトへの出力方法
- HIMEタイプのセット: ドキュメントの属性
- 文字コードのセット: 出力する文字コード
- ドキュメントの出力: ブラウザに表示する内容
⑤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">
<servlet>
<servlet-name>/App1Servlet</servlet-name>
<servlet-class>/App1Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>/App1Servlet</servlet-name>
<url-pattern>/App1Servlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
import java.io.IOException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App1Servlet extends HttpServlet {
// スーパークラス(HttpServlet)のコンストラクタを呼び出す
public App1Servlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// パラメータ取得
String params1 = request.getParameter("param1");
String params2 = request.getParameter("param2");
String params3 = request.getParameter("param3");
// Htmlを作成する処理
String html = "<html>"
+ "<body>"
+ "パラメータ名:params1 値: " + params1 + "<br />"
+ "パラメータ名:params2 値: " + params2 + "<br />"
+ "パラメータ名:params3 値: " + params3 + "<br />"
+ "</body>"
+ "</html>";
// レスポンスのヘッダーに、MIMEタイプ、文字コードをセット
response.setContentType("test/html");
response.setCharacterEncoding("UTF-8");
// 作成したHTMLを出力
response.getWriter().append(html);
}
}
getParameterメソッド
⚫︎ パラメータを取り出す(基本)
- 1つのパラメータ名から1つの値を取り出す
request.getParameter(引数)
引数(String):パラメータ名
返り値(String):値
⚫︎ポイント(1)
- 引数、返り値は、どちらもString ⇨ String以外コンパイルできません
⚫︎ポイント(2)
- パラメータの値がない場合 ⇨ 返りの値は空の文字列
⚫︎ポイント(3)
- パラメータ名がない場合 ⇨ 返りの値がnull
getParameterValuesメソッド
⚫︎ 同じパラメータの複数の値を取り出す
request.getParameterValues(引数)
引数(String):パラメータ名
返り値(String[]):値
⚫︎ポイント(1)
- パラメータの順番 ⇨ 左から順番に格納
⚫︎ポイント(2)
- パラメータがまとまって記述されていない場合 ⇨ 左から順番にまとめて格納される
⚫︎ポイント(3)
- 複数の値がある時にgetParameterで取得した場合 ⇨ 一番左のパラメータが取得される
⚫︎ポイント(4)
- パラメータの値がない場合 ⇨ 返り値の配列の要素に空の文字列が含まれる
⚫︎ポイント(5)
- パラメータ名がない場合 ⇨ 返りの値の配列がnull
getParameterMapメソッド
⚫︎全てのパラメータを取り出す
request.getParameterMap()
引数: なし
返り値(Map<String,String[]>):パラメータ名,値
JSPの概要
JSPの特徴
⚫︎HTMLと一体化したサーブレット
- JSPのソースコード
- HTMLとJavaのコードが混在 ⇨ HTMLの中にJavaのコードを埋め込んだもの ⇨ 動的ページが生成
⚫︎JSPが実行される仕組み - JSPはJavaのプログラム ⇨ 実行される時にコンパイルされる ⇨ アプリケーションサーバー ⇨ Javaのプログラムとして動作
JSPの構成要素
⚫︎同じ画面のHTMLとJSPの比較(コード)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>ようこそ!</h1>
<p>これはサンプルのHTMLページです。</p>
</body>
</html>
<%@ page language="java" contentType="text/html;charset="UTF-8" pageEnconding="UTF-8"%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>ようこそ!</h1>
<p>これはサンプルのHTMLページです。</p>
</body>
</html>
⚫︎ページディレクティブ
⇨ アプリケーションサーバがコンパイルする時に使用
- page
⇨ MIMEタイプ、文字コード、ドキュメントの属性 ⇨ JSPの先頭
⇨ Javaのクラスを使って処理する場合に使用 ⇨ 別の行に記述 - page ⇨ 他のJSPを挿入時に使用
- taglib ⇨ タグライブラリを使用する時に使用
<%@ page language="java" contentType="text/html;charset="UTF-8" pageEnconding="UTF-8"%>
⚫︎スクリプトレット
⇨ Javaのコードを記述するところ
⚫︎スクリプト式
⇨ Javaの変数やメソッドの返り値などHTMLに組み込む
- スクリプト式の記述位置は、スクリプトレットの後
JSPの作り方と基本的な処理
JSPの作り方と実行方法
⇨ 開発環境でJSPを作って、開発環境で実行する
サーブレットの実行方法の違い
- URLの違い
⚫︎JSP
http://localhost:8080/testWeb/test.jsp(jspのファイル名)
⚫︎サーブレット
http://localhost:8080/testWeb/App1(URLパターン)
⇨ JSPの実行にweb.xmlの記述は不要
JSPでよく基本的な処理
⚫︎値の埋め込み
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> //スクリプトレット <% int a = 1; int b = 2; int c = a +
b; %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>Hello World!</h1>
1たす5は //スクリプト式<%=c %>です<br />
</body>
</html>
⚫︎パラメータの取得
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> //パラメータの所得 <%String str =
request.getParameter("param1");%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>Hello World!</h1>
パラメータは<%=str %>です<br />
</body>
</html>
⚫︎出力内容の制御(条件分岐)
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> //パラメータの所得 <%String str =
request.getParameter("param1");%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>Hello World!</h1>
<% if (str! == null) {%> パラメータは<%=str %>です<br />
<% } else { %> パラメータはありません <% } %>
</body>
</html>
⚫︎出力内容の制御(繰り返し表示)
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%>
String str = ["昭和","平成","令和"];
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>Hello World!</h1>
<% for(int i=0; i<strs.length; i++>) {%>
<% strs[i] %>
<% }%>
</body>
</html>
JSPでクラスを使う
JSPからクラスを呼び出して処理
⚫︎JSPにはJavaのコードが記述可(スクリプトレット)
⚫︎スクリプトレットにたくさんのコードを記述するのは非現実的
⇨ 本格的な処理をする時にはクラスを使う
JSPから呼び出すクラス
⚫︎自分で作ったJavaクラス
- たくさんのコードの記述が必要な場合など
- JSPの個別の処理に合わせたものライブラリ化したもの
⚫︎JavaAPIのクラス - JavaAPIはJavaのプログラミングには欠かせないライブラリ
自分で作ったJavaのクラスを使う
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%>
<% page import="yurufuwa.prg.sample.Calc" %>
<%
//パラメータの取得
String sX = request.getParameter("x");
String sY = request.getParameter("y");
int x = Integer.parseInt(sX);
int y = Integer.parseInt(sY);
//計算機クラスにパラメータをセット
Calc calc = new Calc();
calc.setX(x);
calc.setY(y);
%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
<h1>Hello World!</h1>
<% for(int i=0; i<strs.length; i++>) {%>
<% strs[i] %>
<% }%>
</body>
</html>
JavaAPIのクラスを使う
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%>
<% page import="java.util.ArrayList" %>
<% page import="yuryfuwa.prg.sample.Todofuken" %>
//都道府県のリストを取得
Todofuken todoufuken = new Todofuken();
ArrayList<String> todoufukenList = td.getList();
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>都道府県リスト</title>
</head>
<body>
<% for(int i=0; i<todoufuken.size(); i++>) {%>
<%= todoufukenList.get(i) %>
<% }%>
</body>
</html>
JSPの仕組み
処理の仕組み
⚫︎サーブレットに変換
- リクエストを受けてJSPをサーブレットのソースファイルに変換
Javaソースファイルのコンパイル
⚫︎変換したJavaのソースファイルをコンパイル
メソッドの呼び出し
⚫︎アプリケーションサーバがメソッドを呼び出す
変換・コンパイルの条件とタイミング
⚫︎実行される条件
- ファイルの更新日を比較して実行
⚫︎比較が実行されるタイミング - JSPが初めて呼び出される時に比較
JSPが変換されたJavaのコード
⚫︎ブラウザからリクエストを受けて変換
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%>
<% page import="yurufuwa.prg.sample.Calc" %>
<%
String sX = request.getParameter("x");
String sY = request.getParameter("y");
int x = Integer.parseInt(sX);
int y = Integer.parseInt(sY);
Calc calc = new Calc();
calc.setX(x);
calc.setY(y);
%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
</head>
<body>
計算結果: <%= clac.getAnswer() %>
</body>
</html>
</String>
Javaのコードの格納場所
⚫︎Tomcatのフォルダに格納
サーブレット + JSP
特徴
⚫︎MVCモデル
- 3つの要素が役割を分担する設計モデル
- 標準的な役割分担がお手本としているモデル
①コントローラ(Controller) ⇨ サーブレット
画面の入力を取り出すモデルに渡す
②モデル(Model) ⇨ Javaクラス
ビジネスロジックを実行
処理結果を生成し、通知する
③ビュー(View) ⇨ JSP
処理結果を表示
サーブレットが呼び出される
package yurufuwa.prog.sample;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// パラメータ取得
String params1 = request.getParameter("str1");
String params2 = request.getParameter("str2");
// モデルで文字列結合
Concat c = new Concat();
c.setStr1(str1);
c.setStr2(str2);
c.join();
// 結合結果を取得
String answer = c.getAnswer();
// ビュー(JSP)に結果を出力してもらう
ServletContext ctx = getServletContext();
RequestDispatcher rd = ctx.getRequestDispatcher("/WEB-INF/join.jsp");
rd.forward(request, response);
}
}
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> <% //結合結果をリクエストから取得 String ans =
(String)request.getAttribute("ans"); %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
文字列の結合結果: <br />
<%= ans %>
</body>
</html>
URLにセットした2つのパラメータを結合して表示する
①処理結果の渡し方が違う処理(1)
package yurufuwa.prog.sample;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// パラメータ取得
String str1 = request.getParameter("str1");
String str2 = request.getParameter("str2");
// モデルで文字列結合
Concat c = new Concat();
c.setStr1(str1);
c.setStr2(str2);
c.join();
// モデルをリクエストにセット
request.setAttribute("result", c);
// ビュー(JSP)に結果を出力してもらう
ServletContext ctx = getServletContext();
RequestDispatcher rd = ctx.getRequestDispatcher("/WEB-INF/join.jsp");
rd.forward(request, response);
}
}
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> <%@ page import="yurufuwa.prog.sample.Concat" %> <%
//モデルからリクエストから取得 Concat c =
(Concat)request.getAttribute("result"); %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
文字列の結合結果: <br />
<%= c.getAnswer() %>
</body>
</html>
②処理結果の渡し方が違う処理(2)
package yurufuwa.prog.sample;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// パラメータ取得
String str1 = request.getParameter("str1");
String str2 = request.getParameter("str2");
// モデルで文字列結合
Concat c = new Concat();
c.setStr1(str1);
c.setStr2(str2);
c.join();
// モデルの結果クラスを取得
ConcatResult result = c.getResult();
// モデルをリクエストにセット
request.setAttribute("result", c);
// ビュー(JSP)に結果を出力してもらう
ServletContext ctx = getServletContext();
RequestDispatcher rd = ctx.getRequestDispatcher("/WEB-INF/join.jsp");
rd.forward(request, response);
}
}
<%@ page language="java" contentType="text/html;charset="UTF-8"
pageEnconding="UTF-8"%> <%@ page import="yurufuwa.prog.sample.ConcatResult" %>
<% ConcatResult cr = (Concat)request.getAttribute("result"); %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>サンプルHTMLページ</title>
</head>
<body>
文字列の結合結果: <br />
<%= c.getAnswer() %>
</body>
</html>
③サーブレットの役割を削った方法
package yurufuwa.prog.sample;
import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//HttpServletを継承して作る
public class App5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// モデルで文字列結合
Concat c = new Concat();
c.join();
// モデルをリクエストにセット
request.setAttribute("result", c);
// ビュー(JSP)に結果を出力してもらう
ServletContext ctx = getServletContext();
RequestDispatcher rd = ctx.getRequestDispatcher("/WEB-INF/join.jsp");
rd.forward(request, response);
}
}
web.xmlの記述方法
⚫︎アプリケーションサーバがサーブレットを呼び出す時に使用
⇨ サーブレットを動かすために必須
⚫︎その他の設定
⇨ ウェルカムぺーじの設定など
URLパターン ⇨ サーブレットのクラス名
⚫︎2つの対応表を使ってサーブレットのクラス名を決定
注意点と注意事項
注意事項
⚫︎サーブレットを作る時
⇨ サーブレットのフィールド変数は使用しない
⚫︎JSPを作る時
⇨ スクリプト宣言で変数を宣言しない
フィールド変数を使用しない理由
サーブレットの動作の特徴
⚫︎webアプリケーション、アプリケーションサーバーで動作
⚫︎同時に複数のブラウザからアクセス
⬇︎
⚫︎同時に処理を実行する仕組み
⚫︎処理を高速に実行する仕組み
⬇︎
注意点 フィールドを使用しない理由
フィールド変数は使用可能 ⇨ 使い方は限定
⚫︎フィールド変数は、同時実行時に共有される
⇨ 処理ごとに必要なパラメータなdpはセットできない ⇨ 処理ごとに必要でないものは使用可能
参考サイト
【中級編Java(1)】サーブレットの仕組み―サーブレットの基礎知識―|Javaプログラミングのゆるふわレシピ
【サルでも分かる】Java Servlet入門
【中級編Java(3)】シンプルなサーブレットを作る―サーブレットの作り方―|Javaプログラミングのゆるふわレシピ
【中級編Java(4)】シンプルなサーブレットを作る―サーブレットの作り方(2)―|Javaプログラミングのゆるふわレシピ
【中級編Java(5)】JSPの概要―JSPの特徴と構成要素―|Javaプログラミングのゆるふわレシピ
【中級編Java(6)】JSPの作り方と基本的な処理―覚えておきたい基本的な処理―|Javaプログラミングのゆるふわレシピ
【中級編Java(7)】JSPでクラスを使う―覚えておきたい基本的な処理(2)―|Javaプログラミングのゆるふわレシピ
【中級編Java(8)】JSPの仕組み(1)―JSPが実行される仕組み―|Javaプログラミングのゆるふわレシピ
【中級編Java(9)】JSPの仕組み(2)―JSPが変換されるJavaのコード―|Javaプログラミングのゆるふわレシピ
【中級編Java(10)】サーブレット+JSP(1)―動作の仕組みとコード―|Javaプログラミングのゆるふわレシピ
【中級編Java(11)】サーブレット+JSP(2)―処理パターン―|Javaプログラミングのゆるふわレシピ
【中級編Java(12)】web.xmlの記述方法―サーブレットを呼び出すための記述―|Javaプログラミングのゆるふわレシピ
【中級編Java(13)】サーブレット作成時の注意点―フィールド変数は使わない―|Javaプログラミングのゆるふわレシピ
