mysql+jdbc+servlet+jsp实现基于MVC的学生疫情信息打卡系统

    技术2024-05-26  72

    目录

    概览环境:框架:功能介绍范式分析具体功能逻辑 代码分析1.bean:2.dao与dao.impl:3.service与service.impl:4.servlet:5.utils:6.jsp:7.web.xml: 结果整体反思

    概览

    小组团队完成的数据库,本人负责教师功能的一部分以及整个框架的初步构建。整体来讲分工还是有点混乱的,因为基本上互相都有修改各自的部分。 由于代码量较多,所以仅放出部分自己写的内容。

    环境:

    Mysql8.0+Tomcat9.0+JDK1.8+Eclipse IDE for Enterprise Java Developers

    框架:

    对应MVC架构: servlet(controller)+ jsp(view)+ bean,dao,service(model)

    功能介绍

    范式分析

    对于学生来讲一共有下面几种属性: sId 学号 ,name 姓名 ,date 日期,major 专业 ,tem 体温,classNo 班级,if_Contected 是否接触患者,telNum 联系方式,if_EverSick 是否有过往病史,emName 紧急联系人姓名 ,if_Travelled 是否经过重症区域,relationship 与学生的关系 ,if_Sick 是否出现异常症状,emTelNum 联系人联系方式 ,familyHealth 家人身体状况,password 密码 ,healthCondition 综合健康状况

    对于老师来讲一共有下面几种属性: tId 工号,name 姓名,college 学院名,telNum 联系方式,classNo 班级,password 密码

    此时满足第一范式每一个单独的数据项不可分割特性。但对于学生来讲,此时的码为(sId,date),这样子的话有关于学生信息的内容部分依赖于sId,有关于打卡信息的内容部分依赖于sId,date,所以需要第二范式分割,消除部分依赖。

    sId,name,major,classNo,telNum,emName,relationship,emTelNum,password。 sId,Date,Tem,if_Contected,if_EverSick,if_Travelled,if_Sick,familyHealth,healthCondition。

    此时没有了部分依赖,也没有传递依赖,符合第三范式的结果。然后接下来再对功能进行逻辑上的分割,分离学生与老师的账号和密码另外设置一个登录表,对内容进行加密以提升安全性;分离classNo与college到另一个管辖表内,保证老师可以管理零或多个班级。

    具体功能逻辑

    代码分析

    1.bean:

    存储实体类,内容与自己设计的表内容一致。

    2.dao与dao.impl:

    dao.impl实现了具体操作,dao内对其进行了初步的封装。这样以后直接修改dao.impl就可以了。

    package com.healthy.dao; import java.util.List; import com.healthy.bean.Daily; import com.healthy.bean.Student; import com.healthy.bean.Teacher; public interface TeacherDao { public List<Student> selectStudent(String classNo); public List<Daily> selectDaily(String classNo); public boolean updateStudent(String sId, String name, String major, String classNo, String telNum, String emName, String relationship, String emTelNum,String tId); public boolean deleteStudent(String sId,String tId); public String getclassNo(String tId); public List<Teacher> list(String tId); } package com.healthy.dao.impl; import com.healthy.dao.TeacherDao; import com.healthy.utils.DBconnect; import com.healthy.utils.log; import com.healthy.bean.*; import java.sql.*; import java.util.*; public class TeacherDaoImpl implements TeacherDao{ static Connection conn=null; static Statement stmt=null; static PreparedStatement pStemt = null; //显示名下的学生信息 public List<Student> selectStudent(String classNo) { String sql = "select * from student where classNo=\""+classNo+"\""; ResultSet res=null; List<Student> list = new ArrayList<>(); try { conn=DBconnect.set_connect(); stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); res = stmt.executeQuery(sql); while (res.next()){ String sId=res.getString("sId"); String name=res.getString("name"); String major=res.getString("major"); String telNum=res.getString("telNum"); String emName=res.getString("emName"); String relationship=res.getString("relationship"); String emTelNum=res.getString("emTelNum"); Student new_student=new Student(sId,name,major,classNo,telNum,emName,relationship,emTelNum); list.add(new_student); } } catch (SQLException e) { e.printStackTrace(); }finally { DBconnect.close_connect(); log.logWrite("./logFile.log",log.getCurrentTime() + sql); return list; } } //更新学生信息并返回是否成功 public boolean updateStudent(String sId, String name, String major, String classNo, String telNum, String emName, String relationship, String emTelNum,String tId) { boolean flag=false; String check_sql="select classNo from student where sId=\""+sId+"\""; String temp=getclassNo(tId); String temp2=null; ResultSet ifright=null; String sql = "update student set name=\""+name+"\",major=\""+major+"\",classNo=\"" +classNo+"\",telNum=\""+telNum+"\",emName=\""+emName+"\",relationship=\"" +relationship+"\",emTelNum=\""+emTelNum+"\" where sId=\""+sId+"\""; int res=0; try { conn=DBconnect.set_connect(); stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); ifright=stmt.executeQuery(check_sql); while(ifright.next()) temp2=ifright.getString("classNo"); if(temp.equals(temp2)) { res = stmt.executeUpdate(sql); if(res>0){ flag=true; log.logWrite("./logFile.log",log.getCurrentTime() + sql); } } }catch (SQLException e) { e.printStackTrace(); }finally { DBconnect.close_connect(); return flag; } } }

    这一部分采用的sql语句其实是可以被sql注入的,可以使用?的占位符这种预编译的方式替代单纯的+的拼接,防止部分的注入。主要优点在于杜绝编译器执行用户输入的非法数据,并减少硬编译的次数。 同时在Login的Dao部分,对密码采用了加密,保证直接查看sql数据库时无法直接查看到明文内容。

    public String myHash(String password) { return String.valueOf(password.hashCode()); }

    3.service与service.impl:

    Service层封装一个或多个Dao的方法,方便其他代码进行调用。调用Dao层函数代码保存在Impl文件夹下的文件中,Service文件保存最后的接口。本实验比较初级,所以一个Service封装一个Dao。

    package com.healthy.service; import java.util.List; import com.healthy.bean.Daily; import com.healthy.bean.Student; import com.healthy.bean.Teacher; public interface TeacherService { public List<Student> selectStudent(String classNo); public List<Daily> selectDaily(String classNo); public boolean updateStudent(String sId, String name, String major, String classNo, String telNum, String emName, String relationship, String emTelNum,String tId); public boolean deleteStudent(String sId,String tId); public String getclassNo(String tId); public List<Teacher> list(String tId); } package com.healthy.service.impl; import java.util.List; import com.healthy.bean.*; import com.healthy.dao.TeacherDao; import com.healthy.dao.impl.TeacherDaoImpl; import com.healthy.service.TeacherService; public class TeacherServiceImpl implements TeacherService { private TeacherDao teacherDao = new TeacherDaoImpl(); public List<Student> selectStudent(String classNo) { return teacherDao.selectStudent(classNo); } public List<Daily> selectDaily(String classNo) { return teacherDao.selectDaily(classNo); } public boolean updateStudent(String sId, String name, String major, String classNo, String telNum, String emName, String relationship, String emTelNum,String tId) { return teacherDao.updateStudent(sId,name,major,classNo,telNum, emName,relationship, emTelNum,tId); } public boolean deleteStudent(String sId,String tId){ return teacherDao.deleteStudent(sId,tId); } public String getclassNo(String tId) { return teacherDao.getclassNo(tId); } public List<Teacher> list(String tId) { return teacherDao.list(tId); } }

    4.servlet:

    Servlet中可以调用Service中的接口对数据进行处理并向前端返回相关数据。其实Servlet与Jsp是可以结合在一起的,但是分离逻辑和页面是一件很重要的事情,否则显得代码异常混乱。

    package com.healthy.servlet; import java.io.*; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.*; import com.healthy.bean.*; import com.healthy.service.TeacherService; import com.healthy.service.impl.TeacherServiceImpl; public class TeacherSelectStudentServlet extends HttpServlet{ private TeacherService teacherService = new TeacherServiceImpl(); //本实验post提交,所以重写post public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { //转码以支持中文 request.setCharacterEncoding("UTF-8"); //根据tId获得自己管辖的classNo String tId=request.getParameter("tId"); String classNo=teacherService.getclassNo(tId); List<Student> select_student= teacherService.selectStudent(classNo); request.setAttribute("tId", tId); request.setAttribute("select_student", select_student); request.getRequestDispatcher("TeacherOperate.jsp").forward(request, response); } public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{ this.doPost(request, response); } }

    5.utils:

    这边放了数据库连接与日志记录的内容。也可以放置其他的内容。

    package com.healthy.utils; import java.sql.*; public class DBconnect { static String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static String DB_URL = "jdbc:mysql://localhost:3306/YourDatabaseName?serverTimezone=UTC&&useUnicode=true&characterEncoding=utf8"; static String USER = "YourUserName"; static String PASS = "YourPass"; static Connection conn; static Statement stmt; public static Connection set_connect(){ try { Class.forName(JDBC_DRIVER); }catch (ClassNotFoundException e) { e.printStackTrace(); } try { conn=DriverManager.getConnection(DB_URL,USER,PASS); }catch(SQLException e){ e.printStackTrace(); }catch(Exception e){ e.printStackTrace(); } return conn; } public static void close_connect(){ if(stmt!=null) { try { stmt.close(); }catch (SQLException e){ e.printStackTrace(); } } if(conn!=null) { try{ conn.close(); }catch (SQLException e){ e.printStackTrace(); } } } }

    6.jsp:

    显示页面内容,其实与html+css+js的页面构造一致。

    <%@ page import="com.healthy.service.*" %> <%@ page import="java.io.*,java.util.*,java.sql.*"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <title>TeacherOperate.jsp页面</title> <link rel="stylesheet" href="./css/operate.css" type="text/css"> </head> <body> <form class="table" action="TeacherSelectStudentServlet" method="post"> <div style="text-align: center;"> <h4>查询管辖班级的学生信息</h4> </div> <div style="text-align: center;"> <input type="text" name="tId" value="${tId}" readonly="readonly" style="display:none"/> </div> <div class="input" style="text-align: center;"> <input class="btn btn-primary" type="submit" value="查询"/> </div> </form> <div align="center"> <table border="1" > <tr> <td>sId</td> <td>name</td> <td>major</td> <td>classNo</td> <td>telNum</td> <td>emName</td> <td>relationship</td> <td>emTelNum</td> </tr> <c:forEach var="students" items="${select_student}"> <tr> <td>${students.sId}</td> <td>${students.name}</td> <td>${students.major}</td> <td>${students.classNo}</td> <td>${students.telNum}</td> <td>${students.emName}</td> <td>${students.relationship}</td> <td>${students.emTelNum}</td> </tr> </c:forEach> </table> </div> </body> </html>

    7.web.xml:

    存储敏感内容,首先会读取项目web.xml配置文件里的配置,当这一步骤没有出错并且完成之后,项目才能正常地被启动起来。

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>项目名</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>TeacherSelectStudentServlet</servlet-name> <!-- 上面一句指定Servlet对象的名称 --> <servlet-class>com.healthy.servlet.TeacherSelectStudentServlet</servlet-class> <!-- 上面一句指定Servlet对象的完整位置,包含包名和类名 --> </servlet> <servlet-mapping> <servlet-name>TeacherSelectStudentServlet</servlet-name> <!--<servlet-name>与上面<Servlet>标签的<servlet-name>元素相对应,不可以随便起名 --> <url-pattern>/TeacherSelectStudentServlet</url-pattern> <!-- 上面一句话用于映射访问URL --> </servlet-mapping> </web-app>

    结果

    必须通过TeacherLogin登录进入TeacherOperate,否则无法进行查询。这里限定了查询的身份。TeacherLogin经过servlet的参数传递到TeacherOperate内,直接限定了查询的主体。

    整体反思

    1.第一次直接自学写的框架和内容,其实还是很简陋的一个系统。还可以在前端进行修改,并对代码结构进行多次的优化。 2.从安全性来讲也只做到了普通的明文显示为密文以及最普通的基于视图的访问控制,下一步可以进行基于权限的访问控制。 3.web的拦截可以使用一些正则匹配的过滤进行拦截,减少用户的非法输入从视图层向下传输的概率。

    Processed: 0.015, SQL: 10