Java Tomcat 404 エラーとServletの関係


##目次
・はじめに
・環境
・該当ソース
・原因
・終わりに
・参考記事

##はじめに
Java＋JSP＋Servletを使用して、ポートフォリオ作成しています。
初回サーバー起動時に、毎回Tomcat404エラーが出るので調べ、アウトプットも兼ねて記事にしました。

###エラー詳細
サーバー起動後、ログイン画面でログイン情報入力し、
メインメニューへ画面偏移する際に、Tomcat404エラーが出てしまう。

ただ、時間を置き何回か実行すると、
エラーは解消され、正常に画面偏移する。


###Tomcat404エラー
指定したURLに対するファイルが見つからず、表示されるエラー。

考えられる原因として主な事は、

・URLの誤字・脱字
・コンテキストパスの配備
・xmlファイルの配置場所

などがあり、ググった情報を元に調べられることは調べましたが、解決しない…。
（んー:thinking:）

##環境
Java version 1.8.0_231
MySQL 8.0
Tomcat 9.0
Eclipse

##該当ソース
###DAO
```Java:EmployeeDAO.java
package dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import dto.Employee;

//社員テーブルに接続するDAOクラス
public class EmployeeDAO {
private static final String url
="jdbc:mysql://localhost/pcms?serverTimezone=JST";	//URL
private static final String user = "root";	//DBユーザー
private static final String pass = "pw";	//DBパスワード

//ログイン情報に該当する社員を探すメソッド
public Employee findEmployee(int number,String password) {

		Employee employee = null;

		//JDBC読み込み
		try (Connection con = DriverManager.getConnection(url,user,pass)) {

		//データベースからログイン情報を取得するSQL文
		String sql ="select * from db_employee where number = ? and password = ?";
		PreparedStatement ps = con.prepareStatement(sql);

		//プレースホルダに値をセット
		ps.setInt(1,number);
		ps.setString(2,password);

		//SQL文の実行
		ResultSet rs = ps.executeQuery();

		if(rs.next()){

			//データベースから取得した値をセット
			employee = new Employee();
			//社員番号の取得
			employee.setNumber(rs.getInt("number"));
			//氏名の取得
			employee.setName(rs.getString("name"));
			//フリガナの取得
			employee.setHurigana(rs.getString("hurigana"));
			//部署名の取得
			employee.setDepartment(rs.getString("department"));
            }else{
			//該当社員がいなければnullを返す
			return null;
		}

		rs.close();
	    ps.close();

		}catch(SQLException e) {
			e.printStackTrace();
			return null;
	}
	return employee;
}
```
###Servlet

```Java:EmployeeSeach.java

package servlet;

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 javax.servlet.http.HttpSession;

import dao.EmployeeDAO;
import dto.Employee;

//ログイン情報に該当する社員を検索するクラス
@WebServlet("/EmployeeSearch")
public class EmployeeSearch extends HttpServlet{
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    	//ログイン画面から入力された社員番号,パスワードを取得
    	int number = Integer.parseInt(request.getParameter("number"));
    	String password = request.getParameter("password");

    	//該当社員の検索
    	EmployeeDAO ed = new EmployeeDAO();
    	Employee employee = ed.findEmployee(number,password);

    	if(employee != null) {
    		//セッションオブジェクトの生成
    		HttpSession session = request.getSession();
    		//セッションスコープに保存
    		session.setAttribute("employee,employee);
    		session.setAttribute("number",number);

    		//ログイン成功
    		RequestDispatcher rd = request.getRequestDispatcher("mainmenu.jsp");
    		rd.forward(request, response);
    	}else{
    		//ログイン失敗
    		RequestDispatcher rd = request.getRequestDispatcher("login_error.jsp");
    		rd.forward(request, response);
    	}
    }

```

###JSP

```Java:login.jsp.java
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ログイン</title>
</head>
<body>
	<!-- ログイン情報の入力 -->
	<div class="login_screen">
		<form action="./EmployeeSearch"  method="post">	
			<table>
				<tr>
					<td>社員番号</td>	
					<td><input type="text" size="11" name="number" autocomplete="off"></td>
				</tr>																			
				<tr>
					<td>パスワード</td>
					<td><input type="password" size="11" name="password"></td>
				</tr>
			</table>

			<!-- ログインボタン -->
			<div class = "login_button">
				<input type="submit" class="login_button" value="ログイン">
			</div>
		</form>

		<!-- 新規登録メニュー -->
		<!-- コメント -->
		<div class="regist_comment">アカウントを新規作成</div>

		<!-- 新規登録ボタン -->
		<div class = "regist_button">
			<a href="regist_menu.jsp"><input type = "submit" class="regist_button" value = "新規登録"></a>
		</div>

		<!-- 管理者ログイン -->
		<div class = "admin_link">
			<a href="admin_login.jsp">管理者としてログイン</a>
		</div>
	</div>
</body>
</html>
```
##原因
Servletクラス　doGetメソッドに何も定義していなかった…。

```Java:EmployeeSearch.java

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 }

```

###doGet,doPostメソッド
doGetメソッド
ブラウザから要求された時に呼び出される。
例）
ブラウザでURLを入力し、検索。
Getリクエストとなり、サーブレットのdoGet()メソッドが呼び出される。

doPostメソッド
ブラウザからデータを送信された時に呼び出される。
例）
画面上にボタン等を作成して「method=“post”」としてアクセス。
Postリクエストなり、サーブレットのdoPost()メソッドが呼び出される。

リクエストの種類（Get or Post）は、ブラウザ側で決めるため、
Getでリクエストが来るのか、Postでリクエストが来るのかは、サーバ側では制御できない。

どちらでも対応できるように同じ処理をしたいときには、
doGet,doPostメソッドのどちらかに(request, response);を以下のように書くこと。

```Java:EmployeeSearch.java

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
 }

```

上記の事を踏まえ、エラーの原因をまとめると、
EmployeeSearchを動かすためのURLで、"./EmployeeSearch"と入力してアクセスしている。（EclipseでURLを自動入力）
この場合Getリクエストとなり、サーブレットのdoGet()メソッドが呼び出される。

しかし、doGet()メソッドを定義していないので、Tomcat404エラーが発生。

時間の経過、数回実行してエラーが解消されたのは、Postアクセスで確認してしまっているためでした。


##終わりに
サンプルプログラムや書籍を参考に作成していく中、doGet,doPostメソッドについて曖昧な理解だったので、
解決に手間取りましたが、このエラーを通じて理解が深まったのでよかった！

##参考記事
https://www.javadrive.jp/servlet/ini/index3.html
https://kanda-it-school-kensyu.com/java-jsp-servlet-contents/jjs_ch14/jjs_1402/
https://qiita.com/kanataxa/items/522efb74421255f0e0a1