【JavaServlet】千里の道も一歩から　四歩目

#進行状況
前回でようやく
`login.jsp　→　LoginServlet.java　→　mypage.jsp`
の遷移ができるようになりました。
ちなみに、mypage遷移時のURLは
`http://localhost:8080/ServletApp/mypage.jsp`
となりますが、もし最後の拡張子が気になる場合はweb.xmlに

```web.xml
<servlet>
	<servlet-name>mypage</servlet-name>
	<jsp-file>/mypage.jsp</jsp-file>
</servlet>
<servlet-mapping>
	<servlet-name>mypage</servlet-name>
	<url-pattern>/ServletApp/mypage</url-pattern>
</servlet-mapping>
```

を加えてあげると、遷移時のURLが
`http://localhost:8080/ServletApp/mypage`
になります。

##その他のデータの受け渡し方法
実は、サーブレット間のデータの受け渡しには、前回やった`request.getParameter()`メソッドを利用する方法以外に、「クッキー」と「セッション」と呼ばれるものが存在します。
#クッキー作りましょう
クッキーとは、サーバからレスポンスが返ってくる際にクライアント側に保存される情報です。（よくサイトを閲覧していると「このサイトはCookieを使用しています」等ポップアップが出ることもありますね）
<img width="446" alt="servlet17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/bf626f53-2095-5be8-99a9-b2dd83d6af1f.png">
クライアント側でデータを保存しておくメリットとして、

- 会員制サイト　→　次回からユーザ名の入力を省略する
- ショッピングサイト　→　カートに入れた商品を覚えておく

などが挙げられます。
それではクッキーを作っていきましょう。まずは`LoginServlet.java`の`doPost()`メソッドを改造します。

```java:LoginServlet.java
protected void doPost(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
	req.setCharacterEncoding("UTF-8");
	String name=req.getParameter("name");
	Cookie c[]=req.getCookies();
	boolean CreatedCookie=false;
	for(Cookie cookie:c) {
		if(cookie.getName().equals("cookie_user")) {
			CreatedCookie=true;
		}
	}
	if(CreatedCookie==false) {
		Cookie cookie=new Cookie("cookie_user",name);
		res.addCookie(cookie);
	}
//		if(Arrays.stream(c)
//			.filter(e->!e.getName().equals("cookie_user"))
//			.count()==c.length) {
//		Cookie cookie=new Cookie("cookie_user",name);
//		res.addCookie(cookie);
//	}
	req.setAttribute("name",name);
	req.getRequestDispatcher("/mypage.jsp").forward(req,res);
}
```
※6～15行目とコメントアウト行は書き方が違うだけでほぼ同じ動きになります。お好みで使い分けてください。

- `req.getCookies()` ・・・クライアントが持っているクッキーを配列で取得（5行目）
- `cookie.getName()` ・・・クッキーの名前を取得（8行目）
- `new Cookie(String name,String value)` ・・・`名前：値`のペアでクッキーを作成（13行目）
- `res.addCookie(Cookie cookie)` ・・・クッキーをレスポンスに設定（14行目）

これによって、ログイン時に入力したユーザ名を`cookie_user`という名前で保存できます。
また、ここには出てきませんが、

- `cookie.setMaxAge(int seconds)` ・・・クッキーの有効期限を秒数で指定（有効期限が切れるとクッキーが破棄されます）
- `cookie.setValue(String value)` ・・・クッキーに値を再設定

などもあります。
次に`login.jsp`の`<body>`タグ内を改造します。

```jsp:login.jsp
<body>
<%
	Cookie cookies[]=request.getCookies();
	String username="";
	for(Cookie c:cookies){
		if(c.getName().equals("cookie_user"))username=c.getValue();
	}
%>
<form action="/ServletApp/mypage" method="post">
name:<input type="text" name="name" value=<%=username%>><br>
password:<input type="text" name="password"><br>
<input type="submit" value="login">
</form>
</body>
```

ログイン画面表示時に、既に`cookie_user`というクッキー名が存在する場合、その値をテキストフィールドに入力させておく、という処理になります。
#クッキー使いましょう
それでは`login.jsp`へアクセスします。
<img width="396" alt="servlet19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/2a3e83ba-358c-6291-7cdb-5fc029988fd6.png">
`name`に「はと」と入力してログインします。
<img width="397" alt="servlet21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/92d69160-437c-2e1d-db0f-fe809786de3c.png">
一見何も変化がないように見えますが、ここで再度`login.jsp`にアクセスしてみましょう。
<img width="397" alt="servlet22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/d7feb368-fed6-64d2-39ef-6509c23204cd.png">
`name`に、既に先ほど入力した「はと」が入力されているのが分かります。
#クッキー調べましょう
[クッキー作りましょう](#クッキー作りましょう)で「クライアント側に保存される情報」と言いましたが、`Google Chrome`で保存されたクッキーを調べる方法があります。

1. `login.jsp`を開いた状態で`F12`キーを押して「開発者ツール」を開く。
1. メニューの`Application`タブをクリックする。
<img width="767" alt="2020-06-07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/7a7850ab-a924-1e1d-cfe7-581194d3fae7.png">

1. `Cookies`をクリックする。
<img width="767" alt="2020-06-07 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/ec67125f-63b5-755e-b3be-461d5b8516fd.png">
1. `http://localhost:8080`をクリックする。
<img width="767" alt="2020-06-07 (2).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/d9248af8-da3c-6c63-23f6-9656326fd825.png">
完了です。
`Name`に先ほど作成したクッキーの名前である`cookie_user`が、`Value`に入力したユーザ名である「はと」が表示されていますね。値の書き換えや削除もこの画面でできます。

#セッション作りましょう
セッションとは、「ログインしてからログアウトするまで」や「ログイン後、放置してタイムアウトするまで」といった`接続の開始～終了（もしくは破棄）までの一連の処理`の事を指します。
ただ、通常のWebページには「接続している状態」を受け渡す機能はないので、以下のようにサーバにアクセスするたび別の接続として扱われてしまいます。
<img width="490" alt="servlet24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/729075c9-48b7-4c8d-7d9d-36642e8af3c4.png">

この接続A～接続Cを一連の処理（セッション）にしていきましょう。

LoginServlet.javaに以下のコードを追加します。

```java:LoginServlet.java
HttpSession session=req.getSession();
Date date=new Date(session.getCreationTime());
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
session.setAttribute("lastLoginDate", sdf.format(date));
session.setMaxInactiveInterval(20);
```

`lastLoginDate`という名前でセッションの開始時刻を保存するコードです。

- `req.getSession()` ・・・セッションを取得
- `session.getCreationTime()` ・・・セッションが初めて作成された日時をlong型で取得
- `session.setAttribute(String name,Object value)` ・・・`名前：値`のペアでパラメータを格納
- `session.setMaxInactiveInterval(int s)` ・・・セッションの有効期限を`秒数`で指定（デフォルトは1800秒のはず）

mypage.jspも改造します。

```jsp:mypage.jsp
<body>
<%
    String name=request.getParameter("name");
    String session_date=session.getAttribute("lastLoginDate").toString();
%>
<%=name%>さんのログイン日時は<%=session_date%>です。
</body>
```

- `session.getAttribute(String name)` ・・・引数で指定した名前に対応する値をセッション内から`Object型`で取得

また、今回は利用しませんが

- `session.getAttributeNames()` ・・・そのセッションに格納されているパラメータ名を`String型の配列`で取得
- `session.lastAccessedTime()` ・・・そのセッションで最後に接続してきた時間を取得

などもあります。
#セッション使いましょう
では再び`login.jsp`へアクセスします。
「はと」と入力してログイン。
<img width="357" alt="servlet26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/74cc7188-4528-b217-70f1-4596f37fe0a4.png">
ざっくり現在時刻が表示されていると思います。
それでは間髪入れずに`F5`キーでページ更新（本物の入力フォームや商品ページではやらないでね）
<img width="357" alt="servlet26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/38af8600-dbf6-b240-fb32-63aca3205810.png">
時刻は変わりません。先ほど有効期限に設定した20秒の間は「同一の接続」とみなされます。
それでは時間をおいて再リロード。
<img width="357" alt="servlet27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624514/7255d8d8-3e5c-7429-f37e-fac507cc4048.png">

セッションもクッキーの一種のため、[クッキー調べましょう](#クッキー調べましょう)と同じようにセッションが確認できます。ただ、極力改変などができないよう難しい文字列になっています。

今回はここまでになります。もう少しでフレームワークに入れるかな・・・。