読者です 読者をやめる 読者になる 読者になる

自作アプリ1つめ 掲示板みたいなやつ

初めて作ったアプリケーションもどきを晒します。

もともとは簡易な社内SNS的なものを想像してたのですが、
雑なチャットぽいものが出来上がりました。

作り始めたころのレベルは、Javaの講座に週末3ヶ月くらい通ったあとです。
入門書に書いてある意味がなんとなくわかるかなーくらいのレベル感です。

CSS,JSP,データベース随所で躓きながらなんとか動く感じにはなりましたが、
なんとも雑な仕上がりになっています。

もう手はつけてないのですが、
このまま葬られるのが(個人的に)もったいないので、記録に残しておきます。
主要なページは3,4枚なので、ページごとに紹介していきたいと思います。

[index.jsp]

f:id:isotai:20170305181912p:plain

最初に表示されるページです。
ここからログインするか、ユーザー登録ページに遷移できます。

ユーザー登録ページは、後ほど説明するとして、
まずはフロントサイドでやったことから紹介します。

まず、このページはBootStrapとか使って整えようと頑張りました。

CSSよくわからなかったので、途中で手を止めて以下の本でお勉強。
クリックアンドドロップで作れるWebサイトとかに慣れていると、
CSSってかなり不便に感じるかも? フォームの表示場所変えるだけなのに
マージンとかフロートの範囲とか気にするのが煩わしい!と思いつつ
今風なログインページを”目指して”作っています。

f:id:isotai:20170306224355p:plain

ロゴだけはいい感じではないでしょうか。
すべてこのサービスのおかけです。
logo.squarespace.com


入力ホームはBootStrapのテンプレートをお借りしました。
以下のサイトは、ログインフォームのテンプレートが充実していていい感じです。
bootsnipp.com

ログインフォームは基本テンプレートのコピペです。
背景を透明にしたかったので、form のstyle = background-color:rgba(0,0,0,0.0);のところだけいじっています。

<div class = "container">
<div class="wrapper" >
<form method = "get" action="/ooo/LoginUser" class="form-signin" style = background-color:rgba(0,0,0,0.0);>
<h3 class="form-signin-heading" style = color:white;>welcome! please sigh in</h3>
<hr class="colorgraph"></br>
<input type = "text" name = "email" class="form-control" placeholder="Username"></br>
<input type = "password" name="pass" class="form-control"placeholder="Password"></br>
<input type = "submit" value = "ログイン"  class="btn btn-lg btn-primary btn-block"></br>
</hr>
</form>
 </div>
</div>

画像の上に黒透明色をかぶせて、それっぽくしています。

photofronto{
     width:100%;
    height:100%;
    background-size: cover;
    margin:0 auto;
    position:relative;
    background-color:rgba(0,0,0,0.5);
}

背景画像がおかしくならないおまじない。

body{   
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  background-size: cover;
}

ログインフォームから送付入力されたユーザー名とパスワードが正しいかサーバーサイドで検証し、
正しい場合、ユーザーページに遷移するようにします。
よくよく見返してみると、ユーザーとパスワードの判定もなんだか怪しいのですが、
ログイン情報に間違いがあると、NULLで処理がとまって結果的にログインできなくなります!(´Д` )
ユーザー名とパスワードを指定してselectして結果が得られなかったらログイン失敗になります。


ユーザー登録処理のサーブレット

@WebServlet("/LoginUser")
public class LoginUser extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public LoginUser() {
        super();
        // TODO Auto-generated constructor stub
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		
		//フォームから送付されたデータの受け取り文字コードの指定をしない文字化けする。
		request.setCharacterEncoding("UTF-8");
		String email = request.getParameter("email");
		String pass = request.getParameter("pass");		
		
		//取得したデータを値を保持するだけのクラスに渡す。
		LoginUserModel loginusermodel =  new LoginUserModel(email,pass);
		
		//フォームから入力されたユーザーネームとパスワードでDB検索。 結果をaccount変数に入れて返す。
		//DB検索後に、フォームからの入力値と検索結果が一致するか確認。今考えると入力値の検査はこのDAOでやってはいけなかった。
		//accountにはユーザー名、パスワード、ユーザーID入る。
		LoginUserDAO loginuserdao = new LoginUserDAO();
	    Account account = loginuserdao.login(loginusermodel);
	    
	    //なぜかユーザー名にたいしてヌルチェックをしている。
	    if(account.getUserName().equals("")){
	    	RequestDispatcher dispatch = request.getRequestDispatcher("/registerfalse.jsp");
			 dispatch.forward(request, response);
	   }else{
		   
		   //すべてのユーザーのユーザー名とユーザーIDを取得する。
		   //この情報はチャットで宛先を選ぶときに選択するユーザー表示に使用する。
		   GetAllUserDAO getalluserdao = new GetAllUserDAO();
		   ArrayList<Map<Integer,String>> userlist = getalluserdao.getAllUserNameandID();
			
		   //HttpSessionインタフェースのオブジェクトを取得
		    HttpSession session = request.getSession();
		    //useridデータをsessionスコープで保存
		    session.setAttribute("username",account.getUserName() );
		    session.setAttribute("userid",account.getUserId() );
		    session.setAttribute("userlist",userlist);
		   
		   RequestDispatcher dispatch = request.getRequestDispatcher("/UserPage.jsp");
			  dispatch.forward(request, response);
	   }
	}
}


データベースにログインフォームから送付されたユーザー名とパスワードを持ったユーザーがいるか検索。

public class LoginUserDAO {
	public Account login(LoginUserModel loginusermodel){
		
		 Connection conn = null;
			Account account = null;		
			String sql = "select * from users where email = ? and pass = ?";
		
		 try {	
			 Class.forName("org.postgresql.Driver");
		
	   conn =
	    DriverManager.getConnection("jdbc:postgresql:postgres",	
	                                "postgres",					
	                                "3450");						

			    	 }catch (Exception e){
			    		 System.out.println("接続失敗。");
			    		 e.printStackTrace();			    		 
			    	 }			    
			   	 try { 
   
			   	PreparedStatement ps = conn.prepareStatement(sql);				   		
			       ps.setString(1,loginusermodel.getEmail());
			       ps.setString(2,loginusermodel.getPass());
			       
			       ResultSet result = ps.executeQuery();
			

			      if(result.next()){
			    	  String useremail = result.getString("email"); 
			    	  String userpass = result.getString("pass"); 
			    	  String username = result.getString("name"); 
			    	  String userid= result.getString("userid"); 
			    	  
			    	  account = new Account(useremail,userpass,username,userid);
			      }
			       	    
			       
			   	 }catch (SQLException i){
		    		 System.out.println("select failed。");
		    		 i.printStackTrace();
		    		 
		    		 return null;
			   	 }finally{
		    		 
			    	  
			        if(conn !=null){
			        	try{
			        		conn.close();
			        	}catch (SQLException i){
				    		 System.out.println("closefailed");
				    		 i.printStackTrace();
				    		 return null;
			        	}		        	
			        }
	}	
			   	return account;	
			          	
		 } 

register.jsp

f:id:isotai:20170305224824p:plain

ユーザー登録画面です。
登録画面はこだわらなくていいだろ!という思いがつまっています。

受けっとったあと、一応ヌルチェックをしています。えらい!
あとここはJavaScriptフロントサイドでもヌルチェックをしています。

詳しくはここで。
メールアドレスの入力チェック(JavaScript) - isotaiの日記

request.setCharacterEncoding("UTF-8");
		String email = request.getParameter("email");
		String pass = request.getParameter("pass");		
		String name = request.getParameter("name");	
		
		if((email.equals("")) || (pass.equals("")) || (name.equals(""))){
			RequestDispatcher dispatch = request.getRequestDispatcher("/registerfalse.jsp");
			 dispatch.forward(request, response);


登録フォームから受け取った値でデータベースにユーザーを登録します。
パスワードの暗号化とかは実用するわけではないので気にしていないです。(気にする余裕がなかった)

メッセージ交換にユーザー固有のIDが欲しかったので、
randomUUIDという関数を使用してID生成後、一緒に登録します。

String sql = "insert into users(email,pass,name,userid) values(?,?,?,?)";
		   		PreparedStatement ps = conn.prepareStatement(sql);	
		    
		   		//useridの作成
		   		String uuid = UUID.randomUUID().toString();  
		   		
		       ps.setString(1,registerusermodel.getEmail());
		       ps.setString(2,registerusermodel.getPass());
		       ps.setString(3,registerusermodel.getName());
		       ps.setString(4,uuid);


あとはデータベースに書き込んで終了です。

UserPage.jsp

f:id:isotai:20170306220308p:plain

ようやくメインページです。
FacaBookをイメージして作りました;;

テキストエリアにメッセージを書きます。
do not show in filed:にチェックを入れると個人宛メッセージになり、フィードに表示されません。
個人メッセージ確認画面でのみ表示されます。プルダウンタブから宛先のユーザーを選択します。
この表示でログイン処理の際に取得したユーザー一覧情報を使用しています。
投稿フォームとフィードメッセージの表示CSSはBootStrapのテンプレートから拝借しています。

フォームから説明します。

<input type="text" name = "message" class="span4"  rows="10" size="30" placeholder="Type your post,change line = <br>" ></div>
   do not show in filed:<input type="checkbox" name = 'postconfirm' value = "no"></br>
<input type="hidden" name="useridfrom" value="<%=session.getAttribute("userid")%>">
<select name="useridto">
   <%for(int i = 0; i<userlist.size(); i++){%>
   <%Map<Integer,String> list = userlist.get(i);%>
   <%String name =  list.get(1);%>
   <%String id =  list.get(2);%>
   <option value=<%=id%>><%=name%></option>
   <%}%>
</select>
<br/>
<h6 class="pull-right" id="cLeft"></h6>
<div class = "text-right">
<input type="submit" value = "submit" class="btn btn-info" onClick="return formNullCheck()">

プルダウンタブにユーザー一覧を表示するところでちょっと悩みましたが、
JSPを使い、事前にArrayList型のuserlist変数にユーザーの名前とIDを入れて、
for文の中でユーザー情報を一つ一つ取り出し、
の部分で指定しています。

ログイン時にセッションに入れた情報を取りでしているところ。<%ArrayList> userlist = (ArrayList>)session.getAttribute("userlist");%>


メッセージは以下のように保存されます。
メッセージの送信者、宛先のユーザーのIDとフィード投稿可否が保存されます。

f:id:isotai:20170306220111p:plain


次にフィードのメッセージ表示部分です。

<!>投稿されたメッセージの表示</!>
<div class = "center">
<%GetMessageDAO getmessagedao = new GetMessageDAO();%>
<%ArrayList<Map<Integer,String>> messagelist = getmessagedao.getMessage();%>
<%for(int i = 0; i<messagelist.size(); i++){%>
	<%Map<Integer,String> list = messagelist.get(i);%>
	<%	String message =  list.get(1);%>
	<%	String time =  list.get(5);%>
	<%	String namefrom =  list.get(6);%>
	<%	String nameto =  list.get(7);%>
<div class="activity-feed">
<div class="feed-item">
<div class="date">To:<%=nameto%></div>
<div class="text"><%=message%></div>
<div class="date">From:<%=namefrom%> (<%=time%>)</div>
</div>
</div>
<%}%>

JSPから直接DAOを呼び出しています!MVC的にはやっちゃだめとどこかで読んだ気がしますが、
これ作ってるときはそれどころではなかった!
これで一応、メッセージ投稿→ページ更新→最新の30のメッセージ表示。
といった動きで最新の投稿が常に表示されます!

ここでちょっとめんどくさいことが発覚しまして、
メッセージテーブルにはユーザーIDしか保存してないんですね。
でもやっぱりメッセージを表示するときは、To ユーザーの名前 From ユーザーの名前
で表示したいなーとなります、あたりまえですが。

ユーザーの名前を保持してるのは、userテーブルというのが別にあるんです。
これはユーザー登録のときに情報を書き込んでます。

f:id:isotai:20170306221214p:plain

さぁどうしたものかと。
幸い複数テーブルを一度にselectできるInner Join というのがあるようです。
ということで四苦八苦しながらクエリを作りました。これで無事メッセージは表示できています。

select message,useridfrom,useridto,postconfirm,time,t1.name as usernamefrom,t2.name as usernameto from usermessages ii inner join users t2 on ii.useridto = t2.userid inner join users t1 on ii.useridfrom = t1.userid where postconfirm = 'yes' order by time desc limit 30;


だいたいこんな感じです。
このあと、個人メッセージ受信用のページ、メッセージを受信したらメール通知する機能とかを作りまして、
初アプリケーションは日の目を見ることなく葬られました。