【社内勉強会】Servletの基礎（2017/08/31) 


# 0. はじめに


------------------
## 対象者
* Servlet初心者

### 前提知識
* Javaの基本的な構文
* Tomcatの基本的な知識
* Eclipseの基本的な使い方
* HTTP(GET,PUTメソッド、リクエスト/レスポンス)
* HTMLの基本構文



------------------
## 目次
1. Servletとは？
2. Servletを動かそう
3. Tomcatにデプロイ

------------------
# 1. Servletとは？


------------------
##  Servletとは？

>サーバ上でウェブページなどを動的に生成したりデータ処理を行うために、Javaで作成されたプログラム及びその仕様である

※ [Wikipedia Java Servlet](https://ja.wikipedia.org/wiki/Java_Servlet) 引用

* Java EEの機能の一つ
* 1997年リリース
* 最新バージョンはServlet3.1(2013年)

------------------
##  サーブレットコンテナ

* Servletを実行するためのソフトウェアのこと
* TomcatやWebLogicなど

------------------
##  ServletとTomcatのバージョンの関係

* Servlet3.1ならば、Tomcat8で、Java7以上

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/d6df635b-9e5c-4476-eeef-f22a68ddb992.png)
※ http://tomcat.apache.org/whichversion.html 引用

------------------
## Servletを学ぶ意味
* WebフレームワークがServletを隠ぺいしているので、素のServletを書くことはあまりない
* Webフレームワークで問題が起きたときは、Servletの知識が必要になるかもしれない

------------------
# 2. Servletを動かそう


--------
## 実行環境

* Tomcat 8
* Eclipse4.6 pleiades
* Java8
* [Sample Code(GitHub)](https://github.com/yuji38kwmt/SampleWeb)

-------
## Eclipseでプロジェクト作成

1. 「動的Webプロジェクト」を作成
 * ターゲットランタイム：Tomcat8
 * プロジェクト名：「SampleWeb」

2. 確認
* Tomcatライブラリの「servlet-api.jar」が追加されていること

-------
## Servlet作成

1. 新規「サーブレット」から作成。

```java:HelloWorld.java
//Servletであることの印。
@WebServlet(urlPatterns = { "/HelloWorld" })
public class HelloWorld extends HttpServlet {
	@Override
	//HTTPのGETメソッドに応答する処理
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//Helloと現在時刻を出力
	    PrintWriter out = response.getWriter();
	    out.println("Hello World");
	    out.println((new Date()).toString());
	}
}
```

 * `HttpServlet`を継承している
 * `@WebServlet`でServletであることを示している
 * `urlPatterns`に指定したURLにアクセスすると、サーブレットが動く

--------
### Servletの動作確認

1. Eclipseで、「SampleWeb」プロジェクトをTomcatにデプロイ
http://www.gb-sol.com/devblog/?p=637 参考
2. ブラウザで、http://localhost:8080/SampleWeb/HelloWorld にアクセス
 * 画面にアクセス時刻が表示される
 * ただのテキストでHTMLではない
 
--------
## ServletでHTMLを出力

```java:HelloWorldHtml.java
@WebServlet(urlPatterns = { "/HelloWorldHtml" })
public class HelloWorldHtml extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//HTTPレスポンスヘッダのコンテンツタイプ
	    response.setContentType("text/html");

	    //HTTPボディ部
	    PrintWriter out = response.getWriter();
	    out.println("<!DOCTYPE html>");
	    out.println("<html>");
	    out.println("<head>");
	    out.println("<meta charset=\"UTF-8\">");
	    out.println("<title>Hello World!</title>");
	    out.println("</head>");
	    out.println("<body>");
	    out.println("<h1>Hello World!</h1>");
	    out.println("<h2>" + (new Date()).toString() + "</h2>");
	    out.println("</body>");
	    out.println("</html>");
	}
}
```

--------
### 動作確認
* HTMLタグが認識されていること
* ブラウザでソースを表示して、出力内容を確認
* ブラウザでレスポンスヘッダのContentTypeを確認

### ソースの特徴
* `out.println`が冗長
* 処理が長くなりがち
* レイアウト部分と処理の部分が混在している

⇒ JSPの登場（次回説明）

--------
## リクエスト情報の取得


```java:FormResult.java
@WebServlet(urlPatterns = { "/FormResult" })
public class FormResult extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    PrintWriter out = response.getWriter();
	    out.println("HTTP GET Method");
	    //パラメタ取得
	    String name = request.getParameter("name");
	    out.println("name = " + name);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    PrintWriter out = response.getWriter();
	    out.println("HTTP POST Method");
	    //パラメタ取得
	    String name = request.getParameter("name");
	    out.println("name = " + name);
	}
}
```

-------
### form要素でサーバに情報を送信


```html:form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<form action="/SampleWeb/FormResult" method="GET">
  HTTP GET name: <input name="name" >
  <input type="submit" >
</form>
<form action="/SampleWeb/FormResult" method="POST">
  HTTP POST name: <input name="name" >
  <input type="submit" >
</form>

</body>
</html>
```


-------
### 動作確認

* GETは`doGet`メソッド、POSTは`doPost`メソッドが実行される
* GETでもPOSTでも、`request.getParameter`でパラメタを取得できる


-------
## Servlet Filter

Servletの前処理。

```java:SampleFilter.java
// 全てのURLに対して、このフィルタを適用する
@WebFilter(filterName="SampleFilter", urlPatterns="/*")
public class SampleFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //文字コード指定
        request.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    @Override public void init(FilterConfig filterConfig) throws ServletException {}
    @Override public void destroy() {}

}
```

* 文字コード指定やログ設定など、サーブレットに対して共通の処理を実行するときに使う。


-------
## Servlet Filterの順番

web.xmlに定義する必要あり


```xml:web.xml
  <filter-mapping>
    <filter-name>SampleFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter-mapping>
    <filter-name>SampleFilter2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
```

* `filter-mapping`を定義した順番に、フィルタが適用される



-------
## アノテーションを使わない方法

* Servlet2.5以前はアノテーションが使えない。web.xmlに定義する必要がある。
* Servlet3.0以降からアノテーションが使える。

```xml:web.xml
<servlet>
  <servlet-name>HelloWorld</servlet-name>
  <servlet-class>jp.co.sample.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>HelloWorld</servlet-name>
  <url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
```

* アノテーションを使うメリット
    - 設定漏れ(web.xml)が発生しにくい
    - 記述量が少ない(アノテーションなので1行）

------------------
# 3. Tomcatにデプロイ


--------
## 手動でTomcatに配備

Eclipseなどが自動で行う作業を理解するために、まずは手動で実施する。

### プログラムの配置構成

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/00cba4a1-b3db-85a0-f64f-ce21b541be28.png)

※ http://www.javaroad.jp/opensource/js_tomcat2.htm 引用


1. `%TOMCAT_HOME%/webapps`に、上記のようにディレクトリを作成
2. プロジェクトをビルドし、生成されたclassファイルを、`WEB-INF/classes`ディレクトリに配置
3.  `%TOMCAT_HOME%/bin/startup.bat`を実行する




--------
## EclipseでTomcatを動かす
* WTP(Web Tool Platform)プラグインを使用している
* Tomcatのパスの定義： 設定→サーバ→ランタイム環境
* ソースは以下のディレクトリにデプロイされる
`workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/`
* server.xmlの定義

```xml:server.xml
<Host>
  <Context docBase="SampleWeb" path="/SampleWeb" reloadable="false" source="org.eclipse.jst.jee.server:SampleWeb"/>
</Host>
```


--------
# 4. 付録


--------
## 次に学ぶべきこと(予定)

* JSP
* MVC
* Webフレームワーク
 - struts
 - spring
* Session管理
* 文字化け対策
* warファイルの中身

--------
## 参考サイト

* http://qiita.com/opengl-8080/items/7d51351cb540269e1d05
* http://wa3.i-3-i.info/word12835.html
* http://www.javaroad.jp/opensource/js_eclipse6.htm