WAP手機上的問卷調查系統的構建
普通的網頁問卷調查系統大家一定都見過,但是大家有沒有試過在WAP上進行問卷調查呢?估計大部分的朋友都沒有見過,那就讓我們來寫一個吧!
想一想怎么實現這個系統呢?首先建立一個頁面,顯示將就哪一個問題進行調查或投票,一般是出現一個復選框,給出問題和若干選項,服務器收集投票,存入日志文件或存入數據庫,并能顯示問卷調查結果,這就是一個問卷調查系統的構思。其實在WAP手機上也同樣用這種思想來構建問卷調查系統,但是必須顧及手機的特點:顯示面積小,且要結合WML編程。
我在下面給出了一個相當簡單的手機問卷調查系統的Java Servlet編寫的,為了簡單起見我沒有使用數據庫而是使用了一個日志文件存放投票信息,其實這個程序的主要目的還是為了讓大家看看Java編程的思想,就是結構化和可重用性。
現在我把這個程序的使用方法介紹一下,編譯程序WapVoteServlet.class以后,放入運行的Java Servlet目錄下。你可以使用自己的WML素材來編寫WML頁面,只是把WapVoteServlet作為存儲和瀏覽結果的一段腳本程序;當然,如果你對WML不是非常熟悉的話,你也可以用本程序來生成調查問卷。下面我將就第二種用法來介紹,第一種用法請朋友們自己參閱WML相應的資料。
用法是: http://your_wap_host/servlet/WapVoteServlet?config=config_file ?act=vote
用于提交投票或調查選項
http://your_wap_host/servlet/WapVoteServlet?config=config_file ?act=log
用來顯示投票或調查結果
http://your_wap_host/servlet/WapVoteServlet?config=config_file ?act=view
用來生成調查,可以完全不知道如何編寫WML
配置文件中的參數的詳解:
log=your_file_is_here
log文件是用來存儲投票或調查結果的文件,這個參數是強制的,必須寫出它所在的路徑
after=http://your_wap_host/your_page.htm
after為用戶提交投票或調查后所顯示的頁面,默認為當前的投票結果
cookies=0
使用cookie是為了防止用戶多次投票,默認值為0 即不使用cookie,cookies=1為使用
bgcolor=#FFFFFF
背景顏色(默認為白色)
fgcolor=#000000
前景顏色(默認為黑色)
size=2
字體大小
face=Verdana,Arial
默認字體
votecolor=#FF0000
投票結果是以棒狀圖顯示出來,所以必須定義棒的顏色
title=Your Survey
你的調查的標題
options=Your option1,Your Option2,Your Option3
你的選項如對于天極網的喜好程度“ 喜歡,比較喜歡,不喜歡 ”,這個參數是強制參數,每個選項以逗號分開
column=1
選項在頁面中排列的位置 column等于1表示在同一縱列,0表示在同一行
日志文件的格式是:
文本文件,用逗號隔開各個不同的值,每一行包括:客戶機IP地址,日期和選項值 。
配置文件實例:
#
# vote config file
#
log=c:catalinalogsvotelog.txt
after=c:catalinawebappsexamplesservletvote.html
options=搜狐,新浪,網易
column=0
title=您喜歡哪一個門戶網站
cookies=1
bgcolor=#FFFFFF
fgcolor=#000000
size=2
face=Verdana,Arial
votecolor=#FF0000
現在讓我們來看一看源程序吧:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class WapVoteServlet extends HttpServlet
{
public WapVoteServlet()
{
}
private static final String CONFIG = "config";
private static final String ACTION = "act";
private static final String VOTE = "vote";
private static final String LOG = "log";
private static final String AFTER = "after";
private static final String VIEW = "view";
private static final String COOKIES = "cookies";
private static final String BGCOLOR = "bgcolor";
private static final String FGCOLOR = "fgcolor";
private static final String SIZE = "size";
private static final String FACE = "face";
private static final String TITLE = "title";
private static final String COLUMN = "column";
private static final String VOTECOLOR = "votecolor";
private static final String DEFBGCOLOR = "#FFFFFF";
private static final String DEFFGCOLOR = "#000000";
private static final String DEFVOTECOLOR = "#FF0000";
private static final String DEFCOOKIES = "0";
private static final String DEFCOLUMN = "1";
private static final String DEFTITLE = "A Free & Simple Vote System";
private static final String OPTIONS = "options";
private static final String EDITED = "edited";
private static final String FICT = "fct";
private static final String WAPVOTE = "wpv";
private static final int MAX_WML = 900;
private static final int MAX_VOTES = 20;
private static String NEWLINE = "";
private static Hashtable cfgs;
private static Hashtable forLock;
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
NEWLINE = System.getProperty("line.separator");
cfgs = new Hashtable();
forLock = new Hashtable();
}
file://由于使用POST發送表單,所以現用doPost來處理POST請求
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doGet(request, response); file://調用doGet去處理POST請求
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
file://用于處理GET請求
throws ServletException, IOException
{
String s = "";
String s1 = "";
s = HttpUtils.getRequestURL(request).toString();//把收到的請求轉化成字符串
int i;
if((i = s.indexOf("?")) > 0) file://想一想為什么要這么寫?
s = s.substring(0, i);
s1 = request.getQueryString(); file://取的請求的字符串
if(s1 == null)//如果為空,既是沒有寫上配置文件名,故要發出錯誤信息
{
errorMessage("不能讀到配置文件", null, request, response);
return;
}
String s2 = getFromQuery(s1, "config=");//讀取請求中"&"后的字符串
if(s2.length() == 0)
s2 = s1;
String s3 = getFromQuery(s1, "act=");
Hashtable hashtable = getConfig(s2);//讀取配置文件
if(hashtable.get("log") == null)//如果配置文件中沒有log參數,則出現錯誤信息
{
errorMessage("不能從你的配置文件中發現日志文件名!", hashtable, request, response);
return;
}
if(s3.length() == 0) file://s3為act后的字符串
s3 = "vote";
if(((String)hashtable.get("cookies")).equals("1") && s3.equals("vote"))
{
Cookie acookie[] = request.getCookies(); file://設立cookie是為了防止用戶多次投票
file://下面的循環是為了能找出你是否已經投過票
if(acookie != null)
{
for(int j = 0; j < acookie.length; j++)
{
Cookie cookie = acookie[j];
if(s2.equals(cookie.getName()))
{
errorMessage("你的投票被取消了", hashtable, request, response);
return;
}
}
}
Cookie cookie1 = new Cookie(s2, "yes");
cookie1.setMaxAge(0x15180);
response.addCookie(cookie1);
}
if(s3.equals("vote"))
{
takeVote(s, s2, hashtable, request, response);
return;
}
if(s3.equals("log"))
{
showLog(s, hashtable, request, response);
return;
}
if(hashtable.get("options") == null)
{
errorMessage("不能讀入你的配置值", hashtable, request, response);
return;
}
else
{
showVote(s, s2, hashtable, request, response);
return;
}
}
private void readConfig(String s, Hashtable hashtable) file://讀取配置文件
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(s)));
String s1;
while((s1 = reader.readLine()) != null) file://從配置文件中讀入一行參數字符串
{
s1 = s1.trim(); file://移去s1中的空格
if(s1.length() > 0)
{
int i = s1.indexOf("=");//在s1中尋找“=”,i為被=分成的段數
if(i > 0 && i < s1.length() - 1 && s1.charAt(0) != '#' && !s1.startsWith("//"))
file://參數的第一個字符不能為#和//
hashtable.put(s1.substring(0, i).trim(), s1.substring(i + 1).trim());
file://把等號前后的字符串分別存入哈西表中
}
}
reader.close();
File file = new File(s);
hashtable.put("edited", String.valueOf(file.lastModified()));
}
catch(Exception _ex) { }
if(hashtable.get("bgcolor") == null)
hashtable.put("bgcolor", "#FFFFFF"); file://向哈西表中寫入默認的背景色
if(hashtable.get("fgcolor") == null)
hashtable.put("fgcolor", "#000000"); file://向哈西表中寫入默認的前景色
if(hashtable.get("column") == null)
hashtable.put("column", "1"); file://向哈西表中寫入默認的column值
if(hashtable.get("cookies") == null)
hashtable.put("cookies", "0"); file://向哈西表中寫入默認的cookies值為0
if(hashtable.get("title") == null)
hashtable.put("title", "A Free & Simple Vote System");
file://向哈西表中寫入默認的標題
if(hashtable.get("votecolor") == null)
hashtable.put("votecolor", "#FF0000"); file://向哈西表中寫入默認投票色
hashtable.put("fct", new Integer(0));
}
private Hashtable getConfig(String s) file://打開配置文件
{
Hashtable hashtable;
if((hashtable = (Hashtable)cfgs.get(s)) != null)
{
File file = new File(s);
String s1 = (String)hashtable.get("edited");
if(s1.equals(String.valueOf(file.lastModified())))
return hashtable; file://如果文件被編輯過,則返回哈西表
cfgs.remove(s);
hashtable = null;
}
hashtable = new Hashtable();
readConfig(s, hashtable);
cfgs.put(s, hashtable);
String s2 = (String)hashtable.get("log");
if(s2 != null && forLock.get(s2) == null)
forLock.put(s2, new Object());
return hashtable;
}
private void showVote(String s, String s1, Hashtable hashtable, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String s2 = (String)hashtable.get("options");
String s3 = (String)hashtable.get("column");
String s4 = (String)hashtable.get("title");
String s6 = getFont(hashtable);
String s7 = "";
String s8 = "";
if(request.getHeader("Accept").indexOf("wap.wml") >= 0)
PrintWriter OUT;
response.setContentType("text/vnd.wap.wml");
OUT = response.getWriter();
OUT.println("<?xml version="1.0"?>");
OUT.println("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">");
OUT.println("<wml>");
OUT.println("<CARD id='"showvote"' title='""' ?? + (String)hashtable.get(?title?)>");
OUT.println("<DO label='"Vote"' type='"accept"'>");
OUT.println("<GO ?? + method='"post"' vote? ?=" + s1 + " ?act? &? ?config? ??? s href='""'>");
OUT.println("<POSTFIELD value='"$(sVote)"/' name='"wpv"'>");
OUT.println("</GO>");
OUT.println("</DO>");
OUT.println("<P mode='"nowrap"'><B>" + s4 + "</B></P>");
OUT.println(" <P mode='"nowrap"'>");
OUT.println("<SELECT name='"sVote"'>");
StringTokenizer str = new StringTokenizer(s2, ",");
while(str.hasMoreTokens())
{
String s5 = str.nextToken();
OUT.println("<OPTION selected value='""' ?? + s5>" + s5 + "</OPTION>"); }
OUT.println("</SELECT>");
OUT.println("</P>");
OUT.println("</CARD>");
OUT.println("</WML>");
OUT.flush();
OUT.close();
}
private void takeVote(String s, String s1, Hashtable hashtable, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String s2 = (String)hashtable.get("log");
String s3 = (String)hashtable.get("after");
String s6 = "";
Enumeration enumeration = request.getParameterNames();
if(request.getHeader("Accept").indexOf("wap.wml") >= 0)
file://判斷是否為WAP設備接收
{
s6 = request.getParameter("wpv");
if(s6 == null)
s6 = "";
}
if(s6.length() > 0)
writeLog(hashtable, request, s6, s2);
if(s3 == null) file://如果s3為空,則顯示日志文件
{
showLog(s, hashtable, request, response);
return;
}
else file://否則發送重定向
{
String s4 = s + "?" + "config" + "=" + s1 + "&" + "act" + "=" + "log";
response.sendRedirect(s4);
return;
}
}
private void writeLog(Hashtable hashtable, HttpServletRequest request, String s, String s1)//寫日志文件
{
String s2 = request.getRemoteAddr(); file://取得客戶機的IP地址
try{
synchronized(forLock.get(s1))
file://注意:使用synchronized關鍵字,說明同一時間只能有一個寫動作,其余的要在隊列中等待
{
int i = ((Integer)hashtable.get("fct")).intValue();
file://取得日志文件的fct值
if(i >= 20)
{
return;
}
hashtable.put("fct", new Integer(i + 1));//把fct值加1放回哈希表
FileWriter filewriter = new FileWriter(s1, true);
PrintWriter OUT = new PrintWriter(filewriter);
OUT.println((s2 != null ? s2 : "未知地址") + "," + new Date() + "," + s);
OUT.flush();
OUT.close();
}
return;
}
catch(IOException _ex)
{
return;
}
}
private void errorMessage(String s, Hashtable hashtable, HttpServletRequest request, HttpServletResponse response)//輸出錯誤信息
throws IOException
{
PrintWriter OUT = null;
response.setContentType("text/vnd.wap.wml");//設置為WML文件格式
OUT = response.getWriter();
OUT.println("");
OUT.println("");
OUT.println("<WML>");
OUT.println("
OUT.println(" " + s + "");
OUT.println("");
OUT.println("");
OUT.flush();
OUT.close();
}
private void showLog(String s, Hashtable hashtable, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String s1 = (String)hashtable.get("log");
String s2 = getFont(hashtable);
Vector vector = new Vector();
Hashtable hashtable1 = new Hashtable();
StringBuffer stringbuffer = new StringBuffer("");
long l = 0L;
String s7 = (String)hashtable.get("title");
try{
synchronized(forLock.get(s1))
{
BufferedReader bufferedreader = new BufferedReader(new putStreamReader(new FileInputStream(s1)));
String s3;
while((s3 = bufferedreader.readLine()) != null) file://讀入一條參數
vector.addElement(s3); file://作為一個元素加入向量中
bufferedreader.close();
}
}
catch(Exception _ex) { }
if(request.getHeader("Accept").indexOf("wap.wml") >= 0)
for(int j = 0; j < vector.size(); j++)
{
String s4 = (String)vector.elementAt(j); file://取得向量中第j+1個元素
int i = s4.indexOf(","); file://i表示s4被逗號“,”分隔開的段數
if(i > 0 && i != s4.length() - 1)
s4 = s4.substring(i + 1);
i = s4.indexOf(",");
if(i > 0 && i != s4.length() - 1)
s4 = s4.substring(i + 1);
Long long1;
if((long1 = (Long)hashtable1.get(s4)) == null)
{
hashtable1.put(s4, new Long(1L));
}
else
{
hashtable1.remove(s4);
hashtable1.put(s4, new Long(long1.longValue() + 1L));
}
l++;
}
vector = null;
PrintWriter OUT;
response.setContentType("text/vnd.wap.wml");
OUT = response.getWriter();
OUT.println("");
OUT.println("");
OUT.println("
OUT.println("<CARD id='"voteres"' title='""' ?? + (String)hashtable.get(?title?)> <P>");
if(hashtable1.size() == 0)
OUT.println(" 我們現在還未收到任何投票");
else
{
OUT.println(" " + s7 + "");
while(hashtable1.size() > 0)
{
Enumeration enumeration = hashtable1.keys();
long l1 = 0L;
String s6 = null;
while(enumeration.hasMoreElements())
{
String s5 = (String)enumeration.nextElement();
long l2 = ((Long)hashtable1.get(s5)).longValue();
if(l2 > l1)
{
s6 = s5;
l1 = l2;
}
}
hashtable1.remove(s6);
stringbuffer.append(" " + s6 + "" + NEWLINE);
stringbuffer.append(" " + l1 + " (" + formatValue((float)((100D * (double)(float)l1) / (double)(float)l)) + "%)" + NEWLINE);
if(stringbuffer.length() > 900){
break;
}
OUT.println(stringbuffer.toString());
}
OUT.println("");
OUT.println("");
hashtable1 = null;
OUT.flush();
OUT.close();
}
private String getFont(Hashtable hashtable)
{
String s1 = "
String s;
if((s = (String)hashtable.get("face")) != null){
s1 = s1 + " face="" + s + """;
if((s = (String)hashtable.get("size")) != null){
s1 = s1 + " size="" + s + """;
return s1 + ">";
}
private String getFromQuery(String s, String s1) file://從s中找出s1
{
if(s == null)
return "";//如果s為空,當然返回“”
int i;
if((i = s.indexOf(s1)) < 0)//如果s中找不到s1,也返回空值
return "";
String s2 = s.substring(i + s1.length());
file://把s1所表示字符串后的值賦予s2,Config=conf_file&act=vote
if((i = s2.indexOf("&")) < 0) file://如果s2中沒有&,則返回s2的值
return s2;
else
return s2.substring(0, i); file://否則返回&后的字符串
}
private String formatValue(float f)
{
String s = String.valueOf(f);
int i = s.indexOf(".");
if(i > 0 && i + 4 < s.length() && s.indexOf("e") < 0 && s.indexOf("E") < 0){
s = s.substring(0, i + 4);
return s;
}}</SELECT>