
【絶対に挫折しないJava超入門】これ以上簡単に教えるのは無理③【サポート付き】
どうも、エンジニアの陽翔です。
【絶対に挫折しないJava超入門】の第3回です。Java EEの中核技術であるServletの超入門の続きで、今回はシンプルな計算機を開発してもらいます。
完成イメージをこちらYoutubeのでどうぞ。
Java未経験の方でも実際に動くものを作りながら、JavaやWebアプリケーションの理屈を理解してもらう事で、挫折する事なくJavaを身に付ける最初の一歩を踏み出せるはずです!
もし、このnoteをはじめてご覧になる方は、第1回から始めてもらう方が良いかと思います。是非、どうぞ!
1.前回の宿題の答え合わせ
さて、では前回の宿題の答え合わせから。
ちょっと簡単過ぎたでしょうか?もしそう感じたのであれば、既に第2回にしてJava EEが身につき始めている証拠ですねw
宿題
今回作成した「/HelloServlet」に以下のServletを追加してみましょう。
URL
http://localhost:8080/HelloServlet/NAVY
画面イメージ
Hello World!!を「font color=navy」としています。
1-2.答えの例
では答え合わせをしましょう。
①コンテキストルートは作成不要
第2回の中で作成した「/HelloServlet」の下にもう1つServletを追加するという宿題なのでコンテキストルートは追加不要です。
②Servletのソースファイル作成
私は、第2回で作成した「C:\DEV\src\HelloServlet」という開発用のフォルダに、「HelloServletNaby.java」というファイルを作成しました。クラス名が安易なのはつ込まないでください。
③HelloServletNaby.javaのコーディング例
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/NAVY")
public class HelloServletNavy extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<br><br>");
out.println("<b><font color=navy>Hello World!!</font></b><br>");
out.println("by Servlet<br>");
out.println("</body>");
out.println("</html>");
}
}
コーディング例です。HelloServlet.javaとほぼほぼ同じです。
ポイントは2箇所。
まずは、ServletのURLマッピングの指定。
宿題のURLはこちらでしたね。
http://localhost:8080/HelloServlet/NAVY
URLのマッピングは「@WebServlet」アノテーションでの指定ですから、このようにここが対応するようにコーディングします。
2つ目はフォントカラーの指定。
フォントカラーの指定の仕方はいくつもありますが、私は一番簡単にこんな書き方をしました。
③コンパイル
そしてコンパイルです。
c:\>cd DEV\src\HelloServlet
c:\DEV\src\HelloServlet>javac -cp "C:\apache-tomcat-9.0.36\lib\servlet-api.jar" -d "C:\apache-tomcat-9.0.36\webapps\HelloServlet\WEB-INF\classes" HelloServletNavy.java
ここも問題ないですね。
コンパイルが成功したら、Tomcatを再起動すればOKです。
2.シンプルな計算機アプリを開発
さて、先ほどもお伝えした通り、今回はシンプルな計算機アプリを実装してもらいます。今まで同様にまずは手を動かしてもらいます。
今回は以下の4つをコーディングしてもらいます。
・SCForm.jsp
・Simple.css
・SCServlet.java
・SimpleCalculator.java
この4の関係性を簡単に図にしてみました。イメージだけつかめればOKです。
今までの中で一番量が多いですが、第1回、第2回をやってきていれば大丈夫です。頑張っていきましょう。
2-1.コンテキストルートを作成
今回もコンテキストルートを作ります。そしてその配下のフォルダも以下のように作成してください。
コンテキストルートは「/SimpleCalculator」とします。前回同様にその下に「WEB-INF」と「classes」フォルダも作ってください。あとjsp格納用に「jsp」というフォルダも作りましょう。
もう慣れてきましたよね。いい感じです。
2-2.JSPとCSSをコーディング
まずは画面周りからコーディングしていきましょう。
まずは「SCForm.jsp」からです。
いつもどおり最初は無心でこのままコピーして作成しましょう。第1回で作成したJSPよりもだいぶフォームっぽい感じですよね。ただ、私はフロントエンジニアでもデザイナーでもないので、画面がしょぼいのは見逃してください…。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>SimpleCalculator</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/jsp/Simple.css">
</head>
<body>
<form method="POST" action="${pageContext.request.contextPath}/Calc">
<h2>SimpleCalculator</h2>
<br>
<div class="msr_text_04">
<label>数1</label>
<input id="val1"type="text" name="sc_val1" value=<%= request.getParameter("sc_val1") == null ? "0": request.getParameter("sc_val1")%> />
</div>
<br>
<div class="msr_radio_04">
<p>計算方法</p>
<input type="radio" name="sc_radio" id="sc_radio01" value="1" <%= "1".equals(request.getParameter("sc_radio")) ? "checked" : ""%> />
<label for="sc_radio01">+</label>
<input type="radio" name="sc_radio" id="sc_radio02" value="2" <%= "2".equals(request.getParameter("sc_radio")) ? "checked" : ""%> />
<label for="sc_radio02">-</label>
<input type="radio" name="sc_radio" id="sc_radio03" value="3" <%= "3".equals(request.getParameter("sc_radio")) ? "checked" : ""%> />
<label for="sc_radio03">×</label>
<input type="radio" name="sc_radio" id="sc_radio04" value="4" <%= "4".equals(request.getParameter("sc_radio")) ? "checked" : ""%> />
<label for="sc_radio04">÷</label>
</div>
<br>
<div class="msr_text_04">
<label>数2</label>
<input id="val2"type="text" name="sc_val2" value=<%= request.getParameter("sc_val2") == null ? "0": request.getParameter("sc_val2")%> />
</div>
<br>
<div class="msr_text_04">
<label>計算結果</label>
<input id="val3"type="text" name="sc_val3" value=<%= request.getAttribute("sc_val3") == null ? "0": request.getAttribute("sc_val3")%> />
</div>
<br>
<p class="msr_sendbtn_04">
<input type="submit" value="計算する">
</p>
</form>
</body>
</html>
次に「Simple.css」です。
今回のCSSはネットで入手したフリー素材です。
/*--------------------------------------
テキスト
---------------------------------------*/
.msr_text_04 {
padding-bottom: 20px;
width: 460px;
}
.msr_text_04 label {
display: block;
font-size: 14px;
padding-bottom: 5px;
}
.msr_text_04 input[type=text] {
border: 5px solid #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
color: #000000;
font-size: 13px;
padding: 10px;
height: 40px;
width: 460px;
}
/*--------------------------------------
ラジオボタン
---------------------------------------*/
.msr_radio_04 {
padding-bottom: 20px;
}
.msr_radio_04 p {
font-size: 14px;
padding-bottom: 5px;
}
.msr_radio_04 input[type=radio] {
display: none;
margin: 0;
}
.msr_radio_04 input[type=radio] + label {
cursor: pointer;
display: inline-block;
font-size: 13px;
line-height: 1.5px;
margin-right: 12px;
padding: 0 0 0 30px;
position: relative;
}
.msr_radio_04 input[type=radio] + label::before {
border: 3px solid #000000;
border-radius: 50%;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "";
display: block;
margin-top: -9px;
position: absolute;
left: 0;
top: -3px;
height: 24px;
width: 24px;
}
.msr_radio_04 input[type=radio]:checked + label::after {
background: #000000;
border-radius: 50%;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "";
display: block;
margin-top: -4px;
position: absolute;
left: 6px;
top: -2px;
height: 12px;
width: 12px;
}
/*--------------------------------------
チェックボックス
---------------------------------------*/
.msr_chack_04 {
padding-bottom: 20px;
}
.msr_chack_04 p {
font-size: 14px;
padding-bottom: 5px;
}
.msr_chack_04 input[type=checkbox] {
display: none;
margin: 0;
}
.msr_chack_04 input[type=checkbox] + label {
cursor: pointer;
display: inline-block;
font-size: 13px;
line-height: 1.5px;
margin-right: 12px;
padding: 0 0 0 30px;
position: relative;
}
.msr_chack_04 input[type=checkbox] + label::before {
border: 3px solid #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "";
display: block;
margin-top: -9px;
position: absolute;
left: 0;
top: -3px;
height: 24px;
width: 24px;
}
.msr_chack_04 input[type=checkbox]:checked + label::after {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "";
display: block;
position: absolute;
top: 50%;
}
.msr_chack_04 input[type=checkbox]:checked + label::after {
border-bottom: 3px solid #000000;
border-left: 3px solid #000000;
left: 6px;
margin-top: -8px;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
height: 10px;
width: 12px;
}
/*--------------------------------------
プルダウン
---------------------------------------*/
.msr_pulldown_04 {
padding-bottom: 20px;
position: relative;
width: 230px;
}
.msr_pulldown_04 p {
font-size: 14px;
padding-bottom: 5px;
}
.msr_pulldown_04 select {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
background: url(/stylerecipe_img/msr04_pulldown_btn01.png) no-repeat right;
border: 5px solid #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
cursor: pointer;
padding: 5px 10px;
height: 40px;
width: 230px;
}
/*--------------------------------------
ファイル選択
---------------------------------------*/
.msr_file_04 {
padding-bottom: 20px;
width: 460px;
}
.msr_file_04>p {
font-size: 14px;
padding-bottom: 5px;
}
.msr_filebox_04 input[type=file] {
display: none;
}
.msr_filebox_04 label {
border: 5px solid #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
cursor: pointer;
display: block;
font-size: 14px;
padding: 5px 10px;
position: relative;
height: 40px;
width: 460px;
}
.msr_filebox_04 label:before {
background: #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "Browse...";
color: #fff;
display: inline-block;
font-size: 14px;
text-align: center;
padding-top: 5px;
position: absolute;
right: 0;
top: 0;
height: 30px;
width: 99px;
}
/*--------------------------------------
テキストエリア
---------------------------------------*/
.msr_textarea_04 {
padding-bottom: 10px;
width: 460px;
}
.msr_textarea_04 label {
display: block;
font-size: 14px;
padding-bottom: 5px;
}
.msr_textarea_04 textarea {
border: 5px solid #000000;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
color: #000000;
font-size: 13px;
padding: 10px;
height: 210px;
width: 460px;
}
/*--------------------------------------
送信ボタン
---------------------------------------*/
.msr_sendbtn_04 {
margin:0 0 10px;
position: relative;
height: 50px;
width: 150px;
}
.msr_sendbtn_04 input[type=submit] {
background: #000000;
background-position: 10px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
border: none;
color: #FFFFFF;
cursor: pointer;
font-size: 14px;
transition: 0.2s ease-in-out;
-o-transition: 0.2s ease-in-out;
-moz-transition: 0.2s ease-in-out;
-webkit-transition: 0.2s ease-in-out;
height: 50px;
width: 150px;
}
.msr_sendbtn_04:before {
border: 6px solid transparent;
border-left: 6px solid #FFFFFF;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
content: "";
display: inline-block;
height: 12px;
position: absolute;
top: 20px;
left: 20px;
vertical-align: middle;
width: 6px;
z-index: 10;
}
.msr_sendbtn_04 input[type=submit]:hover {
opacity: 0.6;
}
.msr_sendbtn_04_disabled input[type=submit]{
background: #FFFFFF;
border: 5px solid #DDDDDD;
color: #DDDDDD;
cursor: default;
}
.msr_sendbtn_04_disabled:before {
border-left: 6px solid #DDDDDD;
content: "";
}
.msr_sendbtn_04_disabled input[type=submit]:hover {
opacity: 1;
}
どちらのファイルも先ほど作成した「jsp」フォルダの下に格納してください。
2-3.計算機クラスをコーディング
さて、ここが今回のポイントの1つでもあります。JSPでもない、Servletでもない、一般的なJavaのクラスをコーディングしてもらいます。このクラスは計算機としての機能を持たせて、Servletから呼び出す格好にします。
①開発用のフォルダを作る
どこでもいいのですが、前回に合わせて「C:\DEV\src\SimpleCalculator」としました。
②SimpleCalculator.javaをコーディング
public class SimpleCalculator {
// コンストラクタ
public SimpleCalculator() {
}
private final static String TASU = "1";
private final static String HIKU = "2";
private final static String KAKERU = "3";
private final static String WARU = "4";
// 計算処理
public int calc(int val1, int val2, String mode) {
int retVal = 0;
switch (mode) {
case TASU:
retVal = val1 + val2;
break;
case HIKU:
retVal = val1 - val2;
break;
case KAKERU:
retVal = val1 * val2;
break;
case WARU:
retVal = val1 / val2;
break;
}
return retVal;
}
}
「calc」という名の計算メソッドを1つだけ持つシンプルな計算機クラスです。
もしかして、今、Javaやオブジェクト指向の難しさをちょっとかすったかもしれません。でも大丈夫です。後ほど超分かりやすく解説します。
③コンパイル
当然ですが「SimpleCalculator.java」もコンパイルして「SimpleCalculator.class」ファイルを作り出す必要があります。
c:\>cd DEV\src\SimpleCalculator
c:\DEV\src\SimpleCalculator>javac -cp "C:\apache-tomcat-9.0.36\lib\servlet-api.jar" -d "C:\apache-tomcat-9.0.36\webapps\SimpleCalculator\WEB-INF\classes" -encoding UTF-8 *.java
今回のJavacコマンドはこんな感じです。一番最後の「*.java」という指定は、「C:\DEV\src\SimpleCalculator」フォルダに格納されたjavaファイルをすべてコンパイルするという指定です。
今回はこの「SimpleCalculator.java」と次でコーディングする「SCServlet.java」の2ファイルをコンパイルするので、こんな感じにしています。
さらに補足すると「SimpleCalculator.java」だけをコンパイルする場合は「-cp "C:\apache-tomcat-9.0.36\lib\servlet-api.jar"」という指定は不要です。Servletではないので、「servlet-api.jar」への依存がない(コード内で参照していない)からです。
2-4.Servletをコーディング
次にServletをコーディングします。
①SCServlet.javaをコーディングする
さっき作成した「C:\DEV\src\SimpleCalculator」へ格納しましょう。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.RequestDispatcher;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.Integer;
@WebServlet("/Calc")
public class SCServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
int val1 = 0; // 数1格納用
int val2 = 0; // 数2格納用
String radio = ""; // 計算方法格納用
int val3 = 0; // 計算結果格納用
// JSPの画面から値を取得
// nullの場合はゼロとして扱う
val1 = Integer.parseInt(request.getParameter("sc_val1") == null ? "0" : request.getParameter("sc_val1"));
val2 = Integer.parseInt(request.getParameter("sc_val2") == null ? "0" : request.getParameter("sc_val2"));
radio = request.getParameter("sc_radio");
if (radio != null) {
// 計算処理クラスをインスタンス化
SimpleCalculator simpleCalculator = new SimpleCalculator();
// 計算処理を呼び出す
val3 = simpleCalculator.calc(val1, val2, radio);
}
// requestオブジェクトに計算結果を格納
request.setAttribute("sc_val3", val3);
// JSPを呼び出し
ServletContext context = this.getServletContext();
String path = "/jsp/SCForm.jsp";
RequestDispatcher dispatcher
= context.getRequestDispatcher(path);
dispatcher.forward(request, response);
}
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// doPostを呼び出す
doPost(request, response);
}
}
今回のServletは前回とはちょっと違います。後ほど解説しますのでまずはこのままコピーしてください。
③コンパイル
さっきのコンパイルコマンドをもう一度、実行してServletもコンパイルしましょう。
c:\>cd DEV\src\SimpleCalculator
c:\DEV\src\SimpleCalculator>javac -cp "C:\apache-tomcat-9.0.36\lib\servlet-api.jar" -d "C:\apache-tomcat-9.0.36\webapps\SimpleCalculator\WEB-INF\classes" -encoding UTF-8 *.java
一応、想定どおりにclassファイルが出来上がっているか確認。
2-5.計算機アプリへアクセス
さて、では計算機アプリケーションへアクセスしてみましょう。
ブラウザを開きこのURLへアクセス。
http://localhost:8080/SimpleCalculator/Calc
この画面が表示されたら成功です!
Webアプリケーションマネージャ画面でも確認してみましょう。
http://localhost:8080/manager/html
「/SimpleCalculator」が出来ていますね。
さて、今回のシンプルな計算機の実装はこれで終了です。
もしこの結果にならなければ、何かが間違っています。もう一度、このnoteの最初からしっかりとやり直してください。そしてそれでも解決しなければ、DMからお問い合わせください。
冒頭でも掲載しましたが操作はこのYoutubeでアップしています。(説明する必要がないくらい簡単ですが。)
今回に限った話ではないのですが、このnoteのシリーズではとにかくアプリケーションを動かしてもらう事を最優先にしていますので、細かい制御やエラーハンドリングなどはめっちゃ端折っています。
有識者が見たら「雑だな・・・」って思うでしょう。それは分かった上でとにかく少ないコードで動かす事に注力しているのでその点はご認識ください。
たとえば、ゼロで割ったときの例外は計算処理の中でももっともメジャーな例外ですが、そんなのもハンドリングしていません。
つまり、こうやって0で割ると・・・
こんな感じ。本来はこうならないように何らかのハンドリングが必要なんですが、【絶対に挫折しないJava超入門】ではこういう細かい事は後から付け足しで学んでもらえばいいと考えています。
むしろ、こういう細かい点までも、手を動かす前に理解しようとすると途中で挫折していまう可能性が高いと考えています。
という事で、いつもどおり、実装の解説まで出来上がったので一旦noteを公開します。この後、今回のコーディングについての解説部分を更新してTwitterにてお知らせいたします。