單擊導航欄上的「參與調查」按鈕->EntrySurveyAction作出相應,找到全部的Survey對象並轉發到顯示全部survey對象的頁面上供用戶選擇->用戶單擊其中一個調查進入調查頁面->頁面提供上一頁、下一頁、退出、保存等按鈕供用戶選擇->用戶單擊退出直接返回到顯示全部Survey對象的頁面上去或者單擊提交完成調查返回到參與調查的頁面上去。css
請求的方法是Action中的toSurveyPage方法html
1 public String toSurveyPage() throws Exception{ 2 //從新獲取survey對象 3 this.model=this.surveyService.getModelById(this.model.getSurveyId()); 4 float requestPage; 5 //獲得請求頁,實際上就是orderNo 6 if(parameters.get("requestPage")!=null){ 7 requestPage=Float.parseFloat(parameters.get("requestPage")[0]); 8 }else{ 9 requestPage=this.model.getMinOrderNo(); 10 } 11 Page responsePage=this.surveyService.getResponsePage(this.model,requestPage); 12 ServletActionContext.getContext().put("page",responsePage); 13 14 //將兩個參數保存到Session中去 15 this.session.put(this.CURRENT_SURVEY, this.model); 16 this.session.put(ALL_PARAMETERS, new HashMap<String,Map<String,String[]>>()); 17 return "surveyPage"; 18 }
這裏須要注意的是上面代碼中的粗體部分,該部分其實是爲了方便調用之後回顯功能、保存答案功能使用的。前端
顯示全部調查是以圖表配以文字的形式進行說明的,使用的圖標是以前說過的上傳的logo,若是沒有設置logo,則使用默認的logo。java
1 <s:iterator value="%{#surveys}" var="survey"> 2 <s:a cssClass="survey" action="EntrySurveyAction_toSurveyPage.action" namespace="/"> 3 <s:param name="surveyId" value="#survey.surveyId"></s:param> 4 <img width="200px" alt="<s:property value='%{#survey.title}'/>" src='<s:property value="getLogoPath(#survey.logoPath)"/>'/><br/> 5 <s:property value="#survey.title"/> 6 </s:a> 7 </s:iterator>
這裏還須要調用Action中的一個方法getLogoPath,該方法用於獲取logo的時機url地址,方法以下:sql
1 //判斷logo是否存在若是存在返回路徑,若是不存在,返回默認路徑 2 public String getLogoPath(String logoPath){ 3 System.out.println(logoPath); 4 if(logoPath!=null){ 5 String realPath=this.servletConetxt.getRealPath(logoPath); 6 File file=new File(realPath); 7 if(file.exists()){ 8 return servletConetxt.getContextPath()+logoPath; 9 } 10 } 11 return servletConetxt.getContextPath()+"/upload/defaultLogo.jpg"; 12 }
參與調查的頁面一直是重用的,不管點擊下一步仍是上一步,返回的頁面仍是這一個頁面,這確定是請求了一個參數,這個參數就是頁面的標識id。Action根據請求的id獲取該Page對象的全部屬性值,並將該Page對象返回到前端顯示。根據該page的orderNo屬性判斷是否還有上一頁、下一頁並根據不一樣的結果顯示出上一步、下一步、提交按鈕,可是在每一頁上都有「退出」按鈕。數據庫
上一篇筆記中提到的Page兌現的minOrderNo和maxOrderNo就是在這個時候用到的。session
導航的代碼使用strus2標籤控制判斷是否顯示上一頁、下一頁、完成這三個按鈕:數據結構
1 <!-- 導航欄界面的問題,包括上一題、下一題、退出按鈕的設計 --> 2 <div 3 style="width: 30%; margin: 0 auto; text-align: center; margin-top: 30px; font-size: 20px;"> 4 <s:if test="#page.orderNo!=#page.survey.minOrderNo"> 5 <input type="submit" 6 value="<s:property value='#page.survey.submit_pre'/>" 7 name="submit_pre" /> 8 </s:if> 9 <s:if test="#page.orderNo!=#page.survey.maxOrderNo"> 10 <input type="submit" 11 value="<s:property value='#page.survey.submit_next'/>" 12 name="submit_next"> 13 </s:if> 14 <s:if test="#page.orderNo==#page.survey.maxOrderNo"> 15 <%-- <input type="submit" 16 value="<s:property value='#page.survey.submit_done'/>" 17 name="submit_done"> --%> 18 <s:submit name="submit_done" value="%{#page.survey.submit_done}"></s:submit> 19 </s:if> 20 <input type="submit" 21 value="<s:property value='#page.survey.submit_exit'/>" 22 name="submit_exit"> 23 </div>
關鍵是Survey對象的minOrderNo和maxOrderNo是何時賦值的,又是怎麼獲取到的。這裏使用了hibernate的功能。在Survey的hibernate映射文件中使用一種新型的配置方式解決該問題。jsp
<property name="maxOrderNo" type="float"> <formula>(select max(p.orderNo) from page p where p.surveyId=surveyId)</formula> </property> <property name="minOrderNo" type="float"> <formula>(select min(p.orderNo) from page p where p.surveyId=surveyId)</formula> </property>
這是根據數據庫中的相應信息將查詢結果賦值到Bean對象中相關屬性的一種方法。這些屬性在數據庫中並無相關字段,可是在前端頁面中會使用到。formula(表達式)標籤中使用的是原生的sql語句。ide
其他問題的顯示能夠直接拷貝設計調查頁面中的設計代碼稍微修改一下就行了。
參與調查頁面的完整代碼:
1 <%@ page language="java" pageEncoding="utf-8"%> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <!-- 6 天哪,簡直不能認了,必須將struts2標籤所有換成html標籤才能正常 7 不然不能正常解析動態指定的name屬性,怪不得那個老師不使用struts2標籤,我還覺得他是傻X呢 8 9 最後一個問題:下拉列表類型的問題,是否是必需要有個默認值才行,不是默認選擇第一個嗎。 10 可是經過統計答案的過程當中發如今下拉列表框中若是沒有給他一個默認值的話,就默認沒有選擇。 11 --> 12 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 13 <title>Insert title here</title> 14 <link rel="stylesheet" 15 href="${pageContext.servletContext.contextPath}/css/header.css" 16 type="text/css"> 17 <style type="text/css"> 18 table { 19 border: 1px solid black; 20 border-collapse: collapse; 21 width: 100%; 22 } 23 tr td { 24 border: 1px solid black; 25 border-collapse: collapse; 26 } 27 28 a { 29 color: gray; 30 text-decoration: none; 31 } 32 33 a:HOVER { 34 color: red; 35 } 36 37 .tdHL { 38 text-align: left; 39 border-width: 0px; 40 } 41 42 .tdHR { 43 text-align: right; 44 border-width: 0px; 45 } 46 47 .pageTitle { 48 background-color: #CCF; 49 } 50 51 .questionTitle { 52 background-color: #CCC; 53 } 54 </style> 55 </head> 56 <body> 57 <%@ include file="/header.jsp"%> 58 這裏是答題界面! 59 <s:form namespace="/" action="EntrySurveyAction_doEntrySurvey.action"> 60 <div> 61 <s:set value="%{#page.survey.surveyId}" name="id" /> 62 <!-- 當前頁的頁碼 --> 63 <s:hidden name="pageId" value="%{#page.pageId}"></s:hidden> 64 <table> 65 <s:set var="pId" value="%{#page.pageId}"></s:set> 66 <tr> 67 <td> 68 <table style="display: inline-table;"> 69 <tr class="pageTitle"> 70 <!-- 頁面標題 --> 71 <td colspan="2" width="40%" class="tdHL"><s:property 72 value="%{#page.title}" /></td> 73 </tr> 74 <tr> 75 <td colspan="2"> 76 <table style="display: inline-table;"> 77 <tr> 78 <td width="20px"></td> 79 <td> 80 <!-- 迭代問題的集合 --> 81 <table style="display: inline-table;"> 82 <s:iterator value="%{#page.questions}" var="question"> 83 <s:set var="qid" value="%{#question.questionId}"></s:set> 84 <!-- 問題題幹 --> 85 <tr class="questionTitle"> 86 <td colspan="2" class="tdHL"><s:property 87 value="%{#question.title}" /></td> 88 </tr> 89 <!-- 問題主體,主要涉及的問題就是問題的分類 --> 90 <tr> 91 <td colspan="2"> 92 <!-- 定義變量,爲當前類型的題型 --> <s:set 93 value="%{#question.questionType}" var="qt"></s:set> <!-- 第一種題型:帶有單選框或者複選框的 94 題目標識就是題號小於4,0-3 95 --> <s:if test="#qt lt 4"> 96 <s:iterator value="#question.optionTextArr" status="st"> 97 <input name="q<s:property value='#qid'/>" 98 value='<s:property value="#st.index"/>' 99 type='<s:property value="#qt<2?'radio':'checkbox'"/>' 100 <s:property value="setTag(#pId+'','q'+#qid,#st.index,'checked')"/> 101 > 102 <s:property /> 103 <s:if test="#qt==1 || #qt==3"> 104 <br /> 105 </s:if> 106 </s:iterator> 107 <!-- 處理other的狀況 --> 108 <s:if test="#question.other"> 109 <input name="q<s:property value='#qid'/>" 110 value="other" 111 <s:property value="setTag(#pId+'','q'+#qid,'other','checked')"/> 112 type='<s:property value="#qt<2?'radio':'checkbox'"/>'>其它 113 <s:if test="#question.otherType==1"> 114 <input type="text" name='q<s:property value="#qid"/>other' 115 <s:property value="setText(#pId,'q'+#qid+'other')"/> 116 /> 117 </s:if> 118 <s:elseif test="#question.otherType==2"> 119 <select name="q<s:property value='#qid'/>other"> 120 <s:iterator value="#question.otherSelectOptionArr" status="st"> 121 <option 122 <s:property value="setTag(#pId+'','q'+#qid+'other',#st.index,'selected')"/> 123 value='<s:property value="#st.index"/>'> 124 <s:property/> 125 </option> 126 </s:iterator> 127 </select> 128 </s:elseif> 129 </s:if> 130 </s:if> 131 <!-- 第二種題型,是下拉列表類型的題型 --> 132 <s:elseif test="#qt==4"> 133 <select name="q<s:property value='#qid'/>"> 134 <s:iterator value="#question.optionTextArr" status="st"> 135 <option 136 <s:property value="setTag(#pId+'','q'+#qid,#st.index,'selected')"/> 137 value='<s:property value="#st.index"/>'><s:property/></option> 138 </s:iterator> 139 </select> 140 </s:elseif> 141 <s:elseif test="#qt==5"> 142 <input type="text" name="q<s:property value='#qid'/>" 143 <s:property value="setText(#pId,'q'+#qid)"/> 144 /> 145 </s:elseif> <!-- 第三種題型,矩陣問題,6,7,8 --> <s:else> 146 <table style="display: inline-table;"> 147 <!-- 列頭 --> 148 <tr> 149 <td></td> 150 <s:iterator value="#question.matrixColTitleArr"> 151 <td><s:property /></td> 152 </s:iterator> 153 </tr> 154 <!-- 輸出N多行 --> 155 <s:iterator value="#question.matrixRowTitleArr" 156 status="rowst"> 157 <tr> 158 <td><s:property /></td> 159 <s:iterator value="#question.matrixColTitleArr" 160 status="colst"> 161 <td><s:if test="#qt==6"> 162 <!-- 對於矩陣式單選按鈕的問題,必須將每一行視爲一個單獨的問題 --> 163 <input type="radio" 164 value='<s:property value="#rowst.index+'_'+#colst.index"/>' 165 name="q<s:property value='#qid+"_"+#rowst.index'/>" 166 <s:property value="setTag(#pId+'','q'+#qid+'_'+#rowst.index,#rowst.index+'_'+#colst.index,'checked')"/> 167 > 168 </s:if> <s:elseif test="#qt==7"> 169 <input type="checkbox" 170 value='<s:property value="#rowst.index+'_'+#colst.index"/>' 171 name="q<s:property value='#qid'/>" 172 <s:property value="setTag(#pId+'','q'+#qid,#rowst.index+'_'+#colst.index,'checked')"/> 173 > 174 </s:elseif> <s:elseif test="#qt==8"> 175 <select name="q<s:property value='#qid'/>"> 176 <s:iterator 177 status="selst" 178 value="#question.matrixSelectOptionArr"> 179 <option value='<s:property value="#rowst.index+'_'+#colst.index+'_'+#selst.index"/>' 180 <s:property value="setTag(#pId+'','q'+#qid,#rowst.index+'_'+#colst.index+'_'+#selst.index,'selected')"/> 181 > 182 <s:property /> 183 </option> 184 </s:iterator> 185 </select> 186 </s:elseif></td> 187 </s:iterator> 188 </tr> 189 </s:iterator> 190 </table> 191 </s:else> 192 </td> 193 </tr> 194 </s:iterator> 195 </table> 196 </td> 197 </tr> 198 </table> 199 </td> 200 </tr> 201 </table> 202 </td> 203 </tr> 204 </table> 205 <!-- 導航欄界面的問題,包括上一題、下一題、退出按鈕的設計 --> 206 <div 207 style="width: 30%; margin: 0 auto; text-align: center; margin-top: 30px; font-size: 20px;"> 208 <s:if test="#page.orderNo!=#page.survey.minOrderNo"> 209 <input type="submit" 210 value="<s:property value='#page.survey.submit_pre'/>" 211 name="submit_pre" /> 212 </s:if> 213 <s:if test="#page.orderNo!=#page.survey.maxOrderNo"> 214 <input type="submit" 215 value="<s:property value='#page.survey.submit_next'/>" 216 name="submit_next"> 217 </s:if> 218 <s:if test="#page.orderNo==#page.survey.maxOrderNo"> 219 <%-- <input type="submit" 220 value="<s:property value='#page.survey.submit_done'/>" 221 name="submit_done"> --%> 222 <s:submit name="submit_done" value="%{#page.survey.submit_done}"></s:submit> 223 </s:if> 224 <input type="submit" 225 value="<s:property value='#page.survey.submit_exit'/>" 226 name="submit_exit"> 227 </div> 228 </div> 229 </s:form> 230 </body> 231 </html>
到三未知,已經可以實現頁面的顯示並經過上一頁、下一頁翻頁了。下一步實現答案的回顯。所謂的答案回顯就是單擊上一步按鈕以後可以顯示出所回答的問題。
(1)這裏咱們使用HashMap的數據結構來保存全部的答案:Map<String,Map<String,String[]>> allAnswers=new HashMap<String,HashMap<String,String[]>>();
這裏key值是pageId,value值是對應頁面上的全部答案。
(2)Action中還定義了一個Map<String,String[]>類型的字段,該字段是用於保存當前頁中全部請求參數用的,固然也包括全部的答案,該字段和struts2中的params值相同,爲此,Action須要實現ParameterAware接口,以方便經過parameterIntercptor攔截器獲取到全部參數。
(3)同時爲了方便數據處理,還定義了一個「當前的調查(currentSurvey)」字段保存到了Session。
這兩個字段的初始化是在進入調查以前完成的,一下的代碼中的粗體字段是初始化的過程。
1 public String toSurveyPage() throws Exception{ 2 //從新獲取survey對象 3 this.model=this.surveyService.getModelById(this.model.getSurveyId()); 4 float requestPage; 5 //獲得請求頁,實際上就是orderNo 6 if(parameters.get("requestPage")!=null){ 7 requestPage=Float.parseFloat(parameters.get("requestPage")[0]); 8 }else{ 9 requestPage=this.model.getMinOrderNo(); 10 } 11 Page responsePage=this.surveyService.getResponsePage(this.model,requestPage); 12 ServletActionContext.getContext().put("page",responsePage); 13 14 //將兩個參數保存到Session中去 15 this.session.put(this.CURRENT_SURVEY, this.model); 16 this.session.put(ALL_PARAMETERS, new HashMap<String,Map<String,String[]>>()); 17 return "surveyPage"; 18 }
爲了解決這個問題,咱們給上一步、下一步、退出、完成按鈕進行了特殊的命名,
上一步:submit_pre,下一步:submit_next,退出:submit_exit,完成:submit_done,這樣我就可以比較方便的進行判斷了。以submit開頭是由於這麼作比較方便的標記出這四個按鈕的一種類型的按鈕,方便之後的答案處理。
一旦單擊四個按鈕中的任何一個按鈕Action都會調用一下方法處理:
1 public String doEntrySurvey() throws Exception{ 2 Page oldPage=pageService.getPage(pageId); 3 String submitType=this.getSubmitType(); 4 //上一頁 5 if(submitType.endsWith("pre")){ 6 //將答案保存到Session中 7 mergeIntoSession(); 8 Page page=pageService.getPrePage(oldPage); 9 ActionContext.getContext().put("page", page); 10 return "surveyPage"; 11 } 12 //下一頁 13 if(submitType.endsWith("next")){ 14 mergeIntoSession(); 15 Page page=pageService.getNextPage(oldPage); 16 ActionContext.getContext().put("page", page); 17 return "surveyPage"; 18 } 19 //完成 20 if(submitType.endsWith("done")){ 21 //首先保存住全部的答案到Session 22 mergeIntoSession(); 23 //而後保存全部的答案到數據庫 24 saveAllAnswers(); 25 return "toEntrySurveyPageAction"; 26 } 27 //退出 28 if(submitType.endsWith("exit")){ 29 //首先清除掉session中的全部答案 30 clearAnswersOnSession(); 31 //返回到前端的調查頁面,顯示出全部可用的調查 32 return "toEntrySurveyPageAction"; 33 } 34 return ""; 35 }
mergeIntoSession方法,該方法是將答案保存到Session的關鍵方法:
1 //將Parameters中的相關答案選項取出保存到Session中 2 private void mergeIntoSession() { 3 Map<String,Map<String,String[]>>allAnswers=(Map<String, Map<String, String[]>>) this.session.get(this.ALL_PARAMETERS); 4 //將當前頁面上的答案集合保存到全部答案的集合中 5 allAnswers.put(pageId+"", this.parameters); //將傳遞過來的全部參數所有保存起來 6 }
固然代碼很簡單,這是由於簡化處理了,將全部參數都保存了下來,包括非答案的部分。
對於非文本框的表單,咱們使用setTag(pageId,questionId,propertyName)方法來設置屬性值,對於文本框類型的表單,咱們使用setText(pageId,questionId)方法來設置屬性值。
核心代碼以下
1 <!-- 定義變量,爲當前類型的題型 --> <s:set 2 value="%{#question.questionType}" var="qt"></s:set> <!-- 第一種題型:帶有單選框或者複選框的 3 題目標識就是題號小於4,0-3 4 --> <s:if test="#qt lt 4"> 5 <s:iterator value="#question.optionTextArr" status="st"> 6 <input name="q<s:property value='#qid'/>" 7 value='<s:property value="#st.index"/>' 8 type='<s:property value="#qt<2?'radio':'checkbox'"/>' 9 <s:property value="setTag(#pId+'','q'+#qid,#st.index,'checked')"/> 10 > 11 <s:property /> 12 <s:if test="#qt==1 || #qt==3"> 13 <br /> 14 </s:if> 15 </s:iterator> 16 <!-- 處理other的狀況 --> 17 <s:if test="#question.other"> 18 <input name="q<s:property value='#qid'/>" 19 value="other" 20 <s:property value="setTag(#pId+'','q'+#qid,'other','checked')"/> 21 type='<s:property value="#qt<2?'radio':'checkbox'"/>'>其它 22 <s:if test="#question.otherType==1"> 23 <input type="text" name='q<s:property value="#qid"/>other' 24 <s:property value="setText(#pId,'q'+#qid+'other')"/> 25 /> 26 </s:if> 27 <s:elseif test="#question.otherType==2"> 28 <select name="q<s:property value='#qid'/>other"> 29 <s:iterator value="#question.otherSelectOptionArr" status="st"> 30 <option 31 <s:property value="setTag(#pId+'','q'+#qid+'other',#st.index,'selected')"/> 32 value='<s:property value="#st.index"/>'> 33 <s:property/> 34 </option> 35 </s:iterator> 36 </select> 37 </s:elseif> 38 </s:if> 39 </s:if> 40 <!-- 第二種題型,是下拉列表類型的題型 --> 41 <s:elseif test="#qt==4"> 42 <select name="q<s:property value='#qid'/>"> 43 <s:iterator value="#question.optionTextArr" status="st"> 44 <option 45 <s:property value="setTag(#pId+'','q'+#qid,#st.index,'selected')"/> 46 value='<s:property value="#st.index"/>'><s:property/></option> 47 </s:iterator> 48 </select> 49 </s:elseif> 50 <s:elseif test="#qt==5"> 51 <input type="text" name="q<s:property value='#qid'/>" 52 <s:property value="setText(#pId,'q'+#qid)"/> 53 /> 54 </s:elseif> <!-- 第三種題型,矩陣問題,6,7,8 --> <s:else> 55 <table style="display: inline-table;"> 56 <!-- 列頭 --> 57 <tr> 58 <td></td> 59 <s:iterator value="#question.matrixColTitleArr"> 60 <td><s:property /></td> 61 </s:iterator> 62 </tr> 63 <!-- 輸出N多行 --> 64 <s:iterator value="#question.matrixRowTitleArr" 65 status="rowst"> 66 <tr> 67 <td><s:property /></td> 68 <s:iterator value="#question.matrixColTitleArr" 69 status="colst"> 70 <td><s:if test="#qt==6"> 71 <!-- 對於矩陣式單選按鈕的問題,必須將每一行視爲一個單獨的問題 --> 72 <input type="radio" 73 value='<s:property value="#rowst.index+'_'+#colst.index"/>' 74 name="q<s:property value='#qid+"_"+#rowst.index'/>" 75 <s:property value="setTag(#pId+'','q'+#qid+'_'+#rowst.index,#rowst.index+'_'+#colst.index,'checked')"/> 76 > 77 </s:if> <s:elseif test="#qt==7"> 78 <input type="checkbox" 79 value='<s:property value="#rowst.index+'_'+#colst.index"/>' 80 name="q<s:property value='#qid'/>" 81 <s:property value="setTag(#pId+'','q'+#qid,#rowst.index+'_'+#colst.index,'checked')"/> 82 > 83 </s:elseif> <s:elseif test="#qt==8"> 84 <select name="q<s:property value='#qid'/>"> 85 <s:iterator 86 status="selst" 87 value="#question.matrixSelectOptionArr"> 88 <option value='<s:property value="#rowst.index+'_'+#colst.index+'_'+#selst.index"/>' 89 <s:property value="setTag(#pId+'','q'+#qid,#rowst.index+'_'+#colst.index+'_'+#selst.index,'selected')"/> 90 > 91 <s:property /> 92 </option> 93 </s:iterator> 94 </select> 95 </s:elseif></td> 96 </s:iterator> 97 </tr> 98 </s:iterator> 99 </table> 100 </s:else>
Action中定義了setTag方法和setText方法:
setTag方法:
1 public String setTag(String pageId,String name,String value,String tag){ 2 Map<String,Map<String,String[]>>allAnswers=(Map<String, Map<String, String[]>>) this.session.get(this.ALL_PARAMETERS); 3 Map<String,String[]>pageAnswers=allAnswers.get(pageId); 4 if(pageAnswers!=null){ 5 String []values=pageAnswers.get(name); 6 if(values!=null){ 7 for(String temp:values){ 8 if(temp.equals(value)){ 9 return tag; 10 } 11 } 12 } 13 } 14 return ""; 15 }
setText方法:
1 public String setText(String pageId,String name){ 2 Map<String,Map<String,String[]>>allAnswers=(Map<String, Map<String, String[]>>) this.session.get(this.ALL_PARAMETERS); 3 Map<String,String[]>pageAnswers=allAnswers.get(pageId); 4 if(pageAnswers!=null){ 5 String []values=pageAnswers.get(name); 6 if(values!=null){ 7 return "value='"+values[0]+"'"; 8 } 9 } 10 return ""; 11 }
兩個方法中特別要注意的是判空操做必定要有,由於第一次訪問頁面的時候調用setTag方法因爲Session中尚未相對應答案實體(pageId對應的答案)因此必定會報出空指針異常,可是被struts2的異常處理機制捕獲到並且沒有打印,直接就提示「沒有找到相關方法」的提示,可是經過debug調試我卻發現確實是找到了,實際上這是因爲空指針異常致使的方法執行失敗致使的,因此必定要判空,雖然不進行判空操做也沒有什麼問題,可是一次次的提示找不到方法,實在煩人。
到這裏,回顯功能就已經實現了。
當單擊「提交」的時候,Action會首先調用doEntrySurvey方法保存到全部答案到Session,而後調用saveAllAnswers方法處理全部的答案並保存到數據庫,最後重定向到顯示全部調查列表的界面。
其核心是saveAllAnswers方法,該方法會過濾全部的答案選項並將答案分門別類的進行整理最後保存到數據庫,處理的核心對象是allAnswers(HashMap<String,HashMap<String,String[]>>)。
這裏將針對矩陣式單選按鈕類型的問題集進行單獨處理,由於矩陣式單選按鈕類型的問題有一個惟一的標識:以q開頭,並且包含'_',因此比較容易單獨劃分出來。
同時對於非矩陣式單選按鈕類型的問題,默認爲都帶有其餘項,這樣比較方便處理。
保存答案的方法:
1 private void saveAllAnswers() { 2 /* 3 * 使用一個單獨的Map封裝全部的單選按鈕矩陣題型 4 * Integer類型是questionId 5 * String類型是該題目中的全部單選按鈕選項的集合 6 */ 7 Map<Integer,String>matrixRadioMap=new HashMap<Integer,String>(); 8 //使用一個集合保存住全部的答案 9 List<Answer>answers=new ArrayList<Answer>(); 10 Map<String,Map<String,String[]>>allAnswers=(Map<String, Map<String, String[]>>) this.session.get(this.ALL_PARAMETERS); 11 for(Map<String,String[]>map:allAnswers.values()){ 12 String key; 13 String[] values; 14 for(Map.Entry<String, String[]>entry:map.entrySet()){ 15 key=entry.getKey(); 16 values=entry.getValue(); 17 //首先將全部q開頭的參數都挑選出來,代表是答案的選項 18 if(key.startsWith("q")){ 19 //這是最普通的一種答案,只是q開頭,而後後面跟上一個題目的標號id 20 if(!key.contains("other")&&!key.contains("_")){ 21 Answer answer=new Answer(); 22 answer.setAnswerIndexs(StringUtils.arr2String(values)); //設置全部的答案選項 23 // answer.setAnswerTime(new Date()); //設置答題時間,這個字段先不要填寫 24 answer.setQuestionId(getQuestionId(key)); //設置問題id 25 answer.setSurveyId(getSurveyId()); //設置調查id 26 // answer.setUuid(null); //設置回答批次:回答批次不能亂寫,一次回答中的全部回答都必須使用一個回答批次 27 //處理其餘項,默認全部題目都帶有其餘項,這樣方便處理,注意,這裏必須在map變量中查找 28 String[] otherValuesArr=map.get(key+"other"); 29 answer.setOtherAnswer(StringUtils.arr2String(otherValuesArr)); //若是有其它答案的話設置其它答案 30 answers.add(answer); 31 }else if(key.contains("_")){ //若是name屬性值中帶有"_",表名必定是矩陣式單選按鈕的問題 32 Integer questionId=getMatrixRadioQuestionId(key); 33 String oldValue=matrixRadioMap.get(questionId); 34 if(oldValue!=null){ 35 matrixRadioMap.put(questionId, oldValue+","+StringUtils.arr2String(values)); 36 }else{ 37 matrixRadioMap.put(questionId,StringUtils.arr2String(values)); 38 } 39 } 40 } 41 } 42 //最後集中處理單選按鈕矩陣式問題,將全部答案保存到anwers中 43 saveRadioMatrixMapToAnwers(answers,matrixRadioMap); 44 } 45 46 /** 47 * 在這裏建立SurveyToken對象並綁定到當前線程 48 * TODO 使用分庫把保存答案:除了修改配置文件以外,還須要修改該處。 49 */ 50 SurveyToken surveyToken=new SurveyToken(); 51 Survey survey=this.surveyService.getModelById(getSurveyId()); 52 surveyToken.setSurvey(survey); 53 SurveyToken.bind(surveyToken); 54 55 writeAnswersToDB(answers); 56 }
因爲矩陣式單選按鈕類型的問題須要單獨處理,因此另外使用方法將該類問題答案保存到Map(新開的只存放答案的Map,數據結構爲Map<Integer,String>,key值爲questionId,value值爲答案列表)。
1 //將矩陣式單選按鈕的問題保存到answes中 2 private void saveRadioMatrixMapToAnwers(List<Answer> answers, Map<Integer, String> matrixRadioMap) { 3 Integer key; 4 String value; 5 for(Map.Entry<Integer, String>entry:matrixRadioMap.entrySet()){ 6 key=entry.getKey(); 7 value=entry.getValue(); 8 Answer answer=new Answer(); 9 answer.setAnswerIndexs(value); 10 // answer.setAnswerTime(new Date()); 11 answer.setQuestionId(key); 12 answer.setSurveyId(getSurveyId()); 13 answers.add(answer); 14 } 15 }
最後集中保存到數據庫中
1 /** 2 * 將答案所有寫到數據庫 3 * @param answers 4 */ 5 private void writeAnswersToDB(List<Answer> answers) { 6 for(Answer answer:answers){ 7 answerService.saveAnswer(answer); 8 } 9 }
至此,已經可以將採集到的答案保存到數據庫中了,下一步進行數據統計。