Java・ツイッタークローン・タスク管理システム③タスク登録機能をつける

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

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

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



##実行環境
eclipse4.16.0
Tomcat9
Java11

#目次
1.viewの作成
2.DAOの作成
3.サーブレットの作成
4.次回予告

#Viewの作成

こちらは、よくある入力フォームです。

```task-insert.jsp
<body>
<!-- header.jspは最後に作ります-->
<jsp:include page="header.jsp"/>
	<div class="contain">
		<h3>タスク登録</h3>
<!-- task-insert-servletへそれぞれの入力パラメータを渡す-->
		<form action="task-insert-servlet" method="post">
			<table class="form-table" border="1">
	    		<tbody>
		    		<tr>
					    <th>タスク名</th>
					        <td>
					        <div class="input-key">
								<input type="text" class="form-control" name="task_name" size="60" placeholder="入力してください">
							</div>
					    </td>
				   	</tr>
			       	<tr>
			        	<th>カテゴリー</th>
			        	<td>
					        <div class="input-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="input-key">
								<input type="date" name="limit_date" class="form-control" size="60">
							</div>
					    </td>
				   	</tr>
			        <tr>
					    <th>ステータス</th>
				        <td>
					        <div class="input-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>メモ</th>
					        <td>
					        <div class="input-key">
								<input type="text" class="form-control" name="memo" size="60">
							</div>
					    </td>
				   	</tr>
				    <tr>
				        <th><input type="submit" value="登録" class="input-submit"></th>
				        <td></td>
			        </tr>
			    </tbody>
			</table>
	    </form>
	</div>
</body>
```

投稿が完了した時の確認画面です。ここで投稿内容を把握することができます。

```task-insert-comp.jsp
<body>
<%
String task_name = (String)request.getAttribute("task_name");
int category_id = (int)request.getAttribute("category_id");
String category_name = (String)request.getAttribute("category_name");
Date limit_date = (Date)request.getAttribute("limit_date");
String status_code = (String)request.getAttribute("status_code");
String status_name = (String)request.getAttribute("status_name");
String memo = (String)request.getAttribute("memo");

%>
<jsp:include page="header.jsp"/>
	<div class="contain">
		<div class="box">
		  <h3>タスクの登録が完了しました</h3>
		  <p>以下の内容で登録しました</p>
		  <hr>
		  <p>
		  	タスク名：<%=task_name %><br>
		  	カテゴリー：<%=category_id %>：<%=category_name %><br>
		  	期限：<%=limit_date %><br>
		  	ステータス：<%=status_code %>：<%=status_name %><br>
		  	メモ：<%=memo %><br>
		  </p>
		  <a href="menu.jsp">メニューへ戻る</a>
		</div>
	</div>
</body>
```

投稿に失敗した時の表示です。
特に入力エラーではどの箇所に誤りがあったのかを表示します。

```task-insert-failure.jsp
<body>
<!-- リクエストスコープのerrorには入力に誤りがあった理由がリスト化されているので、これを受け取る-->
<%
List<String> error = (List<String>)request.getAttribute("error");
%>
	<jsp:include page="header.jsp"/>
	<div class="contain">
		<div class="box">
		  	<h3>タスクの登録に失敗しました</h3>
		  	<hr>
		  	<p>*下記の原因が考えられます</p>
		  	<ul>
<!-- errorを表示させていく-->
<%for(String er : error){ %>
		  		<li><%=er %></li>
<%} %>
		  </ul>
		  <a href="task-insert.jsp">登録画面へ戻る</a>
		</div>
	</div>
</body>


```

#DAOの作成
まずは、タスク登録用のメソッドを作成します。

```model.dao.TaskDAO.java
/**
	 * タスク登録用メソッド
	 * @param task_name
	 * @param category_id
	 * @param limit_date
	 * @param user_id
	 * @param status_code
	 * @param memo
	 * @return　実行件数
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	 public int insertTask(String task_name, int category_id, Date limit_date, String user_id, String status_code, String memo) throws SQLException, ClassNotFoundException {
//SQL文　入力パラメータとuser_idを指定してレコードを作成
		 String sql = "insert into t_task (task_name, category_id, limit_date, user_id, status_code, memo) values(?, ?, ?, ?, ?, ?)";
		 int sum = 0;
//データベースへ接続
		 try(Connection con = ConnectionManager.getConnection();
				 PreparedStatement pstmt = con.prepareStatement(sql)){
			 pstmt.setString(1, task_name);
			 pstmt.setInt(2, category_id);
			 pstmt.setDate(3, limit_date);
			 pstmt.setString(4, user_id);
			 pstmt.setString(5, status_code);
			 pstmt.setString(6, memo);
//更新系SQL文の実行
			 sum = pstmt.executeUpdate();
		 }
		 return sum;
	 }
```
詳しい解説は、第２回のUserDAO.javaと同じです。
ステータスidだけではわかり伝いのでステータス名を表示させたいです。
そこでメソッドを使ってstatus_idを引数にstatus_nameを取得しましょう

```model.dao.StatusDAO.java
public class StatusDAO {
	/**
	 * ステータス名を取得するメソッド
	 * @param status_code
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public String getStatusName(String status_code) throws SQLException, ClassNotFoundException {
		String sql = "select status_name from m_status where status_code = ?";
		String status_name ="不明";

		try(Connection con = ConnectionManager.getConnection();
				PreparedStatement pstmt = con.prepareStatement(sql)){
			pstmt.setString(1, status_code);
			ResultSet res = pstmt.executeQuery();

			while(res.next()) {
				status_name = res.getNString("status_name");
			}
		}
		return status_name;
	}
}
```


詳しい解説は、第２回のUserDAO.javaと同じです。
カテゴリーCodeだけではわかり伝いのでステータス名を表示させたいです。
そこでメソッドを使ってcategory_codeを引数にcategory_nameを取得しましょう

```model.dao.CategoryDAO.java
public class CategoryDAO {
	/**
	 * カテゴリー名を取得するメソッド
	 * @param category_id
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public String getCategoryName(int category_id) throws SQLException, ClassNotFoundException {
		String sql = "select category_name from m_category where category_id = ?";
		String category_name ="不明";

		try(Connection con = ConnectionManager.getConnection();
				PreparedStatement pstmt = con.prepareStatement(sql)){
			pstmt.setInt(1, category_id);
			ResultSet res = pstmt.executeQuery();

			while(res.next()) {
				category_name = res.getNString("category_name");
			}
		}
		return category_name;
	}
```
#サーブレットの作成

```servlet.TaskInsertServlet.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//DAOの生成
		TaskDAO taskdao = new TaskDAO();
		CategoryDAO categorydao = new CategoryDAO();
		StatusDAO statusdao = new StatusDAO();

		//パラメータの取得
		request.setCharacterEncoding("UTF-8");
		String task_name = request.getParameter("task_name");
		String category_id_str = request.getParameter("category_id");
		String limit_date_check = request.getParameter("limit_date");
		String status_code = request.getParameter("status_code");
		String memo = request.getParameter("memo");

		//sessionスコープからログイン中のユーザー情報を取得してuser_idを取得
		HttpSession session = request.getSession();
		String user_id = (String)session.getAttribute("current_user_id");

		//error表示を保存するリスト生成
		List<String> error = new ArrayList<String>();

		//sessionチェック
		boolean sessioncheck = (boolean)session.getAttribute("login");
		if(!sessioncheck) {
			error.add("ログインしてからタスク登録をしてください");
		}

		//入力漏れをチェック
		if(task_name.equals("")) {
			error.add("タスク名が空欄です");
		}
		if(category_id_str.equals("Choose...")) {
			error.add("カテゴリーが選択されていません");
		}
		if(status_code.equals("Choose...")) {
			error.add( "ステータスが選択されていません");
		}
		//期限（limit_date）についてはDate型なので特別
		boolean limit_check;
		limit_date_check = limit_date_check.replace('-', '/');
	    DateFormat format = DateFormat.getDateInstance();
		format.setLenient(false);
		try {
			format.parse(limit_date_check);
			 limit_check = true;
		} catch(Exception e) {
			limit_check = false;
		}
		if(!limit_check) {
			error.add("期限には日付を入力してください");
		}

		//リクエストスコープへエラーを保存
		request.setAttribute("error", error);

		if(task_name != "") {
			try {
				//パラメータ通りに受け取れないもの、つまりカテゴリーと期限（String型でないもの）を変換
				int category_id = Integer.parseInt( category_id_str);
				Date limit_date = Date.valueOf(request.getParameter("limit_date"));

				//insertメソッドによりデータベース処理
				taskdao.insertTask(task_name, category_id, limit_date, user_id, status_code, memo);

				//カテゴリー名・ステータス名を取得
				String category_name = categorydao.getCategoryName(category_id);
				String status_name = statusdao.getStatusName(status_code);

				//リクエストスコープへ登録情報を保存
				request.setAttribute("task_name", task_name);
				request.setAttribute("category_id", category_id);
				request.setAttribute("category_name", category_name);
				request.setAttribute("limit_date", limit_date);
				request.setAttribute("status_code", status_code);
				request.setAttribute("status_name", status_name);
				request.setAttribute("memo", memo);

				RequestDispatcher rd = request.getRequestDispatcher("task-insert-comp.jsp");
				rd.forward(request, response);
			} catch(SQLException | ClassNotFoundException | IllegalArgumentException e) {
				RequestDispatcher rd = request.getRequestDispatcher("task-insert-failure.jsp");
				rd.forward(request, response);
			}
		}else {
			RequestDispatcher rd = request.getRequestDispatcher("task-insert-failure.jsp");
			rd.forward(request, response);
		}
	}
```

#次回予告
今回はタスク登録機能を実装しました
次回は、登録したタスクを一覧表示させたりソート機能をつけたり検索機能をつけてみます。