Java サーブレット&JSP でアプリを実装してみた！

## はじめに
はじめまして、みつと申します。
IT企業に入社して、ちょうど一年程になります。
まだまだ未熟なPGですが、最近はアウトプットに力を入れています。　

今回、JavaのJSP&サーブレットを使って、簡単なアプリを実装したので、少し説明を入れながら実装したアプリを紹介させていただきます。
## 読者対象
Java初学者の方
Javaの基礎を学習し終わり、画面で何か実装してみたい方

## 環境
・Eclipse(4.28.0)
・Windows 11 Home 22H2

## 仕様説明
プログラムを開始させると、お名前入力欄が出てくるので
お名前を入力してはじめるボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/be1decf2-721c-3171-3ec2-6ffd77d1dc22.png)
タスク一覧画面が表示されます。
初期状態では何も登録されていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/3d5efdf1-25d5-29ba-861a-5419ba43af57.png)
日付・タスク内容を登録すると、先頭にタスクが追加されていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/3ce42de1-b838-31ee-740d-5068bc1736e4.png)
削除ボタンを押下すると、その選択したタスクを削除することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/543f461a-5167-f144-26ba-60753efc49b1.png)
DBには接続せず、アプリケーションスコープとセッションスコープを使用しており、シンプルな構造になっています。


## ディレクトリ構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2869221/3beb1a23-e343-b28e-d469-e00e6f22b7e3.png)

## ソースコード
6つのファイルのソースコードの一部を抜粋して載せています。
Githubにソースコードを載せているので、ご興味ある方は下記のURLをご覧ください。

https://github.com/Mitsu-1216/QiitaSJ_App

①index.jsp
```jsp:index.jsp
<div>
<h1>Todoアプリへようこそ！</h1>
<% if(errorName != null) { %>
<p><%= errorName %></p>
<% } %>
<form action="/sampleSJ/MainServlet" method="get">
お名前：<input type="text" name="name">
<input type="submit" value="はじめる">
</form>
</div>
```
jspファイルはMVCモデルのうちレスポンスをするV(ビュー)にあたります。
正体はサーブレットクラスですが、扱いはHTMLファイルです。
index.jspは起動させて表示される最初のページです。
入力されたお名前はセッションスコープに保存しています。
`<%= errorName %>`は、お名前が入力されなかった場合、
「お名前を入力してください」の文字を表示させます。
<br>
②todo.jsp
```jsp:todo.jsp
<%@ page import="model.TodoBeans,java.util.List,java.util.Date,java.text.SimpleDateFormat" %>
<%
List<TodoBeans> todoList = (List<TodoBeans>) application.getAttribute("todoList");
%>
```
 page importで複数のクラスをインポートし、
アプリケーションスコープからtodoListという属性名のインスタンスを取得しています。

```jsp:todo.jsp
<body>
<h1><%= session.getAttribute("name") %>さんのタスク一覧</h1>
<form action="/sampleSJ/MainServlet" method="post">
<input type="date" name="date">
<input type="text" name="text" placeholder="タスクを入力してください">
<input type="submit" value="登録">
</form>
```
`<%= session.getAttribute("name") %>`でセッションスコープに保存した名前を取得しています。
タスクを登録する際、登録ボタンを押下すると、POSTリクエストを使ってリクエスト先のMainServlet(サーブレットクラス)にリクエストパラメータが渡されます。

```jsp:todo.jsp
<table>
<tr>
<th>期限</th>
<th>タスク内容</th>
<th>削除</th>
</tr>
<% for(TodoBeans todo : todoList) {%>
<tr>
<td><%= todo.getDeadline() %></td>
<td><%= todo.getText() %></td>
<td>
<form action="/sampleSJ/DeleteServlet" method="post">
<input type="hidden" name="text" value="<%= todo.getText() %>">
<input type = "submit" value = "削除">
</form>
</td>
</tr>
<% } %>
</table>
```
登録したタスクを表示するテーブル部分です。
削除ボタンを押下された場合、タスクの内容をPOSTリクエストを使ってDeleteServlet(サーブレットクラス)にリクエストパラメータを渡します。
<br>
③RegisterLogic.java
```java:RegisterLogic.java
public class RegisterLogic {
	public void execute(TodoBeans todo, List<TodoBeans> todoList) {
		todoList.add(0, todo);
	}
}
```
RegisterLogic.javaはMVCモデルのM(モデル)のうち、アプリケーションが行う処理ロジックを担っています。
todo.jsp画面から送信された日付、タスクをtodoListという名前のリストの先頭に追加しています。
<br>
④TodoBeans.java
```java:TodoBeans.java
public class TodoBeans implements Serializable {
	private String text;
	private String deadline;

	public TodoBeans() {
	}
	public TodoBeans (String text,String deadline) {
		this.text = text;
		this.deadline = deadline;
	}
	public String getText() {
		return text;
	}
	public String getDeadline() {
		return deadline;
	}
}
```
TodoBeans.javaは、タスクに関する情報(期限、タスク内容)を持つJavaBeansのモデルです。
MVCモデルのM(モデル)のうち、アプリケーションが扱う情報の保持を行っています。

<br>
⑤MainServlet.java

```java:MainServlet.java
@WebServlet("/MainServlet")
public class MainServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

		protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
        // リクエストパラメータの取得
		String name = request.getParameter("name");
		
        // nameが取得できなかった場合
		if (name == null || name.length() == 0) {
			request.setAttribute("errorName","お名前を入力してください");
            // フォワード
			RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
			dispatcher.forward(request, response);
        
        // nameが取得できた場合
		} else {
            // アプリケーションスコープからtodoListを取得			
			ServletContext application = this.getServletContext();
			List<TodoBeans> todoList = (List<TodoBeans>) application.getAttribute("todoList");
			
            // todoListが取得できなかった場合、新規作成
			if (todoList == null) {
				todoList = new ArrayList<>();
				application.setAttribute("todoList", todoList);
			}
			
            // お名前をセッションスコープに保存
			HttpSession session = request.getSession();
			session.setAttribute("name",name);
            
            // フォワード
			RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/todo.jsp");
			dispatcher.forward(request, response);
		}
	}
```
doGetメソッドは、GETリクエストされると実行されます。
最初のindex.jspの画面でお名前を入力されなかった場合、
「お名前を入力してください」の文字を表示させます。
お名前を入力された場合は、セッションスコープにお名前を保存し、
todo.jspへフォワード(処理をほかのファイルやクラスに移す)させます。
todoListが存在しない場合は、新しくtodoListリストを作成します。

```java:MainServlet.java
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
        // リクエストパラメータの取得
		String date = request.getParameter("date");
		String text = request.getParameter("text");
        
        // タスク内容が入力されている場合
		if(text != null && text.length() != 0) {	
            ServletContext application = this.getServletContext();
			List<TodoBeans> todoList = (List<TodoBeans>) application.getAttribute("todoList");

			TodoBeans todo = new TodoBeans(text,date);
			RegisterLogic registerTodo = new RegisterLogic();
            //tosoListに追加 
			registerTodo.execute(todo, todoList);

            // アプリケーションスコープに保存
			application.setAttribute("todoList", todoList);
		
        // タスク内容が入力されていない場合
        } else {
			request.setAttribute("errorMsg","タスクが入力されていません");
		}

        // フォワード
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/todo.jsp");
		dispatcher.forward(request, response);
	}
}
```
doPostメソッドは、POSTリクエストされると実行されます。
タスク内容が入力されていた場合、todoListに追加します。
<br>
⑥DeleteServlet.java
```Java:DeleteServlet.java
@WebServlet("/DeleteServlet")
public class DeleteServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
        // リクエストパラメータの取得
		String text = request.getParameter("text");

		ServletContext application = this.getServletContext();
		List<TodoBeans> todoList = (List<TodoBeans>) application.getAttribute("todoList");

        // リストのインデックス番号を取得
		int listIndex = 0;
		for (int i = 0; i < todoList.size(); i++) {
			if (todoList.get(i).getText().equals(text))
				listIndex = i;
		}
        // タスクを削除
		todoList.remove(listIndex);
		application.setAttribute("todoList", todoList);

        // フォワード
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/todo.jsp");
		dispatcher.forward(request, response);
	}
}
```
削除ボタンが押下されたタスクの内容でリストのインデックス番号を取得し、インデックス番号が小さいものから順にtodoListから削除しています。


## まとめ
DBには接続せず、スコープを用いることによって、初学者の方もすぐ作れるような簡単なアプリを実装してみました。
Javaの基礎を学習し終えた方で、何かアプリを作ってみたい！という方はサーブレット&JSPを使用した開発を是非一度やってみて下さい！



## 参考文献
下記の文献を参考にさせていただきました。
・スッキリ！Java サーブレット&JSP

## ひとこと
TECH WOMAN KANSAIは、関西を拠点とするコミュニティであり、現在、関西の女性エンジニアが集まる唯一のコミュニティです！
定期的にコミュニティメンバーで集まって勉強会を開催したり、月に1回、いろんなメンバーがQiitaに記事を投稿したりしているので、意欲高く1年間IT企業で働き続けることができました。
コミュニティ内には、いろんな形でITに携わっている方やこれからITで働きたい、という方が沢山いらっしゃいます！
オンラインで勉強会も定期的に開催しているので遠方の方でも気軽に参加していただけると思います:relaxed:

:cherry_blossom:[TECH WOMAN KANSAI Qiita](https://qiita.com/organizations/tech-woman-kansai)
:cherry_blossom:[TECH WOMAN KANSAI connpass](https://tech-woman-kansai.connpass.com/)