Java Eclipseで動的 Webプロジェクト ユーザー検索 JSTLも導入してます

データベースに登録されたユーザーを、idをもとに検索するような機能の演習です。

全体像のイメージ

f:id:ts0818:20170803211434p:plain

 

作っていく順番

紛らわしいですが、上の図とここでの番号は関係ないです。

全部一度にはできないので、

  1. Viewクラス(jspファイル)を作る
  2. Controllerクラス(Servletファイル)を作る
  3. ViewとController間で遷移できるようにする
  4. Modelクラス(JavaBeansや処理用など)を作る
  5. DAOクラス(DB接続やSQL処理など)を作る
  6. ModelクラスでDAOクラスを利用
  7. ControllerクラスでModelクラスの処理を実行

というような流れで作っていく感じです。 

jspServletの間で遷移できるか

まずは、jspファイルとServletファイルの間で遷移できるようにします。その前に、「ウィンドウ(W)」>「パースペクティブ(R)」>「パースペクティブを開く(O)」>「その他(O)...」をクリック。

f:id:ts0818:20170805205157j:plain

Java EE」を選択し、「OK」をクリック。

f:id:ts0818:20170805205154j:plain

パースペクティブ」が「Java EE」になったら、「プロジェクト・エクスプローラー」の表示も変更しておきます。

f:id:ts0818:20170805222459j:plain

f:id:ts0818:20170805222456j:plainをクリックして、「トップ・レベル要素(T)」>「ワーキング・セット」をクリック。

f:id:ts0818:20170805225704j:plain

 「ワーキング・セット」ごとの表示になりますが、まだワーキング・セットを作成していない場合は、

f:id:ts0818:20170805230036j:plain

ワーキングセットの選択(W)...」をクリックし、

f:id:ts0818:20170805231027j:plain

「新規(N)...」をクリック。

f:id:ts0818:20170805231041j:plain

「ワーキング・セット・タイプ(W):」で「Java」を選択し、「次へ(N)>」をクリック。

f:id:ts0818:20170805231036j:plain

「ワーキング・セット名(W):」を入力し、「ワークスペースの内容(O)...」から、作成するワーキング・セットに追加したいプロジェクトを選択すると、「追加(A)->」が選択できるようになるので、「追加(A)->」し、「完了(F)」をクリック。

f:id:ts0818:20170805231033j:plain

 

「ワーキング・セット」に切り替えたら、「ファイル(F)」>「新規(N)」>「動的 Web プロジェクト」を選択。

f:id:ts0818:20170805205149j:plain

「プロジェクト名(M):」を入力し、「次へ(N)>」をクリック。

f:id:ts0818:20170805205144j:plain

「次へ(N)>」をクリック。

f:id:ts0818:20170805205139j:plain

プロジェクトによって、アノテーションが使えない場合は、「web.xml」を作成する必要がありますが、今回は不要なので、「web.xml デプロイメント記述しの生成(G)」のチェックは付けず、「完了(F)」をクリック。

f:id:ts0818:20170805205816j:plain

で、プロジェクトが追加...されてませんね。これは、今現在、「パッケージ・エクスプローラー」の表示を「ワーキングセット」にしているため(「プロジェクト・エクスプローラー」になっている部分)、「ワーキング・セットにプロジェクトを追加(T)」にチェックをつけていなかったためです。

f:id:ts0818:20170805221805j:plain

ということで、「プロジェクト・エクスプローラー」の

f:id:ts0818:20170805222459j:plain

f:id:ts0818:20170805222455j:plainの部分をクリックし、「ワーキング・セットの選択(W)...」をクリック。

f:id:ts0818:20170805221802j:plain

「ワーキング・セット」を選んで(今回は『Web講座』を選択してます)、「編集(E)...」をクリック。

f:id:ts0818:20170805221759j:plain

左側の「ワークスペースの内容(O):」で、追加したいプロジェクト(今回は『WebSearch』)を選択し、「追加(A)->」をクリック。

f:id:ts0818:20170805221754j:plain

「ワーキング・セットの内容(C):」が追加されたら、「完了(F)」をクリック。

f:id:ts0818:20170805221748j:plain

「OK」をクリック。 

f:id:ts0818:20170805223320j:plain

作成した「WebSearch」プロジェクトが「プロジェクト・エクスプローラー」に追加されました。

f:id:ts0818:20170805223314j:plain

プロジェクト内の、「Javaリソース」>「src」を選択した状態で、「新規(N)」>「サーブレット」を選択。

f:id:ts0818:20170805223310j:plain

Javaパッケージ(K):」、「クラス名(M):」を入力し、「次へ(N)>」をクリック。

f:id:ts0818:20170805223307j:plain

「URL マッピング(U):」を変更すると、ブラウザでアクセスする際のURLを変更できますが、今回はデフォルトの状態で、「次へ(N)>」をクリック。

f:id:ts0818:20170805223304j:plain

スーパークラスからのコンストラクター(C)」のチェックを外し、「完了(F)」 をクリック。

f:id:ts0818:20170805224112j:plain

続いて、jspファイルを作っていきます。まずは、「WebContent」>「WEB-INF」を選択した状態で右クリックし、「新規(N)」>「フォルダー」をクリック。

f:id:ts0818:20170805224107j:plain

「フォルダー名(N):」を入力し、「完了(F)」をクリック。

f:id:ts0818:20170805224103j:plain

続いて、作成したフォルダを選択した状態で、右クリックし、「新規(N)」>「JSPファイル」をクリック。

f:id:ts0818:20170805224100j:plain

「ファイル名(M):」を入力し、「次へ(N)>」をクリック。

f:id:ts0818:20170805224057j:plain

「完了(F)」をクリック。

f:id:ts0818:20170805224835j:plain

jspファイルが作成されます。

f:id:ts0818:20170805224832j:plain

同じ流れで、「searchUserResult.jsp」を作成します。

f:id:ts0818:20170805225124j:plain

ファイルを編集します。 

searchUser.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザー検索</title>
</head>
<body>
  <form action="/WebSearch/SearchUser" method="POST">
    ID: <input type="text" name="id" value="">
    <input type="submit" value="検索">
  </form>
</body>
</html>

searchUserResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ユーザー検索結果</title>
</head>
<body>
  <p>検索結果</p>
</body>
</html>    

 

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;

/**
 * Servlet implementation class SearchUser
 */
@WebServlet("/SearchUser")
public class SearchUser extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//
		String forwardPath = null;
		String action = request.getParameter("action");
		if(action == null) {
			forwardPath = "/WEB-INF/jsp/searchUser.jsp";
		}
	    RequestDispatcher dispatcher = request.getRequestDispatcher(forwardPath);
	    dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/searchUserResult.jsp");
		dispatcher.forward(request, response);
	}
}
   

サーブレットファイルを選択し、「実行(R)」>「サーバーで実行」をクリック。

f:id:ts0818:20170806151626j:plain

「次へ(N)>」をクリック。

f:id:ts0818:20170806151627j:plain

「構成済み(C):」にプロジェクトが追加されてるのを確認し、「完了(F)」をクリック。

f:id:ts0818:20170806151628j:plain

ブラウザで、『http://localhost:8080/プロジェクト名/サーブレットファイル名(拡張子なし)』でアクセスします。(マッピングURLを変更してる場合は、サーブレットファイル名のところをマッピングURLに変更します)

f:id:ts0818:20170806151629j:plain

POST送信の結果(『検索』ボタンを押下 )、searchResult.jspが表示されればOK。

f:id:ts0818:20170806151630j:plain

 

データベースとの連携

jspServlet間の遷移ができたので、データベースからのデータ処理を行うModelクラスとDAOクラスを作成していきます。 

まずは、DAOクラスの作成。「プロジェクト・エクスプローラー」でプロジェクトの中の「src」を選択した状態で右クリックし、「新規(N)」>「クラス」をクリック。

f:id:ts0818:20170806151631j:plain

「パッケージ(K):」、「名前(M):」を入力し、「完了(F)」をクリック。

f:id:ts0818:20170806151632j:plain

daoパッケージに、ConnectionManagerクラス(ConnectionManager.java)ができてます。

f:id:ts0818:20170806151633j:plain

同じ流れで、「DaoException.java」「MemberDao.java」も作成します。

f:id:ts0818:20170806151634j:plain

続いて、Modelクラスの作成。「src」を選択した状態で右クリックし、「新規(N)」>「クラス」をクリック。

f:id:ts0818:20170806151635j:plain

「パッケージ(K):」、「名前(M):」を入力し、「完了(F)」をクリック。

f:id:ts0818:20170806151636j:plain

modelパッケージにUserクラス(User.java)ができます。「プロジェクト・エクスプローラー」の階層がおかしくなっているので、

f:id:ts0818:20170806151637j:plain

f:id:ts0818:20170805222459j:plain

f:id:ts0818:20170805222456j:plainをクリックして、

「プロジェクト表示(R)」の「フラット(F)」「階層(H)」の切り替えをすると整います。(どっちを選んでも大丈夫そうです。)

f:id:ts0818:20170806151638j:plain

「src」の中にパッケージが収まりました。

f:id:ts0818:20170806151639j:plain

同じ流れで、「SearchUserLogic.java」も作成しておきます。

f:id:ts0818:20170806151640j:plain

ファイルを編集。

ConnectionManager.java

package dao;

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

public class ConnectionManager {

	// URL・ユーザ名・パスワードの設定
	private final static String URL = "jdbc:mysql://localhost:3306/webdb?useSSL=false";
	private final static String USER = "root";
	private final static String PASSWORD = "root";
	// コネクションオブジェクト
	private Connection connection = null;

	 // このクラスに唯一のインスタンス
	private static ConnectionManager instance = new ConnectionManager();

	/*
	 * static初期化子
	 */
	static {
		// JDBCドライバのロード
		String drv = "com.mysql.jdbc.Driver";
		try {
			Class.forName(drv);
		} catch (ClassNotFoundException e) {
			System.out.println("ドライバがありません" + e.getMessage());
		}
	}

	/**
	 * コンストラクタ
	 */
	private ConnectionManager() {	}
	/*
	 * インスタンス取得メソッド
	 */
	public static ConnectionManager getInstance() { return instance; }

	/**
	 * DBの接続	 *
	 * @return コネクション
	 * @throws Exception
	 */
	public synchronized Connection getConnection() throws DaoException {
		// 	コネクションの確立
		try {
			connection = DriverManager.getConnection(URL, USER, PASSWORD);
		} catch (SQLException e) {
			connection = null;
			throw new DAOException("[conect]異常", e);
		}
		return connection;
	}

	/**
	 * DBの切断
	 */
	public void closeConnection() throws DaoException{
		try {
			if (connection != null) { 	connection.close(); }
		} catch (SQLException e) {
			throw new DaoException("[closeConnection]異常", e);
		} finally {
			connection = null;
		}
	}
}

DaoException.java

/*
 * DaoException.java
 */

package dao;

/**
 * データアクセスオブジェクト例外
 */
public class DaoException extends Exception {
	/**
	 * @param str
	 * @param th
	 */
	public DaoException(String str, Throwable th) {
		super(str, th);
	}
}

MemberDao.java

package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import model.User;

public class MemberDao {

	private Connection con = null; 	// コネクションオブジェクト
	private Statement stmt = null; 	// ステートメントオブジェクト
	private ConnectionManager cm;

	// Connectionの取得
	private void getConnection() throws DAOException{
		if ( this.con != null ){ return; 	}
		cm = ConnectionManager.getInstance();
		con = cm.getConnection(); // データベースへの接続の取得
	}

  // 全データの取得
	public List allMember() throws DAOException {
		getConnection();
		createStmt();
		List<User> list = new ArrayList<User>();
		// SQLステートメントの実行(参照系)
		try (ResultSet res = stmt.executeQuery("SELECT * FROM member")) {
			// 結果の取得
			while (res.next()) {
				User e = new User();
				e.setId(res.getString("id") );
				e.setName(res.getString("name"));
				e.setPass(res.getString("pass"));

				list.add(e);
			}
			// SQLに関する例外処理
		} catch (SQLException e) {
			throw new DAOException("[MemberDAO#allMember]異常", e);
		}finally {
			close();
		}
		return list;
	}

  //IDで検索する
	public User selectById(String id) throws DAOException{
		//準備
		getConnection();
		createStmt();
		String sql = "SELECT * FROM member WHERE id='" + id + "'";		//SQL組立

		User user= null;
		// SQLステートメントの実行(参照系)
		try (ResultSet res = stmt.executeQuery(sql)){
			boolean countFlg = res.next();
			if ( countFlg) {
				user = new User();
				user.setId(res.getString("id") );
				user.setName(res.getString("name"));
				user.setPass(res.getString("pass"));
			}
		// SQLに関する例外処理
		} catch (SQLException e) {
			throw new DAOException("[MemberDAO#selectById]異常", e);
		} finally {
			close();
		}
		return user;
	}

	// Statementの取得
	private void createStmt() throws DAOException{
		if ( this.stmt != null){ 	return; }
		try {
			stmt = con.createStatement();	 // ステートメント取得
		// SQLに関する例外処理
		} catch (SQLException e) {
			throw new DAOException("[createStmt]異常", e);
		}
	}

	// クローズメソッド
	private void close() throws DAOException {
		try {
			if (stmt != null) { stmt.close(); }
		} catch (SQLException e) {
			throw new DAOException("[closeStatement]異常", e);
		} finally {
			this.stmt = null;
			this.cm = null;
		}
	}
}

modelパッケージ

User.java

package model;

public class User {

  private String id;
  private String name;
  private String pass;

  public User(){}
  public User(String id, String name, String pass) {
    this.id = id;
    this.name = name;
    this.pass = pass;
  }

  public String getId() {
    return this.id;
  }

  public String getName() {
    return this.name;
  }

  public String getPass() {
    return this.pass;
  }

  public void setId(String id) {
	this.id = id;
  }

  public void setName(String name) {
	this.name = name;
  }

  public void setPass(String pass) {
	this.pass = pass;
  }

}

SearchUserLogic.java

package model;

import java.util.ArrayList;
import java.util.List;

import dao.DaoException;
import dao.MemberDao;

public class SearchUserLogic {

	public List<User> exute(User user){

		String id = user.getId();

		List<User> list = new ArrayList<User>();

		MemberDao dao = new MemberDao();

		try{
			if(id != "" && id != null){
				user = dao.selectById(id);
				list.add(user);
			}else{
				list = dao.allMember();
			}
		} catch (DaoException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}

		//登録処理
		return list;
	}
}

実際にサーブレットでModelクラスの処理を実行。SearchUser.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;

/**
 * Servlet implementation class SearchUser
 */
@WebServlet("/SearchUser")
public class SearchUser extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//
		String forwardPath = null;
		String action = request.getParameter("action");
		if(action == null) {
			forwardPath = "/WEB-INF/jsp/searchUser.jsp";
		}
	    RequestDispatcher dispatcher = request.getRequestDispatcher(forwardPath);
	    dispatcher.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		List<User> list = new ArrayList<User>();
		// 
		String id = request.getParameter("id");
		User user = new User(id,"","");

		UserSearchLogic logic = new UserSearchLogic();
		list = logic.exute(user);

		request.setAttribute("members", list);
		
		//
		RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/searchUserResult.jsp");
		dispatcher.forward(request, response);
	}
}

jspファイルも編集。 また、jspファイルでjstl(JavaServer Pages Standard Tag Library)という外部ライブラリを使いたいので、http://tomcat.apache.org/download-taglibs.cgi にアクセスし、jarファイルをダウンロードします。バージョンを選びたい場合は、「Archive」を選択してください。

f:id:ts0818:20170806193809j:plain

「Impl」「Spec」「EL」の3つをダウンロードすれば良いみたいです。 (Java講座では講師の先生が1つのjarファイルにしてくれてたけど、1つのファイルにまとめるやり方が分からないので、3つをそのまま使います。)

ちなみに、アプリケーションサーバーにTomcatを使っていない場合は、ここのjarファイルでは動かないかもです。

f:id:ts0818:20170806193810j:plain

「Binary README」にjstlに必要な条件が記載されており、

LIBRARY DEPENDENCIES

This version of the Standard Tag Library has the following runtime
dependencies:

   1. Dependencies provided by a JSP 2.1 container:
      - Java 1.5 or later
      - Servlet 2.5 or later
      - JSP 2.1 or later

   2. Additional dependencies
      - The XML tag library requires Apache Xalan 2.7.1 or later

---
Apache Xalan 2.7.1

To address performance issues with XSLT processing, this version relies on
implementation specific functionality from Apache Xalan. The following
libraries should be included in the classpath for your application:
   - xalan-2.7.1.jar
   - serializer-2.7.1.jar

---------------------------------------------------------------------------
ADD DEPENDENCIES TO A WEB APPLICATION

To use this distribution with your own web applications, add the following JAR
files to the '/WEB-INF/lib' directory of your application:
   - taglibs-standard-spec-1.2.5.jar
   - taglibs-standard-impl-1.2.5.jar
   - taglibs-standard-jstlel-1.2.5.jar
   - xalan-2.7.1.jar
   - serializer-2.7.1.jar


---------------------------------------------------------------------------
USING JSTL TAGS FROM A JSP

The JSTL tag library can be imported into your pages with the following directives:

  CORE LIBRARY
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

  XML LIBRARY
    <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

  FMT LIBRARY 
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

  SQL LIBRARY
    <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

  FUNCTIONS LIBRARY
    <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
   

となっていました。Servletjspのバージョンを調べるには、jspファイルに

Working with server: <%= application.getServerInfo() %><br>
Servlet Specification: <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %><br>
JSP version: <%= JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion() %><br>

を記述すれば良いようです。ブラウザに表示したくない場合は、System.out.println()でそれぞれ出力すれば、コンソールで確認できます。

Servlet、JSPのバージョン確認方法 : kubazaruのブログ

⇩  アプリケーションサーバーがTomcatの場合は下記で一覧表が確認できます

Apache Tomcat® - Which Version Do I Want?

 

ダウンロードしたjarファイルをEclipseの「プロジェクト・エクスプローラー」のプロジェクトの中の、「WebContent」>「WEB-INF」>「lib」に配置します。

f:id:ts0818:20170806193812j:plain

jspファイルを編集。searchUserResult.jspだけ変更します。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>検索結果</title>
</head>
<body>
<table>
  <tr>
    <th>id</th>
    <th>name</th>
    <th>pass</th>
  </tr>
<c:forEach var="member" items="${members}">
  <tr>
    <td>${member.id }</td>
    <td>${member.name}</td>
    <td>${member.pass }</td>
  </tr>
</c:forEach>

</table>
<a href="/Web/SearchUser">戻る</a>

</body>
</html>

 

 MySQLデータベースをEclipseの動的Webプロジェクトで使えるようにします。(今回、webdbデータベースにmemberテーブルを作成しています。)

f:id:ts0818:20170806161557j:plain

f:id:ts0818:20170806161558j:plain

初回実行時で、クラスパスにJDBCドライバを追加する必要があります。

f:id:ts0818:20170806193813j:plain

「クラスパス」タブを選択した状態で、「外部 JAR の追加(X)...」をクリック。

f:id:ts0818:20170806193814j:plain

JDBCドライバ(自分の場合は、『C:¥Program Files (x86MySQL¥Connector.J 5.1¥mysql-connector-java-5.1.41-bin.jar』)を選択。

f:id:ts0818:20170806193815j:plain

「クラスパス」に追加されたら、「実行(R)」をクリック。

f:id:ts0818:20170806193816j:plain

⇩  クラスの読み込みについては下記サイトが詳しいです

自力でNoClassDefFoundErrorを解決!(前半) | 株式会社シンメトリック公式ブログ |

自力でNoClassDefFoundErrorを解決!(後半) | 株式会社シンメトリック公式ブログ |

 

ブラウザで、『http://localhost:8080/WebSearch/SearchUser』にアクセス。

f:id:ts0818:20170806193817j:plain

何も入力せず『検索』ボタンを押すと、webdbデータベースのmemberテーブルのデータを全件取得し表示します。

f:id:ts0818:20170806193818j:plain

1件しかデータが無かったので分かりづらいと思いますが....。

f:id:ts0818:20170806193819j:plain

 

とりあえず、なんとか動いているようです。