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

举报
TiAmoZhang 发表于 2023/02/17 08:48:50 2023/02/17
【摘要】 在本篇中,我们将制作一个投票系统,让学生给自己喜爱的老师投票。

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进行定时自动刷新,后果可想而知!

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

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。