サーブレット/JSPメモ

# HTMLファイルで入力されたものをサーブレットで表示

下記のような簡易的なログインフォームを作成する。

![ログイン画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954144/59a25e64-3b06-059c-9e51-b63fd9f9c190.png)

## ログイン画面のHTMLファイル

コードは下記のような感じ。

```ruby:ログイン画面（login.html）
<div class="login_title_area">
	  <form action="base" method="post">
		  <h1>ログイン</h1>
		  <div class="login_box">
          <div class="userId_input_area">
              <label class="userId_title"></label>
              <input type="text" name="userId" placeholder="ユーサーID" class="userId_input_box">
          </div>
          <div class="password_input_area">
              <label class="password_title"></label>
              <input type="password" name="pass" placeholder="パスワード" class="password_input_box"> 
          </div>
          <div class="login_buttun_area">
              <button type="submit" name="action" value="default" class="login_button">ログイン</button>
          </div>
      </div>		  
	  </form>     
  </div>
```

### 遷移先と送信方法


フォームの遷移先と送信方法を指定。
今回は遷移先がBaseサーブレットで、POSTで送信するため、コードは下記のようになる。
```
<form action="base" method="post">
```

:::note
フォーム送信の指定
```
<form action="サーブレット名の小文字" method="post/get">
```
:::

※サーブレットを使用せず、別ページへ遷移したい場合は

```
action="遷移先のパス"
```
とすればサーブレットを挟むことなく直接遷移ができる。


## サーブレット（BaseServlet）

サーブレットのコードはこんな感じで、
入力されたIDとパスワードをそのまま表示する。


```ruby:サーブレット（BaseServlet）
@WebServlet("/login")  //マッピング名（サーブレットを呼び出すURLパス）を指定
public class BaseServlet extends HttpServlet{  //HttpServletクラスを継承
	@SuppressWarnings("unchecked")
	public void doPost(HttpServletRequest req, HttpServletResponse res) 
			throws IOException, ServletException{ //doGet()をオーバーライド
		
//		セッションオブジェクトの生成と取得
		HttpSession session = req.getSession(true);
//		セッションオブジェクトからIDを取得
		ArrayList<String> userList = (ArrayList<String>)session.getAttribute("userId");
		
		if(userList == null) {
//			初回アクセス
			userList = new ArrayList<String>(); 
		} else {
			req.setCharacterEncoding("utf-8");
			String user = req.getParameter("userId");
			userList.add(user);
		}
		
		session.setAttribute("userI",userList);
		
		req.setCharacterEncoding("utf-8");
		res.setContentType("text/html;charset=utf-8"); //コンテンツタイプの指定
		PrintWriter out = res.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>アカウント情報</title>");
		out.println("</head>");
		out.println("<body>");
		for(String userId : userList) {
			out.println("<h1>ユーザーID："+ userId);
		}		
//		out.println("<h1>パスワード："+ req.getParameter("pass")+"</h1>");
		out.println("</body>");	
	}
```

色々とインポートが必要だが、eclipseを使用していれば半自動でインポートされるので、今回はスキップ。<br><br>

### マッピングを指定

マッピング名（サーブレットを呼び出すURLパス）を指定。<br>
サーブレットはlogin.htmlファイルから呼び出されているので、以下のように記載。


```
@WebServlet("/login") 
```

:::note
<details><summary>マッピングの指定</summary>

```
@WebServlet("/呼び出し元のファイル名") 
```

</details>
:::

### サーブレットクラスの作成

サーブレットクラスを作成する。

```
public class BaseServlet extends HttpServlet{ 
```

:::note warn
注意
HttpServletクラスを継承しないと、作成したサーブレットクラスはサーブレットだと認識しない
:::

doPost/doGetメソッドを作成する。
今回はログイン画面（login.html）でPOST送信を指定しているため、doPostになる。
```
public void doPost(HttpServletRequest req, HttpServletResponse res) 
			throws IOException, ServletException{
```

:::note
<details><summary>doPost/doGetのメソッド作成</summary>

```
public void doPost/doGet(HttpServletRequest req, HttpServletResponse res) 
			throws IOException, ServletException{
```

</details>
:::

### 文字コードとコンテンツタイプの指定

doPost/doGetのメソッドを作成したら、文字コードとコンテンツタイプの指定を行う。
以下のコードをそのままコピーすればOK

:::note
文字コードの指定
```
req.setCharacterEncoding("utf-8");
```
:::

:::note
コンテンツタイプの指定
```
res.setContentType("text/html;charset=utf-8"); 
```
:::

サーブレット内でHTML表記をするために、
PrintWriterクラスのgetWriterメソッドを使用して、サーブレット内でHTMLを使用できるようにする。
以下をそのままコピペ

:::note
PrintWriterクラスのgetWriterメソッド
```
PrintWriter out = res.getWriter();		
```
:::

### HTMLの記述

以上の過程を踏まえたら、いよいよHTMLの記載ができる。

```
out.println("<html>");
		out.println("<head>");
		out.println("<title>アカウント情報</title>");
		out.println("</head>");
		out.println("<body>");
		for(String userId : userList) {
			out.println("<h1>ユーザーID："+ userId);
		}		
		out.println("</body>");	
out.println("</html>");
	}
```

サーブレットでHTMLを表現するために、

:::note
```
out.println("<HTMLタグ>");
```
:::
と表記する必要がある。

例えば、
```
out.println("<html>");
out.println("<div class = "a">");
out.println("<input type="text" name="userId" placeholder="ユーサーID" class="userId_input_box">")
```
といった表記になってくる。

毎回out.printlnの（）内に記載するのはめんどくさいが、HTMLの構成自体は変わらないので、そこまで苦にならないと思う。







# JSPファイルで入力したものをサーブレットで処理してJSPファイルで表示をする



![デモサイト.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954144/acc28836-22a2-213b-88ed-b747e3b643b2.jpeg)

こんな感じの簡易サイトを作成する。
①JSPファイルでユーザーIDとパスワードを入力し、サーブレットへ入力情報を送付
②サーブレットでユーザーIDとパスワードが一致しているかどうかを判定
③不一致の場合：最初の画面（login.jsp）に遷移してエラーメッセージを表示
一致した場合：結果画面（result.jsp）へIDを表示

IDとパスワードが一致した場合はユーザーIDを表示し、
一致しない場合は『ユーザーIDかパスワードが間違っています。』と表示されるシステムを作成する。


ログイン画面のコードはこんな感じ。
```ruby:ログイン画面（login.jsp）
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ログイン</title>
</head>
<body>
<div class="login_title_area">
	  <form action="base" method="post">
		  <h1>ログイン</h1>
		  <% if(request.getAttribute("error")==null){ %>　　
		  <p> </p> 
		  <%} else { %>
		  <p> <font color="red"> <%= request.getAttribute("error") %> </font></p>
		  <% } %>
		  <div class="login_box">
          <div class="userId_input_area">
              <label class="userId_title"></label>
              <input type="text" name="userId" placeholder="ユーサーID" class="userId_input_box">
          </div>
          <div class="password_input_area">
              <label class="password_title"></label>
              <input type="password" name="pass" placeholder="パスワード" class="password_input_box"> 
          </div>
          <div class="login_buttun_area">
              <button type="submit" name="action" value="default" class="login_button">ログイン</button>
          </div>
      </div>		  
	  </form>      
  </div>
</body>
</html>
```

ログインボタンを押すとサーブレットが起動し、ログインの成功/失敗を判断する仕組みで、
失敗の場合はサーブレットよりメッセージを受け取る。

サーブレットから取得したメッセージが文字化けしないように、JSPファイルの冒頭に以下のような文字コードの指定が必要になる。

:::note
JSPを利用する際の文字コードの指定
```
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
```
:::

ログインが失敗の場合は、
```
<p> <font color="red"> <%= request.getAttribute("error") %> </font></p>
```
でサーブレットの"error"に格納されている値を取得し、メッセージを表示。


次にサーブレット。


```ruby:サーブレット（BaseServlet.java）
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;

import bean.ResisterBean;

@WebServlet("/login")  #マッピング名（サーブレットを呼び出すURLパス）を指定
public class BaseServlet extends HttpServlet{  #HttpServletクラスを継承

    #Beanクラスの変数を定義
	ResisterBean resisterBean;
	
	public void doPost(HttpServletRequest req, HttpServletResponse res) 
			throws IOException, ServletException{ //doGet()をオーバーライド
		
		#リクエストのエンコーディング
		req.setCharacterEncoding("utf-8");
		
		#入力情報の取得
		String user = req.getParameter("userId");
		String pass = req.getParameter("pass");
		
		if(user.equals("99999") && pass.equals("1234")) {
			
			#取得した入力情報をBeanへ格納する。
			resisterBean = new ResisterBean();
			resisterBean.setUser(user);

			#リクエストオブジェクトに格納
			req.setAttribute("resisterBean",resisterBean);

				
			#JSPファイルにフォワード
			RequestDispatcher rd = req.getRequestDispatcher("/result.jsp");
			rd.forward(req,res);
		
		} else {
			req.setAttribute("error","ユーザーIDかパスワードが間違っています。");
			
			#JSPファイルにフォワード
			RequestDispatcher rd = req.getRequestDispatcher("/login.jsp");
			rd.forward(req,res);
		}			
	}
}
```

サーブレットを使用するのに必要なオブジェクトをインポート。
eclipseだと半自動でインポートされるので、そこまで気にする必要はないかも。

:::note
マッピング名を指定
```
@WebServlet("/サーブレットを呼び出すURL") 
```
:::

POST/GET送信で使用するメソッドを作成。
下記のコードをコピペでOK。

:::note
doGetをオーバーライド
```
public void doPost(HttpServletRequest req, HttpServletResponse res) 
			throws IOException, ServletException{
```
※GET送信の場合はdoPostがdoGetになる
:::

doGet/doPostメソッドを作成したら、
サーブレット内の文字コードの指定が必要になる。

下記をコピペ

:::note
サーブレットの文字コードの指定
```
req.setCharacterEncoding("utf-8");
```
:::

JSPでの入力情報を取得。

:::note
リクエストで送付された値を取得
```
req.getParameter("JSPファイルのname属性");
```
:::

リクエストを返却する際に、リクエストオブジェクトに格納。

:::note
リクエストオブジェクトに格納
```
req.setAttribute(”名前”,値);
```
:::

最後に遷移先を指定して、フォワード。
下記をそのままコピペすればOK。

:::note
フォワード
```
RequestDispatcher rd = req.getRequestDispatcher("/遷移先URL");
			rd.forward(req,res);
```
:::


次に遷移先のJSPファイルを見ていく。
サーブレットからJSPを使用してユーザーIDを取得して表示するプログラム。

```ruby:遷移先JSPファイル（result.jsp）
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import ="bean.ResisterBean" %> 
<%request.setCharacterEncoding("utf-8");%>  
<!-- ↑入力された日本語をプログラムのなかで文字化けせずに使用することができる暗黙オブジェクト -->  
<% 
ResisterBean resisterBean =(ResisterBean)request.getAttribute("resisterBean") ;
%>
<!DOCTYPE html>
<html>
<head>
<title>ログイン情報</title>
</head>
<body>
<h3>ユーザーID：<%=resisterBean.getUser() %></h3>
</body>
</html>
```

ファイル内にJavaコードを書き込めるようにするため、
下記のコードを記載。これもこのままコピペすればOK。

:::note
使用する言語と文字コードを指定
```
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
```
:::

リクエストオブジェクトのgetAttributeメソッドを使用して、
リクエストに格納されている情報を取得。

:::note
リクエスト情報の取得
```
<% request.getAttribute("resisterBean") ;%>
```
:::

取得したBeanクラスより、対象の値を取得する

:::note
```
<%=resisterBean.getUser() >%>
```
:::

# まとめ

サーブレットとJSPを使用するための手順と書き方をまとめた。
使うオブジェクトやメソッドは決まっているので、全体の流れを掴み、コードはコピペすれば沼にはまることはないと思う。<br>

ただ、JSPからサーブレットの値の引き渡し、サーブレットからJSPへの値の引き渡しには注意が必要だと思うので、気をつけたい。

あと、eclipseでJSPファイルはコンパイル前にエラーが表示されないので、
HTMLの表記とJavaの表記を明確にして、ぐちゃぐちゃにならないように注意したい。