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

TiAmozhang
全栈领域优质创作者
博客专家认证
2023-02-20 10:37:34
加精

 

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

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

 

...全文
321 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

18,927

社区成员

发帖
与我相关
我的任务
社区描述
分享开发工作中的心得,记录编程过程中的所想所悟!
harmonyos华为云微信小程序 个人社区 江苏省·常州市
社区管理员
  • TiAmo zhang
  • 小威要向诸佬学习呀
  • bit..
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧