Java・ツイッタークローン・タスク管理システム④タスク一覧表示をする

##はじめに
Javaを使って初めてアプリケーションを作成する人にむけて記事を書いてみようと思います。
ポートフォリオや、会社の研修課題作成の参考にしていただければ幸いです。
今回は、タスクマネージャーを作成します。
これを応用することで、ツイッタークローンの作成にも活かすことができます。

アプリケーションの機能ごとに記事を投稿していきます。
1.データベース作成
2.ログイン機能
3.タスクの登録機能
4.一覧表示
　　-ソート機能
　　-検索機能
5.編集機能
6.削除機能
7.排他制御について

＊詳しい説明はコード内に書いてありますので、コピペする人は消して使ってください

##実行環境
eclipse4.16.0
Tomcat9
Java11

#目的
1.viewの作成
2.DAOの作成（一覧表示・ソート）
3.サーブレットの作成（一覧表示・ソート）
4.DAOの作成（検索機能）
5.サーブレットの作成（検索機能）
6.次回予告

#viewの作成
検索フォームとタスク一覧テーブルを作っていく

```
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.List, model.entity.TaskBean, model.entity.UserBean, model.dao.UserDAO, model.dao.CategoryDAO, model.dao.StatusDAO"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>タスク一覧</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/task-list.css">
</head>
<body>
<%
List<TaskBean> tasklist = (List<TaskBean>) request.getAttribute("tasklist");
UserDAO userdao = new UserDAO();
CategoryDAO categorydao = new CategoryDAO();
StatusDAO statusdao = new StatusDAO();
String error = (String)request.getAttribute("error");
%>
<!-- *****************検索フォーム**********************-->
<jsp:include page="header.jsp"/>
	<div class="contain">
		<h3>しぼりこみ検索</h3>
		<form action="task-search-servlet" method="post">
		<table class="form-table search-table">
    		<tbody>
	    		<tr>
				    <th>タスク名で絞り込み</th>
				        <td>
				        <div class="search-key">
							<input type="text" class="form-control" name="task_name">
						</div>
				    </td>
			   	</tr>
		       	<tr>
		        	<th>カテゴリーで絞り込み</th>
		        	<td>
				        <div class="search-key">
				      		<select class="form-control" name="category_id">
				        		<option selected>Choose...</option>
				        		<option value="1">新商品A：開発プロジェクト</option>
				        		<option value="2">既存商品B:改良プロジェクト</option>
				      		</select>
					    </div>
				    </td>
			    </tr>
		        <tr>
				        <th>ステータスで絞り込み</th>
				        <td>
				        <div class="search-key">
			      			<select class="form-control" name="status_code">
			        			<option selected>Choose...</option>
			        			<option value="00">未着手</option>
			        			<option value="50">着手</option>
			        			<option value="99">完了</option>
			     		 	</select>
			    		</div>
			        </td>
		        </tr>
			    <tr>
			        <th><input type="submit" value="検索" class="search-button"></th>
			        <td>
			        </td>
		        </tr>
		    </tbody>
		</table>
	  	</form>
<!-- *****************タスク一覧テーブル（テーブル無いの▼ボタンでソートする）*********-->  
		<h3>タスク一覧</h3>
<%if(error != null){ %>
		<p class="error"><%=error %></p>
<%} %>
		<div class="table-wrapper">
			<table class="list-table" border="1">
		  		<thead>
					<tr class="table-header">
						<th class="fixed01">
							<div class="title">タスクID</div>
							<div class="sort-box" >
								<form action="task-list-servlet" method="post" class="sort-form">
									<input type="submit" value="▲" class="sort">
								</form>
								<form action="task-order-by-id-desc" method="post" class="sort-form">
									<input type="submit" value="▼" class="sort">
								</form>
							</div>
						</th>
						<th class="fixed01"><div class="title">タスク名</div></th>
						<th class="fixed01">
							<div class="title">カテゴリー</div>
							<form action="task-order-by-category-servlet" method="post" class="sort-form">
								<input type="submit" value="▲" class="sort">
							</form>
							<form action="task-order-by-category-desc" method="post" class="sort-form">
								<input type="submit" value="▼" class="sort">
							</form>
						</th>
						<th class="fixed01">
							<div class="title">期限</div>
							<form action="task-order-by-limit-servlet" method="post" class="sort-form">
								<input type="submit" value="▲" class="sort">
							</form>
							<form action="task-order-by-limit-desc" method="post" class="sort-form">
								<input type="submit" value="▼" class="sort">
							</form>
						</th>
						<th class="fixed01">
							<div class="title">ユーザ</div>
							<form action="task-order-by-user-servlet" method="post" class="sort-form">
								<input type="submit" value="▲" class="sort">
							</form>
							<form action="task-order-by-user-desc" method="post" class="sort-form">
								<input type="submit" value="▼" class="sort">
							</form>
						</th>
						<th class="fixed01">
							<div class="title">ステータス</div>
							<form action="task-order-by-status-servlet" method="post" class="sort-form">
								<input type="submit" value="▲" class="sort">
							</form>
							<form action="task-order-by-status-desc" method="post" class="sort-form">
								<input type="submit" value="▼" class="sort">
							</form>
						</th>
						<th class="title fixed01">メモ</th>
						<th class="title fixed01">登録日時</th>
						<th class="title fixed01">更新日時</th>
						<th colspan="3" class="title fixed01">タスク管理</th>
					</tr>
				</thead>
				<tbody>
	<%
	for(TaskBean task : tasklist){
		String user_name = userdao.getUserName(task.getUser_id());
		String category_name = categorydao.getCategoryName(task.getCategory_id());
		String status_name = statusdao.getStatusName(task.getStatus_code());
	%>
					<tr >
						<td class="parameter"><%=task.getTask_id() %></td>
						<td class="parameter"><%=task.getTask_name() %></td>
						<td class="parameter"><%=task.getCategory_id() %>：<%=category_name %></td>
						<td class="parameter"><%=task.getLimit_date() %></td>
						<td class="parameter"><%=user_name %></td>
						<td class="parameter"><%=task.getStatus_code() %>：<%=status_name %></td>
						<td class="parameter"><%=task.getMemo() %></td>
						<td class="parameter"><%=task.getCreate_datetime() %></td>
						<td class="parameter"><%=task.getUpdate_datetime() %></td>
						<td class="parameter">
							<form action="task-update-detail-servlet" method="post">
								<input type="hidden" name="task_id" value="<%=task.getTask_id() %>">
								<button type="submit" class="task-button">更新</button>
							</form>
						</td>
						<td class="parameter">
							<form action="task-delete-detail-servlet" method="post">
								<input type="hidden" name="task_id" value="<%=task.getTask_id() %>">
								<button type="submit" class="task-button">削除</button>
							</form>
						</td>
						<td class="parameter">
							<form action="comment-detail-servlet" method="post">
								<input type="hidden" name="task_id" value="<%=task.getTask_id() %>">
								<button type="submit" class="task-button">コメント</button>
							</form>
						</td>
					</tr>
	<%
	}
	%>
				</tbody>
			</table>
		</div>
	</div>
</body>
</html>

```

#DAOの作成（一覧表示・ソート）
このSQL文のt_taskとなっている部分をcategory_idやlimit_dateなどに変えることで簡単にソート用のSQL文はできます。
今回は、task_id, limit_date, category_id, status_code, user_id順でソートできるようにしました。

```model.dao.TaskDAO.java
	/**
	 * タスクの一覧表示
	 * @return tasklist
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	//タスクID順
	public List<TaskBean> getTaskList() throws SQLException, ClassNotFoundException{
		String sql = "select * from t_task";
		List<TaskBean> tasklist = new ArrayList<TaskBean>();

		try(Connection con = ConnectionManager.getConnection();
				Statement stmt = con.createStatement();
				ResultSet res = stmt.executeQuery(sql)){
				//取得したSQLのカラムを順番にタスクオブジェクトへ格納していく。最後にtasklistへ追加する
				while(res.next()) {
					TaskBean task = new TaskBean();
					task.setTask_id(res.getInt("task_id"));
					task.setTask_name(res.getString("task_name"));
					task.setCategory_id(res.getInt("category_id"));
					task.setLimit_date(res.getDate("limit_date"));
					task.setUser_id(res.getString("user_id"));
					task.setStatus_code(res.getString("status_code"));
					task.setMemo(res.getString("memo"));
					task.setCreate_datetime(res.getTimestamp("create_datetime"));
					task.setUpdate_datetime(res.getTimestamp("update_datetime"));

					tasklist.add(task);
				}
		}
		return tasklist;
	}
	//逆
		public List<TaskBean> getTaskListOrderByIdDesc() throws SQLException, ClassNotFoundException{
			String sql = "select * from t_task order by task_id desc";
			List<TaskBean> tasklist = new ArrayList<TaskBean>();
			try(Connection con = ConnectionManager.getConnection();
					Statement stmt = con.createStatement();
					ResultSet res = stmt.executeQuery(sql)){
					//取得したSQLのカラムを順番にタスクオブジェクトへ格納していく。最後にtasklistへ追加する
					while(res.next()) {
						TaskBean task = new TaskBean();
						task.setTask_id(res.getInt("task_id"));
						task.setTask_name(res.getString("task_name"));
						task.setCategory_id(res.getInt("category_id"));
						task.setLimit_date(res.getDate("limit_date"));
						task.setUser_id(res.getString("user_id"));
						task.setStatus_code(res.getString("status_code"));
						task.setMemo(res.getString("memo"));
						task.setCreate_datetime(res.getTimestamp("create_datetime"));
						task.setUpdate_datetime(res.getTimestamp("update_datetime"));

						tasklist.add(task);
					}
			}
			return tasklist;
		}

```


#サーブレットの作成（一覧表示・ソート）
まず、menu画面から遷移した時に表示されるものです。
ログインしていないと一覧が表示されないようになっています。

```servlet.TaskListServlet.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		TaskDAO dao = new TaskDAO();

		try {
			HttpSession session = request.getSession();
			boolean logincheck = (Boolean)session.getAttribute("login");
			if(logincheck) {
				//取得した全タスクをリクエストスコープへ保存する
				List<TaskBean> tasklist = dao.getTaskList();
				request.setAttribute("tasklist", tasklist);

				//転送する
				RequestDispatcher rd = request.getRequestDispatcher("task-list.jsp");
				rd.forward(request, response);
			}

		} catch(SQLException | ClassNotFoundException | NullPointerException e) {
			e.printStackTrace();
			RequestDispatcher rd = request.getRequestDispatcher("login.html");
			rd.forward(request, response);
		}
```

次に、各ソートボタンを押した時に送られるサーブレットの例です
TaskDAO.javaで定義したソート用のメソッド達ごとに、サーブレットを作っていきます。
例えばこれは、task_idの降順にタスクを取得するサーブレットです。

```TaskOrderByIdDesc.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		TaskDAO dao = new TaskDAO();
		List<TaskBean> tasklist = null;
		try {
//ここの部分で使用するメソッドを変えるだけです。
			tasklist = dao.getTaskListOrderByIdDesc();
		} catch(SQLException | ClassNotFoundException e) {
			e.printStackTrace();
		}

		request.setAttribute("tasklist", tasklist);
		RequestDispatcher rd = request.getRequestDispatcher("task-list.jsp");
		rd.forward(request, response);
	}
```

以上で、タスクの一覧表示とソート機能は完成です。

次に、検索機能を実装していきます。

#DAOの作成（検索機能）
検索機能は、task_name, category_id, status_codeで絞り込みができるようにしていきます。

```
	/**
	 * 検索メソッド
	 * @param task_name
	 * @param category_id
	 * @param status_code
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public List<TaskBean> searchTask(String task_name, int category_id, String status_code) throws SQLException, ClassNotFoundException{
		//SQL文（全ての検索フォームが埋められた時に使うもの）
		String sql = "select * from t_task where task_name like ? and category_id = ? and status_code = ?";
		//それぞれの検索項目について、選ばれたものだけを使うSQL文を作成
		if(category_id == 0 && status_code == "0") {
			sql = "select * from t_task where task_name like ?";
		}else if(category_id ==0) {
			sql = "select * from t_task where task_name like ? and status_code = ?";
		}else if(status_code == "0") {
			sql = "select * from t_task where task_name like ? and category_id = ?";
		}

		List<TaskBean> tasklist = new ArrayList<TaskBean>();
		try(Connection con = ConnectionManager.getConnection();
				PreparedStatement pstmt = con.prepareStatement(sql)){
      //先ほどと同じように、それぞれの検索項目について、選ばれた物だけを使うSQL文にそぐう形で引数を代入指定いく
			if(category_id == 0 && status_code == "0") {
				pstmt.setString(1, task_name);
			}else if(category_id ==0) {
				pstmt.setString(1, task_name);
				pstmt.setString(2, status_code);
			}else if(status_code == "0") {
				pstmt.setString(1, task_name);
				pstmt.setInt(2, category_id);
			}else {
				pstmt.setString(1, task_name);
				pstmt.setInt(2, category_id);
				pstmt.setString(3, status_code);
			}

			ResultSet res = pstmt.executeQuery();
			//取得したSQLのカラムを順番にタスクオブジェクトへ格納していく。最後にtasklistへ追加する
			while(res.next()) {
				TaskBean task = new TaskBean();
				task.setTask_id(res.getInt("task_id"));
				task.setTask_name(res.getString("task_name"));
				task.setCategory_id(res.getInt("category_id"));
				task.setLimit_date(res.getDate("limit_date"));
				task.setUser_id(res.getString("user_id"));
				task.setStatus_code(res.getString("status_code"));
				task.setMemo(res.getString("memo"));
				task.setCreate_datetime(res.getTimestamp("create_datetime"));
				task.setUpdate_datetime(res.getTimestamp("update_datetime"));

				tasklist.add(task);
			}
		}
		return tasklist;
	}
```


#サーブレットの作成（検索機能）
コメントをみながらやってみてください。


```
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		TaskDAO taskdao = new TaskDAO();
		List<TaskBean> tasklist = new ArrayList<TaskBean>();

		//リクエストパラメータ取得
		request.setCharacterEncoding("UTF-8");
		String task_name = request.getParameter("task_name");
		String category_id_str = request.getParameter("category_id");
		String status_code = request.getParameter("status_code");

		//入力漏れをチェック
		if(category_id_str.equals("Choose...")) {
			category_id_str = "0";
		}
		if(status_code.equals("Choose...")) {
			status_code = "0";
		}

		task_name = "%" + task_name + "%";

		//category_idをint型へ戻す
		int category_id = Integer.parseInt(category_id_str);

		try {
			//絞り込み内容から検索
			tasklist = taskdao.searchTask(task_name, category_id, status_code);

			//もしtasklistが0件ならエラー画面を表示
			if(tasklist.size() == 0) {
				String error = "検索結果は0件です";
				request.setAttribute("error", error);
			}

		}catch(SQLException | ClassNotFoundException e) {
			e.printStackTrace();
			RequestDispatcher rd = request.getRequestDispatcher("task-list-servlet");
			rd.forward(request, response);
		}
		request.setAttribute("tasklist", tasklist);
		RequestDispatcher rd = request.getRequestDispatcher("task-list.jsp");
		rd.forward(request, response);
	}
```

6.次回予告
今回は、タスク一覧の表示とその処理についてやってまいりました。
次回は、そのタスクリストから遷移することができるタスクの編集機能についてまとめてまいります。