質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

servlet

Servletとは、Webページの動的な生成やデータ処理などをサーバ上で実行するために、Javaで作成されたプログラムです。 ショッピングサイトやオンラインバンキングといった、動的なウェブサイトの構築に用いられています。

Q&A

1回答

15858閲覧

サーブレットでのエラーチェックについて

退会済みユーザー

退会済みユーザー

総合スコア0

JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

servlet

Servletとは、Webページの動的な生成やデータ処理などをサーバ上で実行するために、Javaで作成されたプログラムです。 ショッピングサイトやオンラインバンキングといった、動的なウェブサイトの構築に用いられています。

0グッド

0クリップ

投稿2018/07/07 08:29

編集2018/07/07 15:09

やりたいこと
userId:null
pass:nullのとき、エラーを表示したいのですが、サーブレットにif文がいっぱいできてしまいました。
もっとスッキリ書きたいのですが、アドバイスいただけないでしょうか。
また、ログインIDを入力してください。のログインIDの部分を変数にしてと言われていて、詰まっています。
フォワード先のjspも併せて記載します。

一般的にエラーがメッセージを表示させるのに、配列をしようすると先輩に聞いたのですが、
できそうにないので、インスタンスに文字列を格納してフォワードで送っています。

package

1import java.io.IOException; 2 3import javax.servlet.RequestDispatcher; 4import javax.servlet.ServletException; 5import javax.servlet.annotation.WebServlet; 6import javax.servlet.http.HttpServlet; 7import javax.servlet.http.HttpServletRequest; 8import javax.servlet.http.HttpServletResponse; 9import javax.servlet.http.HttpSession; 10 11import model.AccountLogic; 12import model.Login; 13 14@WebServlet("/LoginServlet") 15public class LoginServlet extends HttpServlet { 16 private static final long serialVersionUID = 1L; 17 18 protected void doGet(HttpServletRequest request, 19 HttpServletResponse response) 20 throws ServletException, IOException { 21 22 //フォワード 23 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 24 dispatcher.forward(request, response); 25 } 26 27 protected void doPost(HttpServletRequest request, 28 HttpServletResponse response) 29 throws ServletException, IOException { 30 31 32 //リクエストパラメータの取得 33 request.setCharacterEncoding("UTF-8"); 34 String userId = request.getParameter("userId"); 35 String pass = request.getParameter("pass"); 36 37 38 //ログイン処理の実行 39 Login rs = new Login(); 40 rs.setUserId(userId); 41 rs.setPass(pass); 42 AccountLogic bo = new AccountLogic(); 43 boolean result = bo.execute(rs); 44 45 //ログインの成否によって処理を分岐 46 if(userId == null){ 47 Human human = new Human("ログインIDを入力してください。"); 48 //リクエストスコープにインスタンスを保存 49 request.setAttribute("human", human); 50 51 //リクエストスコープからインスタンスを取得 52 Human h = (Human) request.getAttribute("human"); 53 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 54 dispatcher.forward(request, response); 55 56 }else if(pass == null){ 57 Human human = new Human("パスワードを入力してください。"); 58 //リクエストスコープにインスタンスを保存 59 request.setAttribute("human", human); 60 61 //リクエストスコープからインスタンスを取得 62 Human h = (Human) request.getAttribute("human"); 63 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 64 dispatcher.forward(request, response); 65 } 66 67 68 69 if (result) { //ログイン成功時 70 71 //セッションスコープにユーザーIDを保存 72 HttpSession session = request.getSession(); 73 session.setAttribute("userId", userId); 74 75 //フォワード 76 RequestDispatcher dispatcher = request.getRequestDispatcher("/ListScreen"); 77 dispatcher.forward(request, response); 78 } else { 79 //ログイン失敗時 80 // 81 //インスタンス生成 82 Human human = new Human("ログインに失敗しました。ログインIDまたはパスワードが違います。"); 83 84 //リクエストスコープにインスタンスを保存 85 request.setAttribute("human", human); 86 87 //リクエストスコープからインスタンスを取得 88 Human h = (Human) request.getAttribute("human"); 89 90 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 91 dispatcher.forward(request, response); 92 93 } 94 } 95 } 96 97コード

jsp

1<!DOCTYPE HTML> 2<html lang="ja"> 3<head> 4<%@ page language="java" contentType="text/html; charset=Windows-31J" 5 pageEncoding="Windows-31J" %> 6 7<title>Sample</title> 8<% 9 //ここでリクエストスコープを受け取る 10 //getAttributeメソッド 11 //追加した属性を取り出す 12 Human human = (Human) request.getAttribute("human"); 13%> 14<%= human.getName() %> 15 16</head> 17<body> 18 <form id="form" method="post" action=""> 19 <span id="input_error"></span> 20 21 <p> 22 <input type="text" name="user" id="user" /> 23 </p> 24 25 <p> 26 <input type="password" name="password" id="password" /> 27 </p> 28 29 <p> 30 <button id="btn" type="button">送信</button> 31 </p> 32 33 </form> 34 <script type="text/javascript"> 35 function validate() { 36 var user = document.getElementById('user'); 37 var password = document.getElementById('password'); 38 var message = document.getElementById('input_error'); 39 var err = []; 40 if (user.value.toString() === '') { 41 err.push('ログインIDが入力されていません。'); 42 } 43 if (password.value.toString() === '') { 44 err.push('パスワードが入力されていません。'); 45 } 46 if (err.length > 0) { 47 message.innerHTML = err.join('<br>'); 48 return false; 49 } 50 return true; 51 } 52 53 var btn = document.getElementById('btn'); 54 btn.addEventListener('click', function(e) { 55 if (validate()) { 56 document.getElementById('form').submit(); 57 } 58 }); 59 </script> 60</body> 61</html> 62<script type="text/javascript"> 63 function formcheck() { 64 //必須チェック 65 if (document.Form1.userId.value == "") { 66 //エラーを打ち出す 67 document.getElementById('input_error').innerHTML += "ログインIDが入力されていません。"; 68 } 69 if (document.Form1.pass.value == "") { 70 document.getElementById('input_error').innerHTML += "パスワードが入力されていません。"; 71 } 72 } 73</script> 74 75コード

java

1package servlet; 2 3import java.io.Serializable; 4 5public class Human implements Serializable { 6 private String name; 7 8 public Human(String name) { 9 this.name = name; 10 } 11 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19}

java

1package model; 2 3public class Login { 4private String userId; 5private String pass; 6 7public String getUserId() { 8 return userId; 9} 10public void setUserId(String userId) { 11 this.userId = userId; 12} 13public String getPass() { 14 return pass; 15} 16public void setPass(String pass) { 17 this.pass = pass; 18} 19 20} 21

java

1package model; 2 3import dao.AccountDAO; 4 5public class AccountLogic { 6 public boolean execute(Login login) { 7 AccountDAO dao = new AccountDAO(); 8 Account account = dao.findByLogin(login); 9 10 return account != null; 11 } 12} 13

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/07/07 08:46

Humanクラスもご提示を。何してるか分からないので回答しようがないです
m.ts10806

2018/07/07 09:00 編集

オブジェクト指向の理解度を教えていただきたく。Humanクラス全く意味持ってないですよ。両方入力されてないときはIDだけエラーでいいんですか?
退会済みユーザー

退会済みユーザー

2018/07/07 09:35

コードを修正しました。
退会済みユーザー

退会済みユーザー

2018/07/07 09:37

javabeansを用意して、リクエストスコープを利用。エラーメッセージを格納して、jspで取り出すと認識しているのですが、いかがでしょうか。
m.ts10806

2018/07/07 09:39

Beansについて何か調べたことなど出展元があればそちらを記載してください。何かの課題っぽいので、習ってきたこと教えてもらってきたことの中にヒントになるようなものはありませんでしたか?
m.ts10806

2018/07/07 09:52

ちょっと回答の方向性が難しいのですが、実コードで回答してしまうと非常に大きくなり理解も追いつきにくいでしょうし、今後の質問者さんのやり方を制限してしまうことになりかねないので、ヒント的な部分コードと現在コードに対する指摘のみにとどめて回答としようと思います。よろしいですか?
退会済みユーザー

退会済みユーザー

2018/07/07 09:54

はい。お願いします。
m.ts10806

2018/07/07 09:54

なるほど。ちょっと勘違いされている部分がありますね。その部分もあわせて書いてみます。
退会済みユーザー

退会済みユーザー

2018/07/07 10:01

よろしくお願いします。
退会済みユーザー

退会済みユーザー

2018/07/07 10:06

ほんとは、配列にエラーメッセージをaddして、ループさせて表示させたいのです。
m.ts10806

2018/07/07 14:30

時間がかかりましたが回答しました。  一応・・・配列もインスタンス化したものもどちらも「オブジェクト」です。「オブジェクトとは何か」というところも調べておいてください。用語とか用法部分になりますが、概念的には知っておく必要はあると思います。
guest

回答1

0

まず最初に。
JavaScriptでバリデーションしているコードは一通り除いておいてください。
同じような処理を書いているコードが2箇所にありますし、
いきなり全部盛ってしまうのはコードがグチャグチャになる原因となります。

JavaBeansについては下記の記事がわかりやすいと思います。

既に参考にされたようですが、今のやり方と「javaBeansに文字が格納できるんだ」という理解だけだとオブジェクト指向のメリットが全くいかせていないことになります。
記事もあるように「JavaBeans=銀行」とあります。
銀行に口座を開設して、適宜、情報を保存したり取り出したりして使うものですね。

今のコードを見ますと、
同名の銀行を開設しまくっています。

本来は「データ」を確認して利用するためなので、「文字を保存する」となると意味がありません。
「文字を保存する」だけでいいなら、わざわざBeansにする意味がありません。

あと「エラーメッセージ」というのでしたらそういう意味を込めた名前をつけないと使うときに分かりづらくなります。

今の書き方だと1つずつしか送っていないのでBeans使うまでもなく、文字だけ送る作りと使い方が変わりません。

一気にすべてやろうとするのではなく、何段階かにわけて書いていってください。

注記:動作確認をすべて行っているわけではありません。構文エラーなどは自身で調整してください。
いきなり実装を考えるのではなく、ロジックを考えるというところを優先させてください。

第1段階 直接エラーメッセージを送る OR 変数に入れて送る

java

1if(userId == null){ 2 Human human = new Human(); 3 request.setAttribute("error", "ログインIDを入力してください。"); 4 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 5 dispatcher.forward(request, response); 6}else if(pass == null){ 7 request.setAttribute("error", "パスワードを入力してください。"); 8 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 9 dispatcher.forward(request, response); 10}

※doPostからだけ送るとNull参照となるのでdoGetでもerrorを空文字""でsetAttribute()しておく

<% String error = (String) request.getAttribute("error"); if(!"".equals(error)){ %> <%=error %> <% } %>

もしくはエラーメッセージをためておく変数を持っておくとか。
こうすると、幾つか同じ記述があるのでまとめることができると気づくかもしれません。

java

1String error = ""; 2if(userId == null){ 3 error = "ログインIDを入力してください。"; 4}else if(pass == null){ 5 error = "パスワードを入力してください。"; 6} 7if(!"".equals(error)){ 8 request.setAttribute("error ", error); 9 RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/Login.jsp"); 10 dispatcher.forward(request, response); 11}

※JSPは同じ

第2段階 配列にエラーメッセージをセット

java

1ArrayList<String> error = new ArrayList<>(); 2 3if(userId == null){ 4 error.add("ログインIDを入力してください。"); 5} 6if(pass == null){ 7 error.add("パスワードを入力してください。"); 8} 9if(error.size() > 0){ 10 //setしてdispatcher 同じ 11}

jsp
※doPostからだけ送るとNull参照となるのでdoGetでもerrorを空配列でsetAttribute()しておく

<% ArrayList<String> error = (ArrayList<String>) request.getAttribute("error"); if(error.size() > 0){ for(int i = 0; i < error.size() ; i++){ %> <%=error[i] %><br /> <% } } %>

第3段階 チェック用の関数を作る

「を入力してください」のところが共通なので、そこだけ可変にしてチェックするような関数を作る。

例:

java

1 public static String checkEmpty(String value,String name){ 2 if(value == null || "".equals(value) ){ 3 return name + "を入力してください"; 4 } 5 return ""; 6 }

※同じクラス内の別メソッドよりの呼び出し

java

1 2String error = checkEmpty("","名前"); 3 4/*実行結果*/ 5// 名前を入力してください

メッセージが取れたら第1段階と同じです。

第4段階 バリデート用のメソッドを作る

第3段階では入力項目の数だけ呼び出し側で書かなければいけませんし、
配列に入れようと思った場合、結果が空文字""かどうかを確認する必要があります。
例:

java

1ArrayList<String> error = new ArrayList<>(); 2 3String errorcheck = ""; 4 5errorcheck = checkEmpty(userId,"ログインID"); 6if(!"".equals(errorcheck)){ 7 error.add(errorcheck); 8} 9errorcheck = checkEmpty(pass,"ログインID"); 10if(!"".equals(errorcheck)){ 11 error.add(errorcheck); 12}

これでは本筋の目的が認証処理であるdoPost()がゴチャゴチャしてきます。
ということで、別途validateメソッドを作ってrequestをそのまま投げて、そちらですべてチェックする方法をとります。

java

1public static ArrayList<String> validate(HttpServletRequest request){ 2 ArrayList<String> error = new ArrayList<>(); 3 String userId = request.getParameter("userId"); 4 String pass = request.getParameter("pass"); 5 6 String errorcheck = ""; 7 8 errorcheck = checkEmpty(userId,"ログインID"); 9 if(!"".equals(errorcheck)){ 10 error.add(errorcheck); 11 } 12 errorcheck = checkEmpty(pass,"ログインID"); 13 if(!"".equals(errorcheck)){ 14 error.add(errorcheck); 15 } 16 return error; 17}

呼び出し元(doPost)

java

1ArrayList<String> error = validate(request); 2 3if(error.size() > 0){ 4 //setしてdispatcher 同じ 5}

※ArrayList<String> errorをLoginServletのプロパティとして宣言しておくと
validate()の冒頭で宣言する必要も呼び出し元で受け取る必要もありません。
その辺りは今後で。

第5段階 Beansについて

原則なのですが、持っておくのは「データ」なので
「エラーメッセージ」のようにその後も保持しておく必要のない
1度だけの使い捨て情報については保持しておく必要はないものと考えます。

ただ保持しておくべきデータについては、基本として全てのフィールドに対してget,setを設置する必要があります。
その部分は参考にされた記事の通りですね。
privateで変数を定義→セッター・ゲッター設置→任意のタイミングで利用 です。
※Eclipseなど開発統合環境のエディタでは自動で作ってくれる機能があります

あくまで「銀行」です。
1フィールド1口座と思ってください。
インスタンス化をすると銀行自体が開設されるので、
基本は何度もnewする必要はありません。
同じ銀行を何度も開設するのは変ですよね?
1度開設したらその銀行内のそれぞれの口座に情報を入れていってください。

なお、現在はコンストラクタでいきなり何か入れていっていますが、
コンストラクタはあまりそういう使い方はしないと思います。
「コンストラクタ 使い方」で調べて文献を読み漁ってください。

今回用意されたHumanに対しては下記のような使い方になるかと思います。

あくまで例なのでそのまま書かないこと。足りない部分や仕様と違う部分は自身で埋めること

java

1public class Human implements Serializable { 2 private String name; 3 private Integer UserId; 4 public Human() { 5 } 6 7//ゲッターセッター部分は省略 8}

※それぞれのフィールドに対してゲッターセッターが用意されていること

java

1if (result) { //ログイン成功時 2 Human human = new Human(); 3 human.setName(/*取得してきたユーザ名*/); 4 human.setUserId(/*取得してきたユーザID*/); 5 6 session.setAttribute("human", human); 7 RequestDispatcher dispatcher = request.getRequestDispatcher("/ListScreen"); 8 dispatcher.forward(request, response); 9}

JSP側はgetを(Human)でキャストして受け取る。

認証データなので名前はAuthUserとかの方が良いですね。
そもそもHumanクラスが何のために用意されたのかわかりませんが。

強いてなら、validate()メソッドをすべてHumanクラスに移動して、
下記のようにするのはありですが、

呼び出し元(doPost)

java

1Human human = new Human(); 2ArrayList<String> error = human.validate(request); 3 4if(error.size() > 0){ 5 //setしてdispatcher 同じ 6}

※この場合はvalidate()メソッドのstaticは外しておいてください。staticではなくなるはずなので。

Humanだけに存在しているのは勿体ないですね。

あとはset~~のときに型が決まっているので、そこでチェックするのもありかもしれません。

ただ、validate()メソッド自体は他の処理で汎用的に使えたほうがいいですよね。
Humanクラスに置くのは進めません。別途Vaidationクラスを作って共通化を検討してください。

共通化ができれば、あとは処理を追加していくだけで良いですし、共通部分と個別部分をわけて考えられます。
個別の情報のみ渡して、あとは分岐して、とか、設定ファイルに持たせるとか、考えられるようになってくるでしょう。

ひとまずBeansのことを考えるのはきちんと第4段階まで出来てからにした方が良さそうです。

他気づき

  • バリデーション前にログイン処理をしている

入力値に不正な値が入ってきてたら不具合が起きます

  • LoginクラスとAccountLogicクラスは何?分ける必要があるのだろうか。使い道が不明
  • 謎の記述→ Human h = (Human) request.getAttribute("human");

このgetAttribute()はまったく意味がない。

  • jsp側 不要記述が多い。もう使ってない記述もあるのでは?

最初に書いたように、JavaScriptでのバリデーションはひとまず一度全て忘れてサーブレットのみで作りこんでいってください。
どうしても欲しいなら後から合体させれば良いです。

未使用記述・不要記述は実装上での邪魔にしかなりません。
1行1行意味を持たせて、必要な記述のみしていってください。
コピペコードが山積していくとわけがわからなくなって余計混乱します。

ざっと書きましたが、
全部一気にやるのではなく、1段階ずつ動作を確実にし、ステップアップしていってください。

投稿2018/07/07 14:06

m.ts10806

総合スコア80871

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/07/07 14:49

今日、明日で少しづつ理解しながら進めてみます。一か月半ほど毎日勉強しているのに、コードを思ったようにかけなくて、自分には才能がないのだと落ち込んでいました。でも、落ち込む時間がもったいないので、前向きに頑張ります。いつも本当にありがとうございます。
m.ts10806

2018/07/07 14:54

一気にやろうとするからだと思います。 フルマラソン完走目指すとして、最初は1kmとか2kmとかからゆっくり始めますよね。 慣れてきてから距離をのばし、体力がついてきてからペースをあげていきます。 それと同じです。いきなりやりたいことをやろうとしないこと。細分化して一行ずつ確実に意味を持ったコードを書いていって「できる」を積み重ねてください。 仕事でもあることですが、煮詰まったら頭から一回完全に切り離して、早めに就寝したり別の趣味に逃げるのもありだと思います。 人間簡単にはダメになりませんが、一度崩れ始めると歯止めが効かなくなります。
退会済みユーザー

退会済みユーザー

2018/07/07 15:13 編集

Loginクラスは、JavaBeansです。 AcountLogicは、BO(ビジネスオブジェクト)というクラスになります。 「スッキリわかるサーブレット」という本のコードをそのまま参考にして書いてます。
m.ts10806

2018/07/07 21:33

やはりHumanクラス全く意味を成してないですね。文字列そのままjspに渡すので充分です。 私はあまり本ではJavaを学習してないんですが(フレームワークのものだけ買っています)、 その本ではバリデーションについて触れていないんでしょうか。 セキュリティに触れていない本はおそらくないのであるはずだとは思いますが・・・ バリデーションについては今回の回答を段階を追ってやっていってください。 どのような勉強法をとっているか分かりませんが、ひたすら本をやるだけが勉強ではないと思います。 特にプログラミングについてはきちんと課題を持って着実に成果を出していくようにして モチベーションの維持をしていく必要があると思います。 見た感じ、本の通りだけやっていて使いこなせていないように思います。 DAOやBeansの考え方は学んでおいて損はないですが、まずオーソドックスなサーブレット&JSPの使い方を確実におさえては? 今自身が何を分かっていて何が分かっていないかを明確にするだけでも学習の進み方が大きく変わります。 先のコメントで書いたマラソンの例だと、自身は今、素で無理なく何㎞走れる実力があるのか? それが分かると次に何をするべきか決まります。 決まらないままただやっていると成長した感がないため、モチベーションがどんどん下がっていきます。 まずは今自分が何ができるのかをリストアップしてみてください。 それは例えば暗記できているか?という確認ではなく、何かしらの課題が出たときにどこまで実装をイメージできるか?という観点で。 どれほどの熟練者であっても全てを暗記しているということはありません。 「こういうときにはこういう機能が使えるはず。正確なスペルとかオプションまで覚えてないけど」という感じで調べます。 そこで参考するのがQiitaなどで書かれた記事、書籍、JavaDoc( https://docs.oracle.com/javase/jp/8/docs/api/ )といったもの。 「どういうキーワードで探せば欲しい情報に近いものが出てくる・部品が集められる」も技術力のうちだと思います。
退会済みユーザー

退会済みユーザー

2018/07/08 06:43

第2段階までなんとかできました!
m.ts10806

2018/07/08 07:05

配列もできたということですかね。 まずそれでやれる幅が広くなりましたね。
退会済みユーザー

退会済みユーザー

2018/07/08 07:23

配列もできました。
m.ts10806

2018/07/08 07:26

ん、第2は配列のことしか触れていませんが…「も」とは?
退会済みユーザー

退会済みユーザー

2018/07/08 09:44

「も」はおかしいですね。
m.ts10806

2018/07/10 04:39

色々取り組まれているようですが、あちらこちらに手を出していてはどれも中途半端になりかねませんし、 ストレスもたまりやすくなります。 やるときは1つに集中、やらないときは完全休養 とメリハリをつけるようにしてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問