最近一直想找点事情做,前几个星期马原老师说要做一份社会调查需要用到调查问卷,然后基本都是网上直接用现成的网站直接做的,我在想自己是不是也能做一个类似简单的管理系统呢。。然后一做就做了半个月,前几天总算是做好了,感觉要是自己勤快一点可能几天就能写好吧,下面是我在写这个调查系统的全部过程和遇到的问题解决方法。
首先是在脑海中构建整个系统的模型,我是喜欢根据这个模型先写好数据库的脚本,然后再写用到的POJO,和数据库相连接的sql类和mybatis的配置文件,最后将这些东西在jsp页面中拼接起来,SpringMVC算是一个粘合剂将这些东西很好的组合在一起。
我的构想:
首先和其他系统一样,应该先有一个账号以便起到多个人使用时使数据分开标识的作用,那么就应该有登录界面和注册账号页面。。这个很简单,随便搞搞就好了。
那么来到管理者的主界面,应该有创建问卷,查看/进行问卷调查,和查看问卷调查结果的功能,到这里,这个系统的大致模型已经有了。
再细想,数据库的数据表,首先应该有存放用户账号密码的表,叫user吧,其次应该有一张存放题目信息的表,叫inf吧,然后就是应该再有一张存放对应题目选项的表,叫det,然后每张表里面的数据就按照意思建就好了。
然后对应每张表,POJO类应该也有三个。。为了偷懒我直接都叫了表的名字。
下面是我mysql建表的脚本代码:
create database users; use users; create table user( username varchar(10) primary key, pwd varchar(20) ); create table inf( num int, username varchar(10), des varchar(200), foreign key(username) references user(username) ); create table det( num int, id int, opt varchar(30), username varchar(10), value int default '0', foreign key(username) references user(username) );
我的num是存题目的编号,id是存选项的编号。
然后就可以开始写POJO的java代码了,还有相应的sql语句,由于整个工程涉及的代码太多,就不一一放上来了,就挑一些重要的放,然后整个工程代码附上github的网址:https://github.com/iunique/IdeaProject。
项目基本骨架:
简介:
Dao放着和数据库相连接的代码,entity里放这POJO类,handles里面放的是页面控制器,用于处理页面映射以及起到servlet的作用,处理请求,跳转页面,config.xml放mybatis的基本配置文件,tab.xml放着sql语句,页面我用到的很多,登录界面login,注册界面register,还有相应的登录和注册判断跳转页面,然后index是用户主界面,对应着三个功能的界面,建调查问卷,进行问卷调查,查看调查文件结果。
先记录一下过程中遇到的几大问题:
1.中文乱码问题
2.WEB-INF目录下限制访问问题
3.算法问题,也就是如何用代码实现整个系统
解决方法:
1.中文乱码算是困扰我最久的问题,因为需要改的地方有很多,mysql数据库存储时的编码,解码设置,jsp页面编码解码的设置,以及mybatis配置文件中编码设置,在java代码处理数据时的编码解码设置。。只有全部搞好了才能实现中文在页面中的正常读取和呈现,少一步都不行,因为平时不用中文读取和呈现,基本没发现还有这么大的一个问题。。然后为此搞了一天最后写了博客:https://blog.csdn.net/qq_37497322/article/details/80034487
2.出于安全性考虑,jsp文件最好放在限制访问的WEB-INF目录下,
不用springMVC解决方法:https://blog.csdn.net/qq_37497322/article/details/80027464
一开始我是没用springMVC的,全部是用上面的方法+大量的web.xml配置映射+十几个servlet。。。代码量大大增加而且很复杂,最后我还是屈服了,花了一两天把代码改成了springMVC版的,映射文件和servlet全交给Controller处理。。才体会到了springMVC的强大,还有自带的表单自动填补POJO类的功能。。。简直不要太强
3.这个问题感觉是长期积累的代码感觉。。。想了一会实现方法,就写出来了,这东西感觉不好表达,或许是一年多的acm经验带来的加成吧,下面贴代码
首先是我的config.xml,也就是mybatis的配置文件,需要注意连接的时候加上字符集,url处最后加上
useUnicode=true&characterEncoding=UTF-8的字样可以解决写入数据库时的编码问题:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 和Spring整合后environment配置都会被干掉 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理,目前由mybatis来管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池,目前由mybatis来管理 --> <dataSource type="POOLED"><!--有关于mysql数据库的各种信息--> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/users?useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root" /> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--将操作配置文件User.xml系添加进mapper--> <mapper resource="tab.xml" /> </mappers> </configuration>
然后是tab.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="dom"> <resultMap type="entity.det" id="det"> <result column="num" property="num" javaType="int"/> <result column="id" property="id" javaType="int"/> <result column="opt" property="opt" javaType="string"/> <result column="value" property="value" javaType="int"/> <result column="username" property="username" javaType="string"/> </resultMap> <resultMap type="entity.user" id="user"> <result column="username" property="username" javaType="string"/> <result column="pwd" property="pwd" javaType="string"/> </resultMap> <resultMap type="entity.inf" id="inf"> <result column="num" property="num" javaType="int"/> <result column="username" property="username" javaType="string"/> <result column="des" property="des" javaType="string"/> </resultMap> <!--查询用户是否存在--> <select id="findUser" parameterType="java.lang.String" resultType="java.lang.Integer"> select COUNT(*) from user where username = '${value}' </select> <!--返回用户密码--> <select id="findPwd" parameterType="java.lang.String" resultType="java.lang.String"> select pwd from user where username = '${value}' </select> <!--插入一个用户--> <insert id="insertUser" parameterType="entity.user"> insert into user values(#{username},#{pwd}) </insert> <!-- 通过id查询题目描述 --> <select id="findDes" parameterType="java.lang.String" resultMap="inf"> select * from inf where username = '${value}' order by num </select> <!--通过num查询响应题目--> <select id="findOneDes" parameterType="entity.inf" resultMap="inf"> select * from inf where username = #{username} and num= #{num} </select> <!--通过num查询所有题目的选项--> <select id="findOptByNum" parameterType="entity.inf" resultMap="det"> select * from det where num = #{num} and username = #{username} order by id </select> <!--查询一个调查表中num最大值--> <select id="findMaxNum" parameterType="java.lang.String" resultType="java.lang.Integer"> select MAX(num) from inf where username = '${value}' </select> <!--查询一个题中选项id的最大值--> <select id="findMaxId" parameterType="entity.inf" resultType="java.lang.Integer"> select MAX(id) from det where username = #{username} and num = #{num} </select> <!--插入题目--> <insert id="insertInf" parameterType="entity.inf"> insert into inf values(#{num},#{username},#{des}) </insert> <!--插入题目选项--> <insert id="insertOpt" parameterType="entity.det"> insert into det values(#{num},#{id},#{opt},#{username},default) </insert> <!--更新选题描述--> <update id="updateDes" parameterType="entity.inf"> update inf set des = #{des} where username = #{username} and num = #{num} </update> <!--更新选项描述--> <update id="updateOpt" parameterType="entity.det"> update det set opt = #{opt} where username = #{username} and id = #{id} and num = #{num} </update> <!--选项选择情况--> <update id="updateRes" parameterType="entity.det"> update det set value = value+1 where username = #{username} and id = #{id} and num = #{num} </update> <!--删除题目信息--> <delete id="deleteDes" parameterType="entity.inf"> delete from inf where num = #{num} and username =#{username} </delete> <!--删除单个选项信息--> <delete id="deleteOneOpt" parameterType="entity.det"> delete from det where id= #{id} and username =#{username} and num = #{num} </delete> <!--删除所有选项--> <delete id="deleteAllOpt" parameterType="entity.inf"> delete from det where username =#{username} and num = #{num} </delete> </mapper>
因为有很多数据库处理的动作所以很长,至于POJO类代码就不贴了,直接按alt+insert可以直接调用getter and setter直接生成POJO类
用于获得SqlSession的工具类session.java:
package Dao; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class session { private final static SqlSessionFactory sqlSessionFactory; static { String resource = "config.xml"; InputStream inputStream=null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } public static SqlSession getSession() { return sqlSessionFactory.openSession(true);//这里设置成true表示支持事务,就是会更新数据库的意思,mybatis默认不支持事务 } }
与tab.xml相对于的java类sql.java:
package Dao; import entity.det; import entity.inf; import entity.user; import org.apache.ibatis.session.SqlSession; import java.util.List; public class sql { private static SqlSession session; static { session= Dao.session.getSession(); } public static int findUser(String name) { return session.selectOne("dom.findUser",name); } public static String findPwd(String name) { return session.selectOne("dom.findPwd",name); } public static void insertUser(user user) { session.insert("dom.insertUser",user); } public static List<inf> findDes(String username) { return session.selectList("dom.findDes",username); } public static List<det> findOptByNum(inf t) { return session.selectList("dom.findOptByNum",t); } public static inf findOneDes(inf t) { return session.selectOne("findOneDes",t); } public static void insertInf(inf t) { session.insert("dom.insertInf",t); } public static void insertOpt(det t) { session.insert("dom.insertOpt",t); } public static int findMaxNum(String username) { return session.selectOne("findMaxNum",username); } public static int findMaxId(inf t) { return session.selectOne("findMaxId",t); } public static void updateDes(inf t) { session.update("dom.updateDes",t); } public static void updateOpt(det t) { session.update("dom.updateOpt",t); } public static void updateRes(det t) { session.update("dom.updateRes",t); } public static void deleteDes(inf t) { session.delete("deleteDes",t); } public static void deleteOneOpt(det t) { session.delete("deleteOneOpt",t); } public static void deleteAllOpt(inf t) { session.delete("deleteAllOpt",t); } }
登录界面login.jsp代码,我这里用了cookies存储登录账号密码:
<%@ page import="java.net.URLDecoder" %><%-- Created by IntelliJ IDEA. User: hjy Date: 18-4-24 Time: 下午8:10 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% request.setCharacterEncoding("UTF-8"); Cookie cookies[]=null; cookies=request.getCookies(); String username=""; String pwd=""; if(cookies!=null) { for(Cookie c:cookies) { String s=c.getName(); if("username".equals(s)) { username= URLDecoder.decode((String)c.getValue(),"UTF-8"); System.out.println(username); } if("pwd".equals(s)) { pwd= URLDecoder.decode((String)c.getValue(),"UTF-8"); System.out.println(pwd); } } } %> <html> <head> <title>login</title> </head> <body> <form action="/servlets/login" method="post"> 账号:<input name="username" value="<%=username%>"/><br/> 密码:<input type="password" name="pwd" value="<%=pwd%>"/> <button type="submit">登录</button> </form> <a href="/registerPage">注册</a> </body> </html>
然后是创建调查问卷的create_tab.jsp,这段代码的实现完全出自于感觉。。然后注意一般用hidden属性来给要传的表加入一些用于数据处理又不想呈现出来的值,还有就是一个表格根据不同的按钮提交给不用的servlet的方法是onclick属性里面,this.form.action='xxx':
<%-- Created by IntelliJ IDEA. User: hjy Date: 18-4-20 Time: 下午3:26 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" import="Dao.*" language="java" pageEncoding="UTF-8"%> <%@ page import="java.util.List" %> <%@ page import="entity.det" %> <%@ page import="entity.inf" %> <% if(session.getAttribute("flag")!=null) { %> <script> alert("添加成功");</script> <% session.removeAttribute("flag"); } %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>调查表建立</title> </head> <body> <div> <div> <a href="/">回到主界面</a> <a href="/research">查看问卷</a> <p>已添加的题目:</p> <% String username=(String)session.getAttribute("username"); List<inf>l; l=sql.findDes(username); for(int i=0;i<l.size();i++) { String des=l.get(i).getDes(); List<det>lz=sql.findOptByNum(l.get(i)); %> <form method="post"> <textarea hidden name="num"><%=(l.get(i)).getNum()%></textarea> <textarea hidden name="username"><%=username%></textarea> <div><%=i+1%>.题目描述:</div> <textarea style="width: 200px;height: 80px" name="des"><%=des%> </textarea> <input type="submit" onclick="this.form.action='/servlets/adjdes'" value="修改描述"/> <input type="submit" onclick="this.form.action='/servelts/deletedes'" value="删除题目"/> </form> <% for(int j=0;j<lz.size();j++) { char c=(char)(65+j); String tt=lz.get(j).getOpt(); %> <form method="post"> <textarea hidden name="username"><%=username%></textarea> <textarea hidden name="num"><%=(l.get(i)).getNum()%></textarea> <textarea hidden name="id"><%=(lz.get(j)).getId()%></textarea> <%=c%>.<textarea style="width: 120px;height: 25px" name="opt"><%=tt%></textarea> <input type="submit" onclick="this.form.action='/servlets/adjopt'" value="修改选项"/> <input type="submit" onclick="this.form.action='/servelts/deleteOneOpt'" value="删除选项"/> </form> <% } } %> </div> <hr> <p>添加题目</p> <% int tmp; tmp=sql.findMaxNum(username); inf a1=new inf(); a1.setUsername(username); a1.setNum(tmp); %> 当前题号:<%=l.size()%><br/> <form method="post" action="/servlets/adjdes"> <textarea hidden name="num"><%=tmp%></textarea> <textarea hidden name="username"><%=username%></textarea> <div><%=l.size()%>.题目描述:</div> <textarea style="width: 200px;height:80px" name="des"><%=sql.findOneDes(a1).getDes()%></textarea> <button type="submit">修改描述</button> </form> 已添加选项:<br/> <% List<det>l1=sql.findOptByNum(a1); for(int i=0;i<l1.size();i++) { char c=(char)(65+i); %> <form method="post"> <textarea hidden name="username"><%=username%></textarea> <textarea hidden name="num"><%=tmp%></textarea> <textarea hidden name="id"><%=l1.get(i).getId()%></textarea> <p><%=c%>.<textarea style="width: 120px;height: 25px" name="opt"><%=(l1.get(i)).getOpt()%></textarea> <input type="submit" onclick="this.form.action='/servlets/adjopt'" value="修改选项"/> <input type="submit" onclick="this.form.action='/servelts/deleteOneOpt'" value="删除选项"/> </form> <% } %> <br/> 为当前题目添加选项: <form method="post" action="/servlets/addopt"> <textarea hidden name="username"><%=username%></textarea> <textarea hidden name="num"><%=tmp%></textarea> <textarea hidden name="id"><%=l1.size()==0?1:((int)(sql.findMaxId(a1))+1)%></textarea> <textarea style="width: 200px;height: 80px" name="opt"></textarea><br/> <button type="submit">添加选项卡</button> </form> <a href="/servlets/addnum" style="display: block">进入下一题添加</a> </div> </body> </html>
问卷调查页面tab_research.jsp:
<%@ page import="entity.inf" %> <%@ page import="java.util.List" %> <%@ page import="Dao.sql" %> <%@ page import="entity.det" %><%-- Created by IntelliJ IDEA. User: hjy Date: 18-4-20 Time: 下午3:27 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>问卷调查</title> </head> <body> <form action="/servlets/handle_submit" method="post"> <% String username=(String)session.getAttribute("username"); List<inf>l= sql.findDes(username); for(int i=0;i<l.size();i++) { %> <p><%=i+1%>.<%=l.get(i).getDes()%></p> <% List<det>lz=sql.findOptByNum(l.get(i)); for(int j=0;j<lz.size();j++) { char c=(char)(65+j); %> <%=c%>.<input type="radio" name="opt<%=lz.get(j).getNum()%>" value="<%=lz.get(j).getId()%>"><%=lz.get(j).getOpt()%><br/> <% } } %> <button type="submit" >提交</button> </form> </body> </html>
然后是整个系统最重要的LoginController.java:
package handles; import Dao.sql; import entity.det; import entity.det; import entity.inf; import entity.user; import org.springframework.http.HttpRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.List; @Controller public class LoginController { @RequestMapping("/") public String home(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); return "login"; } @RequestMapping("/registerPage") public String registerPage(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); return "register"; } @RequestMapping("/servlets/login") public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session, user t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); int tag=sql.findUser(t.getUsername()); String confirm; if(tag==0) { session.setAttribute("confirm","none"); } else { if((t.getPwd()).equals(sql.findPwd(t.getUsername()))) { session.setAttribute("confirm", "true"); session.setAttribute("username", t.getUsername()); String name= URLEncoder.encode(t.getUsername(),"UTF-8"); String pwd= URLEncoder.encode(t.getPwd(),"UTF-8"); Cookie c1=new Cookie("username",t.getUsername()); c1.setMaxAge(30*24*3600); c1.setPath("/"); resp.addCookie(c1); Cookie c2=new Cookie("pwd",t.getPwd()); c2.setMaxAge(30*24*3600); c2.setPath("/"); resp.addCookie(c2); } else { session.setAttribute("confirm", "false"); } } return "judge"; } @RequestMapping("/create_tab") public String create_tab(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); return "create_tab"; } @RequestMapping("/research") public String research(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); return "/tab_research"; } @RequestMapping("/result") public String result(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); return "result"; } @RequestMapping("/servlets/register") public String register(HttpServletRequest req, HttpServletResponse resp, HttpSession session, user t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); int tag=sql.findUser(t.getUsername()); System.out.println(tag); String comfirm; if(tag==0) { comfirm="true"; sql.insertUser(t); inf tmp=new inf(); tmp.setNum(1); tmp.setUsername(t.getUsername()); tmp.setDes("此处添加描述"); sql.insertInf(tmp); session.setAttribute("username",t.getUsername()); } else { comfirm="false"; } session.setAttribute("confirm",comfirm); return "reg_judge"; } @RequestMapping("/servlets/adjdes") public String adjdes(HttpServletRequest req, HttpServletResponse resp, HttpSession session, inf t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); t.setDes(new String(t.getDes().getBytes("ISO-8859-1"),"UTF-8")); sql.updateDes(t); return "create_tab"; } @RequestMapping("/servlets/adjopt") public String adjopt(HttpServletRequest req, HttpServletResponse resp, HttpSession session, det t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); t.setOpt(new String(t.getOpt().getBytes("ISO-8859-1"),"UTF-8")); sql.updateOpt(t); return "create_tab"; } @RequestMapping("/servlets/addopt") public String addopt(HttpServletRequest req, HttpServletResponse resp,det t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); t.setOpt(new String(t.getOpt().getBytes("ISO-8859-1"),"UTF-8")); sql.insertOpt(t); return "create_tab"; } @RequestMapping("/servlets/addnum") public String addnum(HttpServletRequest req, HttpServletResponse resp,HttpSession session) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); String username=(String)session.getAttribute("username"); inf t=new inf(); t.setUsername(username); t.setNum(sql.findMaxNum(username)+1); t.setDes("此处添加描述"); sql.insertInf(t); session.setAttribute("flag","true"); return "create_tab"; } @RequestMapping("/servlets/handle_submit") public String handle_submit(HttpServletRequest req, HttpServletResponse resp,HttpSession session) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); String username=(String)session.getAttribute("username"); List<inf>l=sql.findDes(username); for(int i=0;i<l.size();i++) { int num=l.get(i).getNum(); String tmp=req.getParameter("opt"+num); if(tmp==null) continue; det t=new det(); t.setUsername(username); t.setNum(num); int id=Integer.parseInt(tmp); t.setId(id); sql.updateRes(t); } return "success"; } @RequestMapping("/servelts/deletedes") public String deletedes(HttpServletRequest req, HttpServletResponse resp,inf t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); sql.deleteAllOpt(t); sql.deleteDes(t); return "create_tab"; } @RequestMapping("/servelts/deleteOneOpt") public String deleteopt(HttpServletRequest req, HttpServletResponse resp,det t) throws UnsupportedEncodingException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); sql.deleteOneOpt(t); return "create_tab"; } }
然后附上一些项目的运行效果图。。由于还没写css和特技,所以很丑见谅owo
登录界面:
主界面:
创建调查问卷界面:
调查问卷界面:
调查结果界面:
就到这里了。。代码写的很丑请见谅qwq,这几天写css美化下~