一、開發環境
1 Java語言
Java語言是當今為止依然在編程語言行業具有生命力的常青樹之一。Java語言最原始的誕生,不僅僅是創造者感覺C語言在編程上面很麻煩,如果只是專注于業務邏輯的處理,會導致忽略了各種指針以及垃圾回收這些操作,導致出現問題需要解決的時間往往大于正常編程處理業務邏輯的時間,這些是非常浪費時間的。Java語言的創造者就完美的解決了這個問題,把指針處理和垃圾處理全部自動化,雖然這會損失一些性能,但是隨著計算機硬件的不斷發展,這些性能是可以忽略考慮的。并且C語言是針對硬件開發的語言,在符合條件的硬件上面進行編程可以最大化利用硬件的性能,但是隨著硬件的變化或者操作系統的變更,如果還是用C語言的話需要對整個程序進行重新編程,只有隨著市場變化而變化的語言才是符合潮流,符合生存規律的語言。Java語言的創造者就針對C語言的缺點專門開發了Java語言。讓Java語言不管是在什么樣的環境里都是可以運行,因為在Java語言運行外面套了一個殼,也就是虛擬機,只要是Java虛擬機能安裝的電腦都可以運行Java的程序。
2 MYSQL數據庫
MySQL數據庫是關系型數據庫的一種,也是傳統的行式數據模式,獲取一些數據是先一行一行的獲取,然后一行一行的顯示,與最近大數據興起的列式數據庫有著明顯的不同。行式數據庫主要是處理最重要的數據邏輯部分,并且必須是有效數據,這樣每一處的數據關聯都是不可損壞,如果對數據安全性比較高的肯定是需要選擇MySQL數據庫,列式數據庫的發明僅僅是因為讀取效率高,與傳統的MySQL數據庫比起來在數據寫入方面并不會高明到哪里。MySQL雖然比起oracle或者SQL SERVER來講,安裝包只是幾十兆甚至幾百兆,有點小,但是功能并不會弱到哪里,嚴格遵循SQL標準語法。MySQL的數據存放形式從大向小的說是數據庫最大,然后是表,每個表里面存放數據是有一定的規則的,數據存放是表格形式的,也就是說有橫也有豎,橫著的為行,一般表示一條數據,每個表都有字段,而字段是以列的形式存在,這樣能保證一條數據每一個字段對應的是相同數據類型的數據。表與表之間還可以進行關聯,進行分表操作,如果一條數據相關項目屬性太多,那么可以把有效的相關聯系做成關聯,可以設定是否唯一。
3 IDEA開發工具
IDEA是捷克共和國的Java程序員開發人員創造的一個開發軟件,剛開始主要是對于用Eclipse軟件他們用得不順手,所以直接開發了這款軟件。之所以不順手原因在于沒有代碼提升功能,原因是Eclipse只是把代碼提示作為一種插件形式的存在,如果有些程序開發人員不清楚代碼提示插件可能會出問題,并且代碼提示只是用來作為插件,所以功能上有所欠缺。IDEA不僅僅代碼提示做的很好,在代碼重構上面更上如虎添翼,程序開發人員可以選擇一段代碼然后IDEA就會對代碼進行分解重構,有效的把代碼弄得更夠層次感,復用性更高,用著更簡潔和方便,大大的減少了代碼工作量,提升了代碼開發效率。當然,IDEA對于使用者這么好,肯定也是有目的的,原因在于插件越多越友好,就需要花費大量的金錢來使用,所以說IDEA使用主要是看自己喜好。
4 Spring Boot框架
Spring Boot是一種不需要代碼生成的一種框架,并且可以不需要配置任何的XML文件就可以,因為Spring Boot里面自帶了很多接口,只需要配置不同的接口就會自動的應用并且識別需要的依賴,在配置方面非常的方便,使用起來感覺像沒有用到框架的感覺。Spring Boot有很多默認的配置文件,并且可以對默認的配置文件進行修改,可以設置為自動加載,可以對異常處理分為全局異常處理和默認異常處理。Spring Boot使用過程中就像是使用什么直接注冊什么,所謂的注冊也就是在對應的類和方法上面進行一個特殊的聲明即可。
二、系統設計
1 功能結構設計
圖1即為設計的管理員功能結構,管理員權限操作的功能包括對注冊用戶信息的管理,對問卷,題目,問卷調查,新聞資訊等信息的管理。

圖1 管理員功能結構
圖2即為設計的用戶功能結構,用戶權限操作的功能包括參與問卷調查,查看新聞,查看問卷調查記錄。

圖2 用戶功能結構
2 數據庫設計
在線問卷調查系統運行中產生的數據需要按照提前設置的存儲規則進行保存,而這個存儲規則則是在數據庫的設計中進行設置的。通常情況下,為了更好的配合系統運行,也要給用戶帶來良好的使用體驗,設計一個很好的數據庫是必須的,因為它能減少用戶的等待時間,還可以對系統的請求在最短時間內進行響應。所以,對數據庫設計時,需要花費一定的時間來分析系統對于數據存儲的要求以及存儲的具體數據,然后設計具體的存儲規則,保證數據庫能夠對系統的各種數據請求進行及時回應,縮短數據處理時間,并在一定程度上降低數據冗余,節省存儲空間。
2.1 數據庫概念設計
實體-聯系圖還有一個名稱即E-R圖,是Entity Relationship Diagram各英文單詞首字母的縮寫,它這種概念模型通常用于對現實世界進行描述。同時它還是一種能夠直觀表達數據中實體,聯系,屬性的有效手段。繪制E-R圖能夠選擇的工具也有很多,但是Office Visio 這款軟件在E-R圖的繪制上一般都是作為首選工具,因為它是基于可視化處理,使用它創建E-R圖非常簡單。使用基本的E-R圖構成元素,比如橢圓,菱形,矩形,還有實線段來表達對應的信息,橢圓代表屬性,即實體的特征,矩形代表實體,即數據庫中的一個具體數據表,菱形代表實體中相互關系,實線段主要是完成橢圓,矩形,菱形的連接,基于這樣的方式即可完成對本系統的E-R圖進行完整繪制。
(1)圖4即為題目這個實體所擁有的屬性值。

圖4 題目實體屬性圖
(2)圖5即為用戶這個實體所擁有的屬性值。

圖5 用戶實體屬性圖
(3)圖6即為問卷這個實體所擁有的屬性值。

圖6 問卷實體屬性圖
- 圖7即為問卷調查記錄這個實體所擁有的屬性值。

圖7 問卷調查記錄實體屬性圖
- 圖8即為上面介紹的實體中存在的聯系。

圖8 實體間關系E-R圖
2.2 數據庫物理設計
本小節主要任務即是根據上述內容進行數據存儲結構的設計,也就是在數據庫中設計存放本系統的數據的數據表,設計數據表時,需要對各個字段進行確定,通常來說,一個實體與一張數據表相對應,實體的屬性就用來表示字段名稱,不同的字段表示的數據類型以及取值都不相同,這里需要根據系統實際數據的情況進行設置,同時也需要在具體表中確定該表的主鍵,以及該表各個字段是否能夠保持空等進行說明,設計完成一張數據表的結構之后,在保存時同樣要命名,盡量選擇英文名稱進行命名并保存,方便今后系統對數據表進行數據存儲訪問時,在提高數據存儲效率的同時,還不容易導致系統出錯。接下來就對設計的數據表進行展示。
表1 問卷表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(20) | 否 |
exampaper_name | 問卷名稱 | varchar(200) | 否 |
exampaper_date | 時長(分鐘) | int(11) | 否 |
exampaper_jieshuyu | 結束語 | varchar(255) | 是 |
exampaper_types | 問卷狀態 | int(11) | 否 |
create_time | 創建時間 | timestamp | 否 |
表2 題目表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(20) | 否 |
exampaper_id | 所屬問卷id(外鍵) | int(20) | 否 |
examquestion_name | 試題名稱 | varchar(200) | 否 |
examquestion_options | 選項 | longtext | 是 |
examquestion_types | 試題類型 | int(20) | 是 |
examquestion_sequence | 試題排序,值越大排越前面 | int(20) | 是 |
create_time | 創建時間 | timestamp | 否 |
表3 問卷調查記錄表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(20) | 否 |
examrecord_uuid_number | 問卷調查編號 | varchar(200) | 是 |
yonghu_id | 問卷調查用戶 | int(20) | 否 |
exampaper_id | 所屬問卷id(外鍵) | int(20) | 否 |
insert_time | 問卷調查時間 | timestamp | 否 |
create_time | 創建時間 | timestamp | 否 |
表4 管理員表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | bigint(20) | 否 |
username | 用戶名 | varchar(100) | 否 |
password | 密碼 | varchar(100) | 否 |
role | 角色 | varchar(100) | 是 |
addtime | 新增時間 | timestamp | 否 |
表5 新聞資訊表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(11) | 否 |
news_name | 新聞資訊名稱 | varchar(200) | 是 |
news_types | 新聞類型 | int(11) | 是 |
news_photo | 新聞資訊圖片 | varchar(200) | 是 |
insert_time | 新聞資訊時間 | timestamp | 是 |
news_content | 新聞資訊詳情 | text | 是 |
create_time | 創建時間 | timestamp | 是 |
表6 答題詳情表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(20) | 否 |
examredetails_uuid_number | 問卷編號 | varchar(200) | 是 |
yonghu_id | 用戶id | int(20) | 否 |
examquestion_id | 試題id(外鍵) | int(20) | 否 |
examredetails_myanswer | 用戶選項 | varchar(200) | 是 |
create_time | 創建時間 | timestamp | 否 |
表7 用戶表
字段 | 注釋 | 類型 | 空 |
---|---|---|---|
id (主鍵) | 主鍵 | int(11) | 否 |
username | 賬戶 | varchar(200) | 是 |
password | 密碼 | varchar(200) | 是 |
yonghu_name | 用戶姓名 | varchar(200) | 是 |
sex_types | 性別 | int(11) | 是 |
yonghu_id_number | 身份證號 | varchar(200) | 是 |
yonghu_phone | 手機號 | varchar(200) | 是 |
yonghu_photo | 照片 | varchar(200) | 是 |
create_time | 創建時間 | timestamp | 是 |
三、系統實現
編程人員在搭建的開發環境中,運用編程技術實現本系統設計的各個操作權限的功能。在本節中,就展示部分操作權限的功能與界面。
1 管理員功能實現
1.1 問卷管理
圖1 即為編碼實現的問卷管理界面,管理員在該界面中可以對已有問卷進行啟用或禁用,可以新增問卷,編輯更改已有問卷的資料,包括問卷名稱,結束語等信息,可以刪除需要刪除的問卷,可以根據問卷名稱,問卷的狀態來獲取需要的問卷信息。

圖1 問卷管理界面
核心代碼:
/*** 后端修改*/
@RequestMapping("/update")
public R update(@RequestBody ExampaperEntity exampaper, HttpServletRequest request){logger.debug("update方法:,,Controller:{},,exampaper:{}",this.getClass().getName(),exampaper.toString());String role = String.valueOf(request.getSession().getAttribute("role"));if(StringUtil.isEmpty(role))return R.error(511,"權限為空");//根據字段查詢是否有相同數據Wrapper<ExampaperEntity> queryWrapper = new EntityWrapper<ExampaperEntity>().notIn("id",exampaper.getId()).andNew().eq("exampaper_name", exampaper.getExampaperName()).eq("exampaper_date", exampaper.getExampaperDate()).eq("exampaper_types", exampaper.getExampaperTypes());logger.info("sql語句:"+queryWrapper.getSqlSegment());ExampaperEntity exampaperEntity = exampaperService.selectOne(queryWrapper);if(exampaperEntity==null){exampaperService.updateById(exampaper);//根據id更新return R.ok();}else {return R.error(511,"表中有相同數據");}
}/*** 刪除*/
@RequestMapping("/delete")
public R delete(@RequestBody Integer[] ids){logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString());exampaperService.deleteBatchIds(Arrays.asList(ids));return R.ok();
}
1.2 問卷調查管理
圖2 即為編碼實現的問卷調查管理界面,管理員在該界面中對用戶提交的問卷調查信息進行查看,管理員可以直接查看每條問卷調查的調查詳情信息,同時可以刪除問卷調查信息。

圖2 問卷調查管理界面
核心代碼:
/*** 批量上傳*/
@RequestMapping("/batchInsert")
public R save( String fileName){logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName);try {List<ExampaperEntity> exampaperList = new ArrayList<>();//上傳的東西Map<String, List<String>> seachFields= new HashMap<>();//要查詢的字段Date date = new Date();int lastIndexOf = fileName.lastIndexOf(".");if(lastIndexOf == -1){return R.error(511,"該文件沒有后綴");}else{String suffix = fileName.substring(lastIndexOf);if(!".xls".equals(suffix)){return R.error(511,"只支持后綴為xls的excel文件");}else{URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName);//獲取文件路徑File file = new File(resource.getFile());if(!file.exists()){return R.error(511,"找不到上傳文件,請聯系管理員");}else{List<List<String>> dataList = PoiUtil.poiImport(file.getPath());//讀取xls文件dataList.remove(0);//刪除第一行,因為第一行是提示for(List<String> data:dataList){//循環ExampaperEntity exampaperEntity = new ExampaperEntity();exampaperList.add(exampaperEntity);}//查詢是否重復exampaperService.insertBatch(exampaperList);return R.ok();}}}}catch (Exception e){return R.error(511,"批量插入數據異常,請聯系管理員");}
}/*** 前端列表*/
@IgnoreAuth
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params, HttpServletRequest request){logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params));// 沒有指定排序字段就默認id倒序if(StringUtil.isEmpty(String.valueOf(params.get("orderBy")))){params.put("orderBy","id");}PageUtils page = exampaperService.queryPage(params);//字典表數據轉換List<ExampaperView> list =(List<ExampaperView>)page.getList();for(ExampaperView c:list)dictionaryService.dictionaryConvert(c, request); //修改對應字典表字段return R.ok().put("data", page);
}/*** 前端詳情*/
@RequestMapping("/detail/{id}")
public R detail(@PathVariable("id") Long id, HttpServletRequest request){logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id);ExampaperEntity exampaper = exampaperService.selectById(id);if(exampaper !=null){//entity轉viewExampaperView view = new ExampaperView();BeanUtils.copyProperties( exampaper , view );//把實體數據重構到view中//修改對應字典表字段dictionaryService.dictionaryConvert(view, request);return R.ok().put("data", view);}else {return R.error(511,"查不到數據");}
}
1.3 題目管理
圖3 即為編碼實現的題目管理界面,管理員在該界面中可以導出題目,可以新增題目,可以對指定的題目信息進行修改,刪除,同時可以查看用戶對各個題目選項的統計信息,該統計信息是以餅圖進行展示。

圖3 題目管理界面
核心代碼:
/*** 后端詳情*/
@RequestMapping("/info/{id}")
public R info(@PathVariable("id") Long id, HttpServletRequest request){logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id);ExamquestionEntity examquestion = examquestionService.selectById(id);if(examquestion !=null){//entity轉viewExamquestionView view = new ExamquestionView();BeanUtils.copyProperties( examquestion , view );//把實體數據重構到view中//級聯表ExampaperEntity exampaper = exampaperService.selectById(examquestion.getExampaperId());if(exampaper != null){BeanUtils.copyProperties( exampaper , view ,new String[]{ "id", "createDate"});//把級聯的數據添加到view中,并排除id和創建時間字段view.setExampaperId(exampaper.getId());}//修改對應字典表字段dictionaryService.dictionaryConvert(view, request);return R.ok().put("data", view);}else {return R.error(511,"查不到數據");}
}/*** 后端保存*/
@RequestMapping("/save")
public R save(@RequestBody ExamquestionEntity examquestion, HttpServletRequest request){logger.debug("save方法:,,Controller:{},,examquestion:{}",this.getClass().getName(),examquestion.toString());String role = String.valueOf(request.getSession().getAttribute("role"));if(StringUtil.isEmpty(role))return R.error(511,"權限為空");Wrapper<ExamquestionEntity> queryWrapper = new EntityWrapper<ExamquestionEntity>().eq("exampaper_id", examquestion.getExampaperId()).eq("examquestion_name", examquestion.getExamquestionName()).eq("examquestion_options", examquestion.getExamquestionOptions()).eq("examquestion_types", examquestion.getExamquestionTypes()).eq("examquestion_sequence", examquestion.getExamquestionSequence());logger.info("sql語句:"+queryWrapper.getSqlSegment());ExamquestionEntity examquestionEntity = examquestionService.selectOne(queryWrapper);if(examquestionEntity==null){examquestion.setCreateTime(new Date());examquestionService.insert(examquestion);return R.ok();}else {return R.error(511,"表中有相同數據");}
}
1.4 用戶管理
圖4 即為編碼實現的用戶管理界面,管理員在該界面中為用戶重置密碼,修改用戶基本信息,新增用戶,刪除需要刪除的用戶信息。

圖4 用戶管理界面
核心代碼:
/*** 后端修改*/
@RequestMapping("/update")
public R update(@RequestBody YonghuEntity yonghu, HttpServletRequest request){logger.debug("update方法:,,Controller:{},,yonghu:{}",this.getClass().getName(),yonghu.toString());String role = String.valueOf(request.getSession().getAttribute("role"));if(StringUtil.isEmpty(role))return R.error(511,"權限為空");//根據字段查詢是否有相同數據Wrapper<YonghuEntity> queryWrapper = new EntityWrapper<YonghuEntity>().notIn("id",yonghu.getId()).andNew().eq("username", yonghu.getUsername()).or().eq("yonghu_id_number", yonghu.getYonghuIdNumber()).or().eq("yonghu_phone", yonghu.getYonghuPhone());logger.info("sql語句:"+queryWrapper.getSqlSegment());YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper);if("".equals(yonghu.getYonghuPhoto()) || "null".equals(yonghu.getYonghuPhoto())){yonghu.setYonghuPhoto(null);}if(yonghuEntity==null){yonghuService.updateById(yonghu);//根據id更新return R.ok();}else {return R.error(511,"賬戶或者手機號或者身份證號已經被使用");}
}
1.5 新聞資訊管理
圖5 即為編碼實現的新聞資訊管理界面,管理員在該界面中負責發布新聞資訊,更改新聞資訊的部分信息,刪除需要刪除的新聞資訊信息。

圖5 新聞資訊管理界面
核心代碼:
/*** 后端列表*/
@RequestMapping("/page")
public R page(@RequestParam Map<String, Object> params, HttpServletRequest request){logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params));String role = String.valueOf(request.getSession().getAttribute("role"));if(StringUtil.isEmpty(role))return R.error(511,"權限為空");else if("用戶".equals(role))params.put("yonghuId",request.getSession().getAttribute("userId"));if(params.get("orderBy")==null || params.get("orderBy")==""){params.put("orderBy","id");}PageUtils page = newsService.queryPage(params);//字典表數據轉換List<NewsView> list =(List<NewsView>)page.getList();for(NewsView c:list){//修改對應字典表字段dictionaryService.dictionaryConvert(c, request);}return R.ok().put("data", page);
}
2 用戶功能實現
2.1 問卷列表
圖6 即為編碼實現的問卷列表界面,用戶在該界面中選擇問卷并參與問卷調查。

圖6 問卷列表界面
核心代碼:
/*** 前端列表*/
@IgnoreAuth
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params, HttpServletRequest request){logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params));// 沒有指定排序字段就默認id倒序if(StringUtil.isEmpty(String.valueOf(params.get("orderBy")))){params.put("orderBy","id");}PageUtils page = examrecordService.queryPage(params);//字典表數據轉換List<ExamrecordView> list =(List<ExamrecordView>)page.getList();for(ExamrecordView c:list)dictionaryService.dictionaryConvert(c, request); //修改對應字典表字段return R.ok().put("data", page);
}/*** 前端詳情*/
@RequestMapping("/detail/{id}")
public R detail(@PathVariable("id") Long id, HttpServletRequest request){logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id);ExamrecordEntity examrecord = examrecordService.selectById(id);if(examrecord !=null){//entity轉viewExamrecordView view = new ExamrecordView();BeanUtils.copyProperties( examrecord , view );//把實體數據重構到view中//級聯表ExampaperEntity exampaper = exampaperService.selectById(examrecord.getExampaperId());if(exampaper != null){BeanUtils.copyProperties( exampaper , view ,new String[]{ "id", "createDate"});//把級聯的數據添加到view中,并排除id和創建時間字段view.setExampaperId(exampaper.getId());}//級聯表YonghuEntity yonghu = yonghuService.selectById(examrecord.getYonghuId());if(yonghu != null){BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createDate"});//把級聯的數據添加
源碼+論文下載>>