写点什么

Java 高手速成 | Java web 实训之投票系统

作者:TiAmo
  • 2023-02-18
    江苏
  • 本文字数:3183 字

    阅读完需:约 10 分钟

Java高手速成 | Java web 实训之投票系统

01、投票系统的案例需求

在本篇中,我们将制作一个投票系统,让学生给自己喜爱的老师投票。该系统由 1 个界面组成,系统运行,出现投票界面,如图所示:


▍显示效果

在这个界面中,标题为:“欢迎给教师投票”;在界面上有一个表格,显示了各位教师的编号、姓名、得票数;其中,得票数显示为一个红色的进度条,并显示得票的数值;表格的第 4 列是投票链接,点击链接,该教师的票数加 1,并显示在界面上。

比如,点击编号为 2 的教师对应的投票链接,界面效果为:


▍显示效果

由此可见,其票数增加了 1 票。


02、投票系统分析


在这个项目中,我们只需要用到 1 个界面:投票界面。需要编写的 JSP 文件有几个呢?

一种想法认为,只需要编写 1 个 JSP,在里面显示投票界面,同样是这个 JSP,负责接受用户的投票,将对应的教师的得票数加 1。这种方法比较直观,但是可维护性较差,2 个功能的所有代码放在一个 JSP 内,如果作细微的修改,则比较麻烦,也不利于开发上的分工。

因此我们建议采用如下方法:使用 2 个 JSP,1 个 JSP 负责显示投票界面,另 1 个 JSP 负责接受用户的投票,将对应的教师的得票数加 1,工作完毕再跳转回第 1 个 JSP。结构如图所示:


▍结构

各页面的命名和作用如下表所示:


 ▍各模块定义

03、开发过程

1)准备数据

此处使用Access数据库。很明显,本项目中只需要 1 个数据表,包含教师编号、教师姓名和得票数。


创建表的脚本如下:


插入一些数据,每个教师初始状态的得票数为 0。

2)如何出现进度条

本项目中,票数以进度条形式出现,如图所示:


如何出现进度条呢?

实际上,进度条就是一个普通的红色图片,只不过显示时固定其高度,让宽度和得票数成正比就可以了。

用图像处理工具(如画图板)准备一个进度条文件:bar.jpg,含有一个很小的红色正方形即可。


3)编写 display.jsp


打开 MyEclipse,新建一个 Web 项目:Vote,将 bar.jpg 拷贝到 WebRoot 下的 img 目录(该目录可以事先新建),首先我们编写 display.jsp,代码如下。

<%@ page language="java" import="java.sql.*" pageEncoding="gb2312"%><html>  <body>  <table align="center">    <caption>欢迎给教师投票</caption>   <tr bgcolor="yellow">     <td>编号</td>     <td>姓名</td>     <td>得票数</td>     <td>投票</td>   </tr>   <%       Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");    Connection conn = DriverManager.getConnection("jdbc:odbc:DSSchool");    Statement stat = conn.createStatement();    String sql = "SELECT TEACHERNO,TEACHERNAME,VOTE FROM T_VOTE";    ResultSet rs = stat.executeQuery(sql);    while(rs.next()){      String teacherno     <tr bgcolor="pink"= rs.getString("TEACHERNO");      String teachername = rs.getString("TEACHERNAME");      int vote = rs.get>       <td><%=teacherno %></td>       <td><%=teachername %></td>       <td><img src="img/bar.jpg" width="<%=vote%>" height="10"> <%=vote%></td>       <td><a href="vote.jsp?teacherno=<%=teacherno%>">投票</a></td>       </tr>  <%        }    stat.close();    conn.close();  %>   </table>  </body></html>
复制代码

在上述代码中,

<img  src="img/bar.jpg" width="<%=vote%>"  height="10"
复制代码

显示进度条,高度固定为 10,宽度和得票数相等。

<a  href="vote.jsp?teacherno=<%=teacherno%>">投票</a>
复制代码

使用 url 传值将 teacherno 的值以参数形式传给 vote.jsp。

4)编写 vote.jsp

接下来编写 vote.jsp,代码如下:

<%@ page language="java" import="java.sql.*" pageEncoding="gb2312"%><html>  <body>    <%       String teacherno = request.getParameter("teacherno");       Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");    Connection conn = DriverManager.getConnection("jdbc:odbc:DSSchool");    String sql = "UPDATE T_VOTE SET VOTE=VOTE+1 WHERE TEACHERNO=?";    PreparedStatement ps = conn.prepareStatement(sql);    ps.setString(1,teacherno);    ps.executeUpdate();    ps.close();    conn.close();  %>  <jsp:forward page="display.jsp"></jsp:forward>  </body></html>
复制代码

在上述代码中,

String teacherno =  request.getParameter("teacherno");
复制代码

获得前一个页面传过来的 teacherno 参数,赋值给 teacherno 变量。

<jsp:forward  page="display.jsp"></jsp:forward>
复制代码

表示工作完成之后,跳回 display.jsp,此处用到了 JSP 的 forward 动作。


编写完毕,这个项目的结构如图所示:


▍项目结构

访问 display.jsp,就可以得到相应效果。

04、进一步改进

1)存在的问题

前面的例子中,有一个较大的问题,就是:display.jsp 和 vote.jsp 中,存在大量访问数据库的重复代码。比如,display.jsp 和 vote.jsp 中都存在:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");Connection conn =  DriverManager.getConnection("jdbc:odbc:DSSchool");
复制代码

如何解决这个问题?

2)如何封装数据库连接

对于代码重复,常见的解决方法是将重复的代码写入函数。如何定义函数呢?

我们知道,函数可以在 JSP 声明中定义,因此,可以将数据库连接代码专门放在一个声明中,代码如下:

<%@ page  language="java" import="java.sql.*"  pageEncoding="gb2312"%><%!        public  Connection getConnection() throws Exception{               Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");             Connection conn =  DriverManager.getConnection("jdbc:odbc:DSSchool");               return conn;        }%>
复制代码

特别提醒:如果不是直接访问页面,而仅仅是定义一些功能,文件扩展名理论上可以任意。另外,该函数一定要定义在 JSP 声明中。


3)如何重用代码


定义了函数 getConnection,我们就可以在 display.jsp 和 vote.jsp 中使用该函数了。当然,在此之前,要导入 db.inc。

经过处理的 display.jsp 代码如下:

<%@ page language="java" import="java.sql.*" pageEncoding="gb2312"%><%@ include file="db.inc" %><html>  <body>  <table align="center">    <caption>欢迎给教师投票</caption>   <tr bgcolor="yellow">     <td>编号</td>     <td>姓名</td>     <td>得票数</td>     <td>投票</td>   </tr>   <%       Connection conn = getConnection();       Statement stat = conn.createStatement();    String sql = "SELECT TEACHERNO,TEACHERNAME,VOTE FROM T_VOTE";    ResultSet rs = stat.executeQuery(sql);    while(rs.next()){      String teacherno = rs.getString("TEACHERNO");      String teachername = rs.getString("TEACHERNAME");      int vote = rs.getInt("VOTE");  %>    <tr bgcolor="pink">       <td><%=teacherno %></td>       <td><%=teachername %></td>       <td><img src="img/bar.jpg" width="<%=vote%>" height="10"> <%=vote%></td>       <td><a href="vote.jsp?teacherno=<%=teacherno%>">投票</a></td>       </tr>  <%        }    stat.close();    conn.close();  %>   </table>  </body></html>
复制代码

在上述代码中,

<%@ include  file="db.inc" %>
复制代码

表示导入 db.inc。

Connection conn =  getConnection();
复制代码

表示调用导入的 getConnection 方法。

访问 display.jsp,也能得到同样的效果。

05、思考:如何防止刷票

刷票是一种恶意投票行为。在本系统中,也存在刷票的隐患。

访问 display.jsp,显示效果如图所示:


▍显示效果

给编号为 1 的教师投票,界面变为:


▍显示效果

注意,此时浏览器地址栏上的地址变为:


▍地址效果

在保持该 URL 的情况下,点击浏览器上的刷新按钮:


▍刷新按钮

就可以达到刷票的效果。比如,刷新 10 次,界面效果为:


▍显示效果

如果使用 JavaScript 进行定时自动刷新,后果可想而知!

如何解决这个问题呢?请大家评论区补充。

发布于: 刚刚阅读数: 6
用户头像

TiAmo

关注

有能力爱自己,有余力爱别人! 2022-06-16 加入

CSDN全栈领域优质创作者;阿里云创作者社区专家博主、技术博主、星级博主、阿里云ACE;华为云享专家;

评论

发布
暂无评论
Java高手速成 | Java web 实训之投票系统_Java_TiAmo_InfoQ写作社区