網路票選

如果要一群人想要產生一個共識,通常最困難的是安排一個大家都有空的時間進行表決。畢竟無論是同學、同事、朋友甚至是家人,每個人都有各自事情要做。為求公平公正公開透明,使得時間通常也受至限制。要找到所有人都有空檔且能出席的共同時間需要花很多時間溝通與安排規劃,除非個別連絡確認時間。利用網路應用種式進行表決能解決這個問題,透過第三方提供的服務使得公平公正不受質疑,又能夠讓參與者不受時間和空間限制。在許多先進國家的社會都承認網路表決的結果,甚至受到法律的保障。

裝飾器

使用者的瀏覽器客戶端與動態網頁伺服器端連繫與溝通看似簡單,事實上非常不容易。世界上同時數十億個網路使用者,要將他們相互建立關係並不是件容易的事。在網頁程式中有眾多方法暫存與客戶端的互動記錄,首先可以利用Request.Session物件來進行,這也是本次的主題。首先請建立新網頁「ch05.jsp」,並且將裝飾器「temp.jsp」內容完整複製到新建立的「ch05.jsp」中。

未建立投票機制

沒有建立正式的Session機制的情況下,伺服器雖然在底層有基本資料使得客戶端不至於斷線。但是在應用程式的使用層級仍然不記錄曾經投票的連線。這使得投票的動作可以無限制的從遠端執行,這是很明顯的問題。早期的網路文化時常存在這個漏洞,經營者有意或無意的釋放個漏洞以期待產生驚人的數字。事實上這只要在資料庫端利用公式計算就可以達到灌水效果,現在實名制度和其他記名方式都能夠準確的建立投票機制。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@include file="conn.jsp"%><!-- 資料庫連線 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>討論區最有價值的主題票選</title><!-- 瀏覽器標題 -->
<link href="style.css" rel="stylesheet">
<!-- 自定義裝飾 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet">
<script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
</head>
<body>
	<%@include file="menu.jsp"%><!-- 選單 -->
	<div class="container">		
		<div class="page-header">
			<h1>討論區最有價值的主題票選</h1><!-- 網頁標題 -->
		</div>
		<%
        request.setCharacterEncoding("UTF-8");//將輸入編碼設定為UTF-8
        response.setCharacterEncoding("UTF-8");//將輸出編碼設定為UTF-8
        try {//建立資料表以try,catch的方式,因CREATE TABLE IF NOT EXISTS在不同資料庫中有錯誤的風險與舊資料被清除的問題
                stat.executeUpdate("CREATE TABLE 'bbs_vote' ('bbs'      INTEGER,'cnt'   INTEGER,'key'   TEXT,PRIMARY KEY('bbs'));");
        } catch (Exception e) {}	           
        if(request.getParameter("Oid")!=null){
	        try{
	        	stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);");
	        }catch(Exception e){}
        	stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid"));
        }                               
        sql = "SELECT b.*,(SELECT COUNT(*)FROM bbs_feedback WHERE bbs=b.Oid)as f_cnt, IFNULL((SELECT cnt FROM bbs_vote WHERE bbs=b.Oid),0)as v_cnt FROM bbs b";//建立查詢字串
        rs = stat.executeQuery(sql);//查詢結果
	  	%>
		<form action="ch05.jsp" method="GET">                     
		<%while (rs.next()) {%>                   
		<h2>
	        <input type="radio" name="Oid" value="<%=rs.getString("Oid")%>">
	        <a href="ch05.jsp?Oid=<%=rs.getString("Oid")%>"><%=rs.getString("title")%></a>
	        <small><%=rs.getString("user")%>, <%=rs.getString("f_cnt")%>篇回覆</small>
	        <small><%=rs.getString("v_cnt")%>票</small>
		</h2>
		<hr />
		<%}%>                     
		<button class="btn" type="submit">確定</button>
		</form>
	</div>
	<%@include file="foot.jsp"%><!-- 頁尾 -->
</body>
</html>

建立投票機制

沒有記名的資訊系統,通常無法做精準的投票。以下程式碼以基本的session方式,驗證使用者在這個網頁的狀況。
在第1次投票成功時,計錄1個名為voted的session。在此同時也判斷voted是不是存在,若存在就不進行計數的動作。
if(request.getParameter("Oid")!=null&& session.getAttribute("voted")==null){
     try{
     	stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);");                                     	
     }catch(Exception e){}
     stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid"));
     session.setAttribute("voted", true);
}                  


網頁本體加上檢查voted是否存在,若存在即跳出警告。
<%if(session.getAttribute("voted")!=null) { %>
<script>alert("已投票");</script>
<%} %>

完整的程式碼請參考
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@include file="conn.jsp"%><!-- 資料庫連線 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>討論區最有價值的主題票選</title><!-- 瀏覽器標題 -->
<link href="style.css" rel="stylesheet">
<!-- 自定義裝飾 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet">
<script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
</head>
<body>
	<%@include file="menu.jsp"%><!-- 選單 -->
	<div class="container">		
		<div class="page-header">
			<h1>討論區最有價值的主題票選</h1><!-- 網頁標題 -->
		</div>
		<%
        request.setCharacterEncoding("UTF-8");//將輸入編碼設定為UTF-8
        response.setCharacterEncoding("UTF-8");//將輸出編碼設定為UTF-8
        try {//建立資料表以try,catch的方式,因CREATE TABLE IF NOT EXISTS在不同資料庫中有錯誤的風險與舊資料被清除的問題
                stat.executeUpdate("CREATE TABLE 'bbs_vote' ('bbs'      INTEGER,'cnt'   INTEGER,'key'   TEXT,PRIMARY KEY('bbs'));");
        } catch (Exception e) {}	           
        if(request.getParameter("Oid")!=null&& session.getAttribute("voted")==null){
            try{
               stat.executeUpdate("INSERT INTO bbs_vote(bbs, cnt)VALUES("+request.getParameter("Oid")+", 0);");                                        
            }catch(Exception e){}
            stat.executeUpdate("UPDATE bbs_vote SET cnt=cnt+1 WHERE bbs="+request.getParameter("Oid"));
            session.setAttribute("voted", true);
       	}                           
        sql = "SELECT b.*,(SELECT COUNT(*)FROM bbs_feedback WHERE bbs=b.Oid)as f_cnt, IFNULL((SELECT cnt FROM bbs_vote WHERE bbs=b.Oid),0)as v_cnt FROM bbs b";//建立查詢字串
        rs = stat.executeQuery(sql);//查詢結果
	  	%>
	  	<%if(session.getAttribute("voted")!=null) { %>
		<script>alert("已投票");</script>
		<%} %>
		<form action="ch05.jsp" method="GET">                     
		<%while (rs.next()) {%>                   
		<h2>
	        <input type="radio" name="Oid" value="<%=rs.getString("Oid")%>">
	        <a href="ch05.jsp?Oid=<%=rs.getString("Oid")%>"><%=rs.getString("title")%></a>
	        <small><%=rs.getString("user")%>, <%=rs.getString("f_cnt")%>篇回覆</small>
	        <small><%=rs.getString("v_cnt")%>票</small>
		</h2>
		<hr />
		<%}%>                     
		<button class="btn" type="submit">確定</button>
		</form>
	</div>
	<%@include file="foot.jsp"%><!-- 頁尾 -->
</body>
</html>

沒有留言:

張貼留言