★以下「前提条件」をクリア済みだとスムーズに作業が進みます。
##前提条件
・Javaの実行環境がそろっている(環境変数設定ができている)
→わからない人は以下の様な資料が参考になります。
https://eng-entrance.com/java-install-env
それでもわからない場合は自力で調べるか他の人に聞きましょう。
・Mavenが導入されている。
→以下の資料を参考にする場合「3.2. Mavenプラグインの設定」までを実行します。
「2.2. プロキシの設定」は現時点ではやらないでください。
https://qiita.com/tarosa0001/items/e5667cfa857529900216
・MySQLが導入されている。
→以下の様な資料が参考になります。
https://qiita.com/FORTE/items/d31e7054aa89ba467f90
この資料の最後の「文字コードの設定」はファイルの実行権限がないため、
編集できない場合があります。
その場合は以下の様な資料を参考にして、権限を変えましょう。
https://qiita.com/murashi/items/708acd6b37aaf46b4fec
・Githubのアカウントがある。
→作成方法は以下の様な資料が参考になります。
https://qiita.com/okumurakengo/items/848f7177765cf25fcde0
・Herokuのアカウントがある。
→作成方法は以下の様な資料が参考になります。
https://programmingnavi.com/1438/
・HerokuCLIの導入。
→作成方法は以下の様な資料が参考になります。
https://devcenter.heroku.com/articles/heroku-cli
・Herokuにクレカ登録ができている。
→登録方法は以下の様な資料が参考になります。
https://wp.developapp.net/?p=5250
・HerokuにてJavaビルドパックを導入。
→以下の資料では「Heroku側の下準備」が参考になります。
それ以外は今はやらないほうがいいです。
https://qiita.com/norihiko_tokudaiji/items/eb7c067b77757b20d113
##動的WEBプロジェクトの作成
いよいよ開発です(*‘ω‘ *)
・Eclipseにて「ファイル」→「新規」→「動的WEBプロジェクト」をクリック。すると以下の様な画面になります。
・以下を入力または選択し「完了」を押下します。
→プロジェクト名:TestApp
→ターゲット・ランタイム:Tomcat8(Java8)
※Tomcat(Java)のバージョンは特に指定がない場合は”8”を指定しましょう。
この後使うHerokuのサポートが8推奨だからです。
・以下の様な画面になればプロジェクト作成は成功です
##必要なファイルを作成していく
今回は以下の様なログイン画面を作成していきます。
必要なファイルとその役割は以下の通り。
●JSP(作成方法は→https://sukkiri.jp/technologies/ides/eclipse/jsp_create.html)
・index.jsp
→Webcontent直下に配備。
プロジェクト実行時に自動的にこのファイルが起動する。
・Webcontent/WEB-INF/jsp/login.jsp
・Webcontent/WEB-INF/jsp/loginFail.jsp
・Webcontent/WEB-INF/jsp/mainPage.jsp
→3つまとめましたがまず、WEB-INF直下に***”jspフォルダ”を作成します。
そのあと3つのjspファイルを作成します。
それぞれのファイルの説明ですが、login.jspはログインページ、mainPage.jspはログインが成功されたときに表示されるメインページ、loginFail.jspはログインが失敗したとき*に表示されるページです。
●Servlet(作成方法は→https://sukkiri.jp/technologies/ides/eclipse/servlet_create.html)
・LoginServlet.java
→ログインページの呼び出しと、DBへの接続メソッド呼び出し。
●javaクラスファイル(作成方法は→https://sukkiri.jp/technologies/ides/eclipse/class_create.html)
・model/User.java
→パッケージ:model
ユーザ情報のゲッターとセッター。JavaBeanzに当たる。
・model/CheckUserLogic.java
→パッケージ:model
DAOを呼び出すためのクラス。
Servletから直でDAOを呼び出してもいいのだけど、ワンクッション挟む方が無難らしい。
Ruby(Rails)だとあまりやないけど、ServletがControllerでDAOがmodelファイルみたいな感じだと思う。この場合だとModelに直接処理を書いてるみたいなイメージで思っている。
・dao/UserDAO.java
→パッケージ:dao
DAOはDBとのやり取りをするクラス。
事実上MVCのMに当たりそう。
●その他ファイル
・Procfile
→プロジェクトフォルダー直下に配備。今回ならTestApp直下。
ちなみにこのファイルはWEB公開するときに必要で、
ここに記載されているwarファイルを読み込むことで、本番環境でアプリが起動される。
とりあえず今のところはこんな感じです。
文章だけだとわかりづらいので以下の画面も参照しながら、確実に作成しましょう。
##作成したファイルにコードを書いていく。
<%@ 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>TestApp</title>
</head>
<body>
<div>
<h1>ようこそ ゲスト さん</h1>
<a href="./LoginServlet">ログインページへ>></a>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TestApp</title>
</head>
<body>
<div>
<h3>Login</h3>
<form action="./LoginServlet" method="post">
<p>・ニックネーム:</p>
<input type="text" name="nickName">
<p>・パスワード:</p>
<input type="password" name="password">
<button type="submit">Login</button>
</form>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TestApp</title>
</head>
<body>
<div>
<h3>Login</h3>
<p style="color:red;">入力に誤りがあります。</p>
<form action="./LoginServlet" method="post">
<p>・ニックネーム:</p>
<input type="text" name="nickName">
<p>・パスワード:</p>
<input type="password" name="password">
<button type="submit">Login</button>
</form>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="model.User" %>
<% User findedUser = (User) request.getAttribute("findedUser"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TestApp</title>
</head>
<body>
<div>
<h3>メインページ</h3>
<p>ようこそ<strong><%= findedUser.getNickName() %></strong>さん</p>
</div>
</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;
import model.CheckUserLogic;
import model.User;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/login.jsp");
dispatcher.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// jspから送られた値を取得
String nickName = request.getParameter("nickName");
String password = request.getParameter("password");
// userインスタンスを生成しつつ、コントラスタを動かす。
User user = new User(nickName, password);
// CheckUserLogicインスタンスを生成。
CheckUserLogic checkUser = new CheckUserLogic();
// executeメソッドの処理結果を新たに変数に入れる。入る値はnullかDAOで生成した新たなUserインスタンス。
User findedUser = checkUser.execute(user);
// findedUserの処理結果に応じて表示するViewを選定する。
if (findedUser != null) {
// Userインスタンスが入っていれば、結果をリクエストパラメータにセットしmainPageを表示する。
request.setAttribute("findedUser", findedUser);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/mainPage.jsp");
dispatcher.forward(request, response);
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/loginFail.jsp");
dispatcher.forward(request, response);
}
}
}
package model;
import java.io.Serializable;
public class User implements Serializable {
private String nickName;
private String password;
public User() {
}
public User(String nickName, String password) {
this.nickName = nickName;
this.password = password;
}
public String getNickName() {
return nickName;
}
public String getPassword() {
return password;
}
}
package model;
import dao.UserDAO;
public class CheckUserLogic {
public User execute(User user) {
UserDAO dao = new UserDAO();
return dao.findUser(user);
}
}
package dao;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import model.User;
public class UserDAO {
private static Connection getConnection() throws URISyntaxException, SQLException {
// heroku configに設定されている値を取得。
URI dbUri = new URI(System.getenv("CLEARDB_DATABASE_URL"));
// :をデリミタとして必要な情報を抜き取る。
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
// JDBC用のURLを生成。
String dbUrl = "jdbc:mysql://" + dbUri.getHost() + dbUri.getPath();
return DriverManager.getConnection(dbUrl, username, password);
}
public User findUser(User user) {
User findedUser = null;
try {
// ドライバの読み込み。
Class.forName ("com.mysql.cj.jdbc.Driver");
// データベースへ接続のためprivateメソッドを呼び出す。
try(Connection conn = getConnection()) {
// SELECT文を準備。
String sql = "SELECT * FROM account WHERE nickname = ? AND password = ?";
PreparedStatement pStmt = conn.prepareStatement(sql);
pStmt.setString(1, user.getNickName());
pStmt.setString(2, user.getPassword());
// SELECTを実行し、結果表を取得。
ResultSet rs = pStmt.executeQuery();
// 一致したユーザーが存在した場合、
// そのユーザーを表すfindedUserインスタンスを生成。
if (rs.next()) {
// 結果表からデータを取得
String nickName = rs.getString("nickname");
String password = rs.getString("password");
findedUser = new User(nickName, password);
}
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
return null;
}
return findedUser;
}
}
web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT target/*.war
・書き込んだら、サーバを追加(Tomcat8)しプロジェクトを実行しましょう。
サーバの追加方法→https://sukkiri.jp/technologies/ides/eclipse/server_add.html
プロジェクトの実行
→「プロジェクトを右クリック」→「実行」→「サーバで実行」
##Mavenプロジェクトに変換。
デプロイするためにはMavanは必須です。
Mavenの説明→https://qiita.com/ASHITSUBO/items/6c2aa8dd55043781c6b4
・プロジェクトを「右クリック」→「構成」→「Mavenプロジェクトに変換」をクリック。
すると以下の様な画面になります。
もし変更したい場合は以下の様な記事が参考になります。
https://itsakura.com/java-eclipse-maven
ちなみに、グループIdは何とかなりますが、アーティファクトIdを変更すると後々面倒です。
アプリ自体のURLが書き換わるので、Servletなどのリンクを書き直す必要があります。
当方はこれでかなり苦しみました
##pom.xmlの編集。
Mavenに変更するとpom.xmlというファイルがプロジェクト直下に出来上がっていると思います。
これを以下の様に変更しましょう。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<!--javaxを読込めるようにする-->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<!--ASMの導入。(http://atmarksharp.v01.jp/posts/asm-java-bytecode-generator.html)-->
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>6.1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
<!-- アプリ依存のjarファイルを作成するためのプラグイン -->
<!-- https://devcenter.heroku.com/articles/deploying-java -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals><goal>copy</goal></goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.github.jsimone</groupId>
<artifactId>webapp-runner</artifactId>
<version>9.0.27.0</version>
<destFileName>webapp-runner.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
・pom.xmlを「右クリック」→「実行」→「Maven clean」を実行。
「BUILD SUCCESS」が出ていればOKです。(表示例は以下画像参照)
・続いて同じく「Maven install」を実行します。
こちらも「BUILD SUCCESS」が出ていればOKです。
・この「Maven clean」「Maven install」の作業をプロジェクトに対しても実行しましょう。
##Githubにコードをアップする。
Eclipseで作成したプロジェクトをGithub上にアップします。
・以下「Github 上で新規リポジトリを作成する」を参考にしましょう。
またリポジトリ名はアプリと同じ名前(TestApp)にするとわかりやすいでしょう。
https://qiita.com/cotrpepe/items/7cafaacb538425a78f1f
・プロジェクトをコミットします。
「プロジェクト右クリック」→「チーム」→「コミット」すると以下の様な画面になるので「++」ボタンを押下します。
・コミットメッセージに「first commit」と入力し「コミットおよびプッシュ」を押下すると以下の様な画面になります。
・「URI」にGithubで作成したリポジトリーのURLを貼り付けます。
・次に「認証」の欄から、「ユーザ」を「パスワード」を入力し、「次へ」を押下します。
・Githubを確認し、プッシュしたものが上がっていれば成功です!
##Herokuにアップする。
次にHerokuにアップします。
これができたら、とりあえずWEB公開自体は成功です。
一応ポートフォリオとして見せれるかと思います!
・コマンドプロンプトまたはPowerShellを起動。
ちなみにPowershellの方が流行りなのと操作性に優れています。
起動は以下画像参照。
・PowerShellにてプロジェクト(TestApp)のworkspaseまで下ります。
例)「cd C:\pleiades-4.7.3-java-win-64bit-jre_20180411\pleiades\workspace\TestApp」
また以下の様にドラック&ドロップでも行けます。
わからなければ、「PowerShell 使い方」などで検索してみましょう。
ググれカス!ってやつですね!
・heroku CLIを起動しHeroku上にアプリをアップする。
// プロジェクトに移動
> cd C:\pleiades-4.7.3-java-win-64bit-jre_20180411\pleiades\workspace\TestApp
//現在の位置を確認します。アップしたいプロジェクト配下にいればOK。
> pwd
Path
----
C:\pleiades-4.7.3-java-win-64bit-jre_20180411\pleiades\workspace\TestApp
// HerokuCLIを使ってログインします。プロンプトが帰ってきたらEnterを押します。
> heroku login
heroku: Press any key to open up the browser to login or q to exit:
Opening browser to https://cli-auth.heroku.com/auth/browser/799a4794-66aa-46dd-ab9c-2aad6a4b3a6f
・すると、ログイン画面が出てくるのでログインボタンを押下します。
・無事ログインできれば以下の様な画面が出てくるので画面を閉じ、PowerShellに戻りましょう。
// Heroku上にアプリの箱を作成します。その際URLが自動的に発行されるのでメモしておきましょう。
> heroku create
Creating app... done, ⬢ secure-hollows-65644
https://secure-hollows-65644.herokuapp.com/ | https://git.heroku.com/secure-hollows-65644.git
//URLが自動生成されたら、ローカルのデータをリモート(Heroku)へアップします。
> git push heroku master
Enumerating objects: 59, done.
Counting objects: 100% (59/59), done.
Delta compression using up to 4 threads
Compressing objects: 100% (39/39), done.
Writing objects: 100% (59/59), 20.40 MiB | 2.61 MiB/s, done.
Total 59 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Java app detected
remote: -----> Installing JDK 1.8... done
remote: -----> Installing Maven 3.6.2... done
remote: -----> Executing: mvn -DskipTests clean dependency:list install
<中略>
remote: [INFO] Installing /tmp/build_7748a56485859c3572741c4b0b374be0/pom.xml to /app/tmp/cache/.m2/repository/test/test/0.0.1-SNAPSHOT/test-0.0.1-SNAPSHOT.pom
remote: [INFO] ------------------------------------------------------------------------
remote: [INFO] BUILD SUCCESS
remote: [INFO] ------------------------------------------------------------------------
remote: [INFO] Total time: 13.463 s
remote: [INFO] Finished at: 2019-12-05T02:46:08Z
remote: [INFO] ------------------------------------------------------------------------
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 71M
remote: -----> Launching...
remote: Released v3
remote: https://secure-hollows-65644.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/secure-hollows-65644.git
* [new branch] master -> master
PS C:\pleiades-4.7.3-java-win-64bit-jre_20180411\pleiades\workspace\TestApp>
・「deploy... done.」が出て入ればおそらく成功です。
・うまくいけば以下コマンドでWEBアプリが起動します。
> heroku open
・ここまで確認できれば、index.jsp⇔LoginServlet.java⇔login.jsp,loginFail.jsp間のリンクは出来ているということになります。
##MySQLを使うためにローカルを編集します。
ここで初めて「ローカル」といったワードが出てきましたが、手元にあるコードのことを指します。
またHerokuにアップしたアプリを「本番環境」や「Production」「リモート」など言ったりします。
基本的にはローカルで編集を行い、本番環境へアップし画面の確認を行うといった流れになります。
・MySQLのドライバーをダウンロード。
以下の記事が分かりやすいと思います。
https://qiita.com/syoki/items/3d82ef00300868353572
・ダウンロードしたファイルを2か所に格納します。
今回起動しているバージョンのTomcatファイルのlib配下
→例)C:\pleiades-4.7.3-java-win-64bit-jre_20180411\pleiades\tomcat\8\lib
プロジェクトの「Webcontent/WEB-INF/lib」配下にもjarを入れる。
→以下画像を参照。
##コミットしてGithubを最新にする。
ローカルを編集したら、必ずGithubも更新します。
まずは以下を確認して、Eclipse上で「Gitステージング」を表示させてください。
https://tech.pjin.jp/blog/2015/07/01/git-on-eclipse-4-how-to-push/
・コミットします。以下画像参照。
※コミットメッセージは基本英語です。今回は「add MySQL jar file」にしました。
構文は気にせず、伝わればいいと思います。
##Herokuも最新にします。
Powershellを閉じてしまってる場合は、プロジェクト(TestApp)のworkspaseまで下り「heroku login」をお願いします。
さっきまでの状態のままなら、「git push heroku master」だけ実行します。
//現在の位置を確認します。アップしたいプロジェクト配下にいればOK。
>pwd
// 一度閉じてしまっている場合は、以下のコマンドも実行しましょう。
>heroku login
//URLが自動生成されたら、ローカルのデータをリモート(Heroku)へアップします。
>git push heroku master
// アプリを開きます。
>heroku open
・アプリが開いたら、先ほどのように動作確認を行いましょう。
##HerokuにMySQLを導入。
動作確認が出来たら、最後にMySQLを導入します。
導入後は、あらかじめMySQLにレコードを入れておきます。
そしてアプリの「Login」ボタン実行時に処理結果に応じた処理がなされます。
無事ログインできれば成功です。
・アドオンを追加
→PowerShellにてTestApp配下にいること。CLIにてlogin状態であることを確認して下さい。
// 何も表示されないことを確認。
> heroku config
=== secure-hollows-65644 Config Vars
// AddOnを追加します。
> heroku addons:create cleardb:ignite
Creating cleardb:ignite on ⬢ secure-hollows-65644... free
Created cleardb-flexible-21500 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation
// 今度は「CLEARDB_DATABASE_URL」が表示されることを確認。
> heroku config
=== secure-hollows-65644 Config Vars
CLEARDB_DATABASE_URL: mysql://bc56879409bf95:0cebfc1d@us-cdbr-iron-east-05.cleardb.net/heroku_d80576c5913a375?reconnect=true
・MySQL内部にログイン。
→「CLEARDB_DATABASE_URL」の構成は以下になります。
mysql://(--username--):(--password--)@(--hostname--)/(--dbname--)?reconnect=true
これを元に以下のコマンドを組み立て、実行します。
mysql --user=(--username--) --password=(--password--) --host=(--hostname--) (--dbname--)
例)CLEARDB_DATABASE_URL: mysql://aaaaaaaaaaaaaa:bbbbbbbb@cc-cccc-cccc-cccc-05.cleardb.net/heroku_ddddddddddddddd?reconnect=true
↓
表示結果を元にコマンドを組み立てると・・・
↓
mysql --user=aaaaaaaaaaaaaa --password=bbbbbbbb --host=cc-cccc-cccc-cccc-05.cleardb.net heroku_ddddddddddddddd
// 組み立てたコマンドを実行。
> mysql --user=bc56879409bf95 --password=0cebfc1d --host=us-cdbr-iron-east-05.cleardb.net heroku_d80576c5913a375
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 243376916
Server version: 5.6.42-log MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
// ↑↑↑mysql>が出ればOK。
・コマンドを実行するとMySQLにログインできます。
次にテーブルを作成し、レコード追加、最後に確認を行います。
mysql> CREATE TABLE account
-> (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> nickname VARCHAR(16) NOT NULL,
-> password VARCHAR(16) NOT NULL
-> );
Query OK, 0 rows affected (0.21 sec)
// Query OKが出ればOK。エラーならERROR~とか出る。
mysql> INSERT INTO account (NICKNAME, PASSWORD) VALUES('test1', 'test1+');
Query OK, 1 row affected (0.20 sec)
mysql> SELECT * FROM account;
+----+----------+----------+
| id | nickname | password |
+----+----------+----------+
| 1 | test1 | test1+ |
+----+----------+----------+
1 row in set (0.19 sec)
・上記の様にレコードがちゃんと表示されたらOK。
・「exit」でMySQLから抜けましょう。
##アプリの最終確認。
ログイン成功確認まで実行します。
・「heroku open」または既に開いているアプリの更新を行いトップページを表示させます。
以下画像を参考にして動作確認を行います。
お疲れ様です、これでおしまいです。