JavaWeb学生管理系统(详细源码+解析)

编程入门 行业动态 更新时间:2024-10-27 10:26:49

JavaWeb学生<a href=https://www.elefans.com/category/jswz/34/1769858.html style=管理系统(详细源码+解析)"/>

JavaWeb学生管理系统(详细源码+解析)


很多人大学的第一个小项目就是使用JavaWeb实现了一个学生管理系统或者是图书管理系统。在没有项目经验的情况下,前后端都需要自己去完成,还是要耗费不少时间精力的。本次我就分享一下我在大学期间完成的第一个小项目:学生管理系统。采用的技术有:Thymeleaf+Ajax+HTML+JQuery+Java+MySQL。下面会进行详细介绍,也可以关注微信公众号【橙晴丰Ciao】,私信我获取项目源码:JavaWeb学生管理系统。

效果演示


如何实现上面图片所实现的效果呢?接下来我将进行一个简单介绍。

项目搭建

  • 安装好Java环境【验证方式:同时点击win+r输入java -version】
  • 安装好MySQL环境
  • 先→创建一个JavaWeb项目,然后再实现具体的功能。

项目结构

JavaWeb项目搭建好后,就可以进行开发了,为了让第一次学习的小伙伴更加清楚地知道项目结构,我先把开发好后的结构图展示一下:

数据库搭建

在MySQL数据库中创建一个student_info数据库,用于存储我们要操作的学生信息表以及管理员登录表。

CREATE DATABASE student_info;DROP TABLE IF EXISTS `t_login`;
CREATE TABLE `t_login` (`user_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`user_password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_login
-- ----------------------------
INSERT INTO `t_login` VALUES ('admin', 'admin');-- ----------------------------
-- Table structure for `t_student`
-- ----------------------------
DROP TABLE IF EXISTS `t_student`;
CREATE TABLE `t_student` (`student_id` int(11) NOT NULL AUTO_INCREMENT,`student_name` varchar(100) DEFAULT NULL,`student_class` varchar(100) DEFAULT NULL,PRIMARY KEY (`student_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1704134100 DEFAULT CHARSET=utf8;

项目开发

项目对数据库的操作是必不可少的,所以我们先进行数据库方面的配置。在resource文件夹中进行数据库连接方面的配置:

常用配置

druid.properties

数据库可能存在时区问题,根据报错提示网上查找解决方案修改url即可

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/student_info?  
username=root
password=root
initialSize=5
maxActive=10
maxWait=1000

JDBCUtil

src/utils工具包中创建JDBCUtil工具类进行数据库连接等操作:

package com.lzk.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;public class JDBCUtil {private static DataSource dataSource;static {try {//读取配置文件,创建连接池InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties");Properties properties = new Properties();properties.load(inputStream);//使用DruidDataSourceFactory创建连接池dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取连接池* @return*/public static DataSource getDataSource(){return dataSource;}/*** 获取连接* @return*/public static Connection getConnection(){try {return dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}/*** 归还连接的方法* @param connection*/public static void releaseConnection(Connection connection){try {connection.close();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}
}

BaseDao

src/utils工具包中创建BaseDao工具类进行数据增删改查等操作:

package com.lzk.utils;import com.lzk.utils.JDBCUtil;
import org.apachemons.dbutils.QueryRunner;
import org.apachemons.dbutils.handlers.BeanHandler;
import org.apachemons.dbutils.handlers.BeanListHandler;
import org.apachemons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class BaseDao<T> {private QueryRunner queryRunner = new QueryRunner();/*** 批处理方法* @param sql* @param paramArr* @return*/public int[] batchUpdate(String sql,Object[][] paramArr){Connection conn = JDBCUtil.getConnection();try {return queryRunner.batch(conn,sql,paramArr);} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());} finally {JDBCUtil.releaseConnection(conn);}}/*** 执行增删改的sql语句* @param sql* @param params* @return*/public int update(String sql,Object... params){Connection conn = JDBCUtil.getConnection();//执行增删改的sql语句,返回受到影响的行数try {return queryRunner.update(conn,sql,params);} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());} finally {JDBCUtil.releaseConnection(conn);}}/*** 执行查询一行数据的sql语句,将结果集封装到JavaBean对象中* @param clazz* @param sql* @param params* @return*/public T getBean(Class<T> clazz,String sql,Object... params){Connection conn = JDBCUtil.getConnection();try {return queryRunner.query(conn,sql,new BeanHandler<>(clazz),params);} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());} finally {JDBCUtil.releaseConnection(conn);}}/*** 执行查询多行数据的sql语句,并且将结果集封装到List<JavaBean>* @param clazz* @param sql* @param params* @return*/public List<T> getBeanList(Class<T> clazz, String sql, Object... params){Connection conn = JDBCUtil.getConnection();try {return queryRunner.query(conn,sql,new BeanListHandler<>(clazz),params);} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());} finally {JDBCUtil.releaseConnection(conn);}}//查询数据条数public long findCount(String sql, Object... params) throws SQLException {Connection conn = JDBCUtil.getConnection();try {long count= queryRunner.query(conn,sql,new ScalarHandler<>(),params);return count;} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());} finally {JDBCUtil.releaseConnection(conn);}}}

数据模型层

User

用户实体类,跟数据库中的t_login表对应,存储管理员的信息。要有构造方法(无参、多参)以及getter和setter方法。

public class User {private String userId;private String userPassword;
}

Student

学生实体类,对应学生信息表。要有构造方法(无参、多参)以及getter和setter方法。

public class Student {private Integer studentId;private String studentName;private String studentClass;
}

PageInfo

分页信息实体类,不涉及数据库存储,只用于分页信息展示。要有构造方法(无参、多参)以及getter和setter方法。

public class PageInfo {//当前页 currentPageprivate Long currentPage;//页面大小private Long pageSize = 5L;//总数据totalCountprivate Long totalCount;//总页数totalPageprivate Long totalPage;//上一页private Long previousPage;//下一页private Long nextPage;
}

以上实体类都需要有getter和setter方法,否则在进行Thymeleaf模板渲染时就会出错。

web.xml配置文件

这个文件在web/WEB-INF,可以通过配置此文件进行控制层的映射。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"version="4.0"><!-- 把首页指向portalServlet,表示请求路径为/时,交由portalServlet进行处理 --><welcome-file-list><welcome-file>portalServlet</welcome-file><!-- 也可以通过这种方式配置首页,但login页面有使用thymeleaf语法,直接使用静态资源访问方式需要进行页面变量修改 --><!--        <welcome-file>/WEB-INF/view/login.html</welcome-file>--></welcome-file-list><!-- 在上下文参数中配置视图前缀和视图后缀,这个是使用了Thymeleaf后需要进行配置的,表示经过servlet渲染后返回的页面的路径以及后缀 --><context-param><param-name>view-prefix</param-name><param-value>/WEB-INF/view/</param-value></context-param><context-param><param-name>view-suffix</param-name><param-value>.html</param-value></context-param><!-- 这个servlet由项目中哪个包下的servlet进行处理 --><servlet><servlet-name>PortalServlet</servlet-name><servlet-class>com.lzk.servlet.model.PortalServlet</servlet-class></servlet><!-- 处理请求学生数据时路径的映射配置 --><servlet-mapping><servlet-name>StudentServlet</servlet-name><url-pattern>/student</url-pattern></servlet-mapping><servlet><servlet-name>StudentServlet</servlet-name><servlet-class>com.lzk.servlet.model.StudentServlet</servlet-class></servlet><servlet><servlet-name>CodeServlet</servlet-name><servlet-class>com.lzk.servlet.model.CodeServlet</servlet-class></servlet><servlet-mapping><servlet-name>CodeServlet</servlet-name><url-pattern>/code</url-pattern></servlet-mapping><servlet-mapping><servlet-name>PortalServlet</servlet-name><url-pattern>/portalServlet</url-pattern></servlet-mapping>
</web-app>

经过上面的配置后,当访问首页/时,就会交由portalServlet进行处理。

ProtalServlet

package com.lzk.servlet.model;import com.lzk.servlet.base.ViewBaseServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class PortalServlet extends ViewBaseServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//解析模板processTemplate("login", request, response);}
}

protalServlet进行请求处理时会将login页面进行渲染后返回,之所以可以实现模板渲染,是因为继承了ViewBaseServlet类。

ViewBaseServlet

这个类是基于Thymeleaf实现的可以进行模板渲染,继承自该类的所有子实现类也具有相同的功能。

package com.lzk.servlet.base;import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ViewBaseServlet extends HttpServlet {private TemplateEngine templateEngine;@Overridepublic void init() throws ServletException {// 1.获取ServletContext对象ServletContext servletContext = this.getServletContext();// 2.创建Thymeleaf解析器对象ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);// 3.给解析器对象设置参数// ①HTML是默认模式,明确设置是为了代码更容易理解templateResolver.setTemplateMode(TemplateMode.HTML);// ②设置前缀String viewPrefix = servletContext.getInitParameter("view-prefix");templateResolver.setPrefix(viewPrefix);// ③设置后缀String viewSuffix = servletContext.getInitParameter("view-suffix");templateResolver.setSuffix(viewSuffix);// ④设置缓存过期时间(毫秒)templateResolver.setCacheTTLMs(60000L);// ⑤设置是否缓存templateResolver.setCacheable(true);// ⑥设置服务器端编码方式templateResolver.setCharacterEncoding("utf-8");// 4.创建模板引擎对象templateEngine = new TemplateEngine();// 5.给模板引擎对象设置模板解析器templateEngine.setTemplateResolver(templateResolver);}protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {// 1.设置响应体内容类型和字符集resp.setContentType("text/html;charset=UTF-8");// 2.创建WebContext对象WebContext webContext = new WebContext(req, resp, getServletContext());// 3.处理模板数据templateEngine.process(templateName, webContext, resp.getWriter());}
}

login页面

在ProtalServlet中会进行模板渲染login页面,也就是登录时候的界面。因为我们在web.xml中进行了模板渲染视图上下文配置,所以该页面需要在/WEB-INF/view/中,并且为html形式。

这个页面就是一个登录表单,就是样式比较多

<!doctype html>
<html lang="zh-CN" xmlns:th="">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="/@bootcss/v3.bootcss@1.0.25/favicon.ico"><link rel="canonical" href=".4/examples/signin/"><title>学生管理系统登录界面</title><!-- Bootstrap core CSS --><link href="/@bootcss/v3.bootcss@1.0.25/dist/css/bootstrap.min.css" rel="stylesheet"><!-- IE10 viewport hack for Surface/desktop Windows 8 bug --><link href="/@bootcss/v3.bootcss@1.0.25/assets/css/ie10-viewport-bug-workaround.css" rel="stylesheet"><link href="/@bootcss/v3.bootcss@1.0.25/examples/signin/signin.css" rel="stylesheet"><script src="/@bootcss/v3.bootcss@1.0.25/assets/js/ie8-responsive-file-warning.js"></script><script src="/@bootcss/v3.bootcss@1.0.25/assets/js/ie-emulation-modes-warning.js"></script><script language="javascript" th:inline="javascript">function flushCode() {// 每次刷新的时候获取当前时间,防止浏览器缓存刷新失败var time = new Date();document.getElementById("scode").src="/StudentManage01/code?method=imageCode&time="+time;}</script><style type="text/css">body{background-size:auto,auto;background-repeat: no-repeat;}.code-class{position: relative;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;padding: 10px;font-size: 16px;color: inherit;font: inherit;margin: 0;width: 180px;height: 44px;line-height: 1.42857143;color: #555;background-color: #fff;background-image: none;border: 1px solid #ccc;border-radius: 4px;box-shadow: inset 0 1px 1px rgba(0,0,0,.075);-o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;}.identity{vertical-align: middle;height: 34px}</style>
</head><body><div class="container"><form class="form-signin" th:action="@{/student(method='Login')}" method="post"><h1>LOGIN</h1><input type="text" id="inputEmail" name="userId" class="form-control" placeholder="账号" required autofocus><br/><input type="password" id="inputPassword" name="userPassword" class="form-control" placeholder="密码" required><div ><input type="text" id="inputCode" name="code" class="code-class" placeholder="验证码" required><img alt="验证码" id="scode" class="identity" onclick="flushCode()" th:src="@{/code(method='imageCode')}" ></div><br/><input class="btn btn-lg btn-primary btn-block" type="submit" value="登录"><br/></form></div><script src="/@bootcss/v3.bootcss@1.0.25/assets/js/ie10-viewport-bug-workaround.js"></script>
</body>
</html>

登录页面使用了bootstrap,但是采用的是在线方式导入样式,所以需要联网才能显示效果。
可以看到页面有一个验证码的图片,这个验证码是通过后端进行绘制后返回给前端页面的。
访问的路径为:/StudentManage01/code?method=imageCode&time="+time;
在web.xml中有进行验证码路径的相关配置,发起的/code请求会交由CodeServlet进行处理。跟ProtalServlet一样,但是这里多了两个参数。我们先看下CodeServlet是怎么对验证码进行处理的。

CodeConstant

验证码图片长宽的参数定义。

public class CodeConstant {// 图片高度public static final int IMG_HEIGHT = 100;// 图片宽度public static final int IMG_WIDTH = 30;// 验证码长度public static final int CODE_LEN = 4;}

CodeServlet

package com.lzk.servlet.model;import com.lzk.constant.CodeConstant;
import com.lzk.servlet.base.ModelBaseServlet;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;public class CodeServlet extends ModelBaseServlet {public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {// 用于绘制图片,设置图片的长宽和图片类型(RGB)BufferedImage bi = new BufferedImage(CodeConstant.IMG_HEIGHT, CodeConstant.IMG_WIDTH, BufferedImage.TYPE_INT_RGB);// 获取绘图工具Graphics graphics = bi.getGraphics();graphics.setColor(new Color(100, 230, 200)); // 使用RGB设置背景颜色graphics.fillRect(0, 0, 100, 30); // 填充矩形区域// 验证码中所使用到的字符char[] codeChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456".toCharArray();String captcha = ""; // 存放生成的验证码Random random = new Random();for(int i = 0; i < CodeConstant.CODE_LEN; i++) { // 循环将每个验证码字符绘制到图片上int index = random.nextInt(codeChar.length);// 随机生成验证码颜色graphics.setColor(new Color(random.nextInt(150), random.nextInt(200), random.nextInt(255)));// 将一个字符绘制到图片上,并制定位置(设置x,y坐标)graphics.drawString(codeChar[index] + "", (i * 20) + 15, 20);captcha += codeChar[index];}// 将生成的验证码code放入sessoin中request.getSession().setAttribute("code", captcha);// 通过ImageIO将图片输出ImageIO.write(bi, "JPG", response.getOutputStream());}
}

这个类中对请求的处理跟ProtalServlet不一样,他有更具体的方法进行处理,而ProtalServlet是只针对Post请求和Get请求进行处理,而Post请求又调用Get请求的方法,因此ProtalServlet对请求只有一种应对方法,当然要想访问ProtalServlet也只能通过/进行。也就是一个请求路径对应一个Servlet,不管参数怎么变,对应的Servlet最多只能对不同请求进行两种不同的处理,一种为客户端发起Post请求时进行的处理,一种为Get。这种方式会非常繁琐,一是每个请求路径都要在web.xml进行配置,二是不好管理,例如对学生信息的增删改查,要写四个Servlet,而这四个Servlet关联性又很强。所以我们引入了ModelBaseServlet。

ModelBaseServlet

这个Servlet继承了ViewBaseServlet,所以也有模板渲染的功能并且通过暴力反射的方式去获取当前访问的方法名进行调用。所以当前端页面发起/StudentManage01/code?method=imageCode&time="+time;请求时,就会路径映射到codeServlet并且暴力反射调用CodeServlet中的imageCode。这种方式就可以实现针对CodeServlet中对验证码不同请求有多种不同的处理方式,只需要在里面写不同的方法即可。

package com.lzk.servlet.base;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;public class ModelBaseServlet extends ViewBaseServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//获取请求参数method的值String method = request.getParameter("method");//method参数的值就是要调用的方法的方法名,那就是已知方法名要去查找调用本对象的方法try {Method declaredMethod = this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);//暴力反射declaredMethod.setAccessible(true);//调用方法declaredMethod.invoke(this,request,response);} catch (Exception e) {e.printStackTrace();}}
}

StudentServlet

现在是对学生信息数据方面的处理,通过该Servlet实现学生数据的增删改查。在这个Servlet中就可以看到引入的ModelBaseServlet的作用。里面可以实现四个方法,请求时只需要通过method参数指定请求的方法即可。
在登录页面点击登录按钮后会向@{/student(method='login')}发起请求,即调用login方法进行验证,成功则到list页面,失败则到·error页面。该servlet需渲染的页面后面都会提供。
Servlet在进行业务处理时会调用Service层,Servcie层调用Dao层。

package com.lzk.servlet.model;import com.lzk.bean.PageInfo;
import com.lzk.bean.Student;
import com.lzk.service.StudentService;
import com.lzk.service.impl.StudentServiceImpl;
import com.lzk.servlet.base.ModelBaseServlet;
import org.apachemons.beanutils.BeanUtils;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import java.util.*;
import java.util.List;public class StudentServlet extends ModelBaseServlet {//创建Service对象private StudentService studentService = new StudentServiceImpl();//删除学生信息public void deleteStudent(HttpServletRequest request, HttpServletResponse response) throws Exception {Integer id = Integer.valueOf(request.getParameter("id"));studentService.deleteStudentById(id);}//跳转到学生信息修改页面public void toStudentInfoPage(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取要修改的学生的idInteger id = Integer.valueOf(request.getParameter("id"));Long currentPage =  Long.valueOf(request.getParameter("currentPage"));Student student = new Student();Long pageSize = new PageInfo().getPageSize();//查询出当前学生的信息try {//查询指定学生信息if(!id.equals(-1)){student = studentService.findStudentById(id);}if(currentPage.equals(-1)){currentPage = studentService.getPageInfo(1L, pageSize).getTotalPage();}//将student存储到请求域中request.setAttribute("currentPage",currentPage);request.setAttribute("student", student);//跳转到修改页面processTemplate("student-update", request, response);} catch (Exception e) {e.printStackTrace();}}//修改和增加学生信息public void updateOrAddStudent(HttpServletRequest request, HttpServletResponse response) throws Exception {//获取请求参数Map<String, String[]> parameterMap = request.getParameterMap();Long currentPage = Long.valueOf(parameterMap.get("currentPage")[0]);Long pageSize = new PageInfo().getPageSize();if(currentPage==-1){currentPage = studentService.getPageInfo(1L, pageSize).getTotalPage()-1;}//将请求参数封装到Student对象Student student = new Student();try {BeanUtils.populate(student, parameterMap);System.out.println(student.toString());//调用业务层的方法执行修改if(student.getStudentId()!=null){studentService.updateStudent(student);}else{studentService.insertStudent(student);}request.setAttribute("currentPage",currentPage);processTemplate("list", request, response);} catch (Exception e) {e.printStackTrace();}}//登录:查找登录用户是否存在public void login(HttpServletRequest request, HttpServletResponse response) throws Exception {long count = -1;try{//获取要登录的用户的idString id = String.valueOf(request.getParameter("userId"));//获取要登录的用户的密码String password = String.valueOf(request.getParameter("userPassword"));//调用业务层的方法查询用户是否存在count = studentService.findExistStudent(id, password);//验证码String code = (String) request.getSession().getAttribute("code");// 获取页面提交的验证码String inputCode = request.getParameter("code");//登录成功要同时满足用户存在且验证码正确boolean equals_code = code.toLowerCase().equals(inputCode.toLowerCase());if (count > 0 && equals_code) {//查询成功,解析Thymeleaf模板processTemplate("list", request, response);} else if(!equals_code){request.setAttribute("errorMsg", "验证码错误");processTemplate("error", request, response);} else {request.setAttribute("errorMsg", "用户不存在");processTemplate("error", request, response);}} catch (Exception e) {e.printStackTrace();//跳转到统一的异常提示页面request.setAttribute("errorMsg", e.getMessage());processTemplate("error", request, response);}}//获取分页学生列表数据public void getStudentList(HttpServletRequest request, HttpServletResponse response) throws Exception {Map<String, String[]> parameterMap = request.getParameterMap();//将请求参数封装到PageStudent对象PageInfo pageStudent = new PageInfo();//将请求域中的数据与每个pageStudent对应起来BeanUtils.populate(pageStudent, parameterMap);Long currentPage = pageStudent.getCurrentPage();Long pageSize = pageStudent.getPageSize();pageStudent = studentService.getPageInfo(currentPage, pageSize);//调用业务层的方法查询某一页的学生信息,所以currentPage需要前端处理好访问哪一页后传递过来List<Student> studentList = studentService.findStudentByPage(currentPage);//将pageStudent存储到请求域中request.setAttribute("pageInfo", pageStudent);//将某一页的学生信息存储到request一个名为list的对象中request.setAttribute("list", studentList);//跳转到展示页面processTemplate("student-table", request, response);}
}

StudentService

根据面向接口编程的原则,所以先实现这个接口。

面向接口的好处:当具体的业务逻辑要进行变更时,不需要改变Servlet层的代码,只需要重新写一个实现类去实现该接口,当然原先的接口也可以保存下来,只需要在导入实现类包的时候选择最新的那个。

package com.lzk.service;import com.lzk.bean.PageInfo;
import com.lzk.bean.Student;import java.sql.SQLException;
import java.util.List;public interface StudentService {//查询某一页学生信息List<Student> findStudentByPage(long pagenumber) throws Exception;//删除学生信息public void deleteStudentById(Integer id) throws Exception;//添加学生信息public void insertStudent(Student student) throws Exception;//查询指定学生信息public Student findStudentById(Integer id) throws Exception ;//修改学生信息public void updateStudent(Student student) throws Exception;//查询学生是否存在public long findExistStudent(String id,String name) throws Exception;//查询学生总数public long findAllStudentCount() throws Exception;//返回学生的分页导航数据PageInfo getPageInfo(Long currentPage, Long pageSize) throws Exception;}

StudentServiceImpl

package com.lzk.service.impl;import com.lzk.bean.PageInfo;
import com.lzk.bean.Student;
import com.lzk.dao.StudentDao;
import com.lzk.dao.impl.StudentDaoImpl;
import com.lzk.service.StudentService;import java.sql.SQLException;
import java.util.List;public class StudentServiceImpl implements StudentService {//创建Dao对象private StudentDao studentDao = new StudentDaoImpl();//查询某一页学生信息@Overridepublic List<Student> findStudentByPage(long currentpage) throws Exception {return studentDao.findStudentByPage(currentpage);}//删除学生信息@Overridepublic void deleteStudentById(Integer id) throws Exception{studentDao.deleteStudentById(id);}//添加学生信息@Overridepublic void insertStudent(Student student) throws Exception {studentDao.insertStudent(student);}//查询指定学生信息@Overridepublic Student findStudentById(Integer id) throws Exception {return studentDao.findStudentById(id);}//修改学生信息@Overridepublic void updateStudent(Student student) throws Exception {studentDao.updateStudent(student);}//查询学生是否存在public long findExistStudent(String id,String password) throws Exception{return studentDao.findExistStudent(id, password);}//查询学生总数public long findAllStudentCount() throws Exception{return studentDao.findAllStudnetCount();}@Overridepublic PageInfo getPageInfo(Long currentPage,Long pageSize) throws SQLException {long totalCount = studentDao.findAllStudnetCount();long totalPage = totalCount % pageSize == 0 ? totalCount/pageSize : totalCount/pageSize + 1;Long nextPage = null;Long previousPage = null;if(currentPage < totalPage-1){nextPage = currentPage + 1;}if(currentPage != 0){previousPage = currentPage - 1;}PageInfo pageInfo = new PageInfo(currentPage,pageSize,totalCount,totalPage,previousPage,nextPage);return pageInfo;}
}

StudentDao

Service需要调用Dao层

为什么要分为三层,而不让StudentService直接处理完呢?
其实每一层都有对应的功能,servlet负责请求的处理,service负责具体的业务逻辑处理,dao层负责对数据库数据的处理。分为三层可以解耦合,让结构更为清晰。

package com.lzk.dao;import com.lzk.bean.PageInfo;
import com.lzk.bean.Student;import java.sql.SQLException;
import java.util.List;public interface StudentDao {//查询所有学生信息List<Student> findAll() throws SQLException;//查询某一页学生信息List<Student> findStudentByPage(long pagenumber) throws SQLException;//删除学生信息void deleteStudentById(Integer id) throws SQLException;//添加学生信息void insertStudent(Student student) throws SQLException;//查询指定学生信息Student findStudentById(Integer id) throws SQLException;//修改学生信息void updateStudent(Student student) throws SQLException;//根据学号,姓名查询学生是否存在,klong findExistStudent(String id,String password) throws SQLException;//查询数据总数long findAllStudnetCount() throws SQLException;}

list页面

list页面只展示导航条部分数据,学生数据是通过页面加载时发起th:onload="|getStudentListByPage(${currentPage == null ? 0 : currentPage})|"请求去获取的。这个方法在后面的student.js里。

<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>展示学生列表信息</title><!-- Bootstrap core CSS --><link href="/@bootcss/v3.bootcss@1.0.25/dist/css/bootstrap.min.css" rel="stylesheet"><link href="/@bootcss/v3.bootcss@1.0.25/assets/css/ie10-viewport-bug-workaround.css" rel="stylesheet"><link href="/@bootcss/v3.bootcss@1.0.25/examples/dashboard/dashboard.css" rel="stylesheet"><script src="js/jquery-1.8.3.js"></script><script src="js/student.js"></script>
</head>
<body th:onload="|getStudentListByPage(${currentPage == null ? 0 : currentPage})|"><div><nav class="navbar navbar-inverse navbar-fixed-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#">学生信息管理系统</a></div></div></nav><div class="row"><div class="col-sm-3 col-md-2 sidebar"><ul class="nav nav-sidebar"><li><a th:onclick="getStudentListByPage(0)" style="cursor: pointer">分页学生信息</a></li><li><a th:onclick="toStudentInfoPage(-1,-1)" style="cursor: pointer">添加学生信息</a></li></ul></div><div id="content"></div></div></div>
</body>
</html>

student.js

第一次发起的请求为:student?method=getStudentList&currentPage=0,这个请求还是通过web.xml中配置的StudentServlet处理,处理逻辑看上面的StudentServlet中的getStudentList方法。其中的PageInfo包装了分页信息。

//异步加载学生信息列表
function getStudentListByPage(currentPage) {$.ajax({url: 'student?method=getStudentList&currentPage='+currentPage,type: 'GET',success: function(response) {$("#content").empty();$("#content").html(response)}});
}
//删除学生信息
function deleteStudentById(studentId,currentPage) {$.ajax({url: 'student?method=deleteStudent&id=' + studentId,type: 'GET',success: function () {getStudentListByPage(currentPage);}});
}function showAppointPage() {var current = document.getElementById("appointPage").value;getStudentListByPage(current-1);
}function toStudentInfoPage(studentId,currentPage) {$.ajax({url: 'student',type: 'GET',data: { 'method': 'toStudentInfoPage', 'id': studentId, 'currentPage': currentPage},success: function(response) {$("#content").empty();$("#content").html(response)}});
}function updateOrAddStudent() {// 获取表单数据var formData = new FormData(document.getElementById('myForm'));$.ajax({url: 'student',type: 'post',data: formData,contentType: false});}function checkPage() {var appointPage = parseInt($("#appointPage").val());var totalPage = parseInt($("#totalPage").text());if (appointPage < 0 ) {$("#appointPage").val("1");}else if(appointPage > totalPage){$("#appointPage").val("1");}
}

student-table.html

<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Title</title>
</head>
<body><div class="col-sm-8 col-sm-offset-3 col-md-10 col-md-offset-2 main" ><h1 class="sub-header">List Student</h1><div class="table-responsive" ><table class="table table-striped" th:unless="${#lists.isEmpty(list)}" border="1" cellspacing="0" width="800"><thead><tr><th style="text-align:center">学生的编号</th><th style="text-align:center">学生的姓名</th><th style="text-align:center">学生的班级</th><th>删除信息</th><th>修改信息</th></tr></thead><!--   如果没有学生信息,则显示没有学生数据,请添加学生  --><tbody th:if="${#lists.isEmpty(list)}"><tr><td th:colspan="5">没有学生数据,请添加学生</td></tr></tbody><!--  如果有学生信息,则遍历展示学生信息   --><tbody th:unless="${#lists.isEmpty(list)}"><!--  使用th:each遍历域对象里面的集合    --><tr  th:each="student : ${list}"><td th:text="${student.studentId}" align="center">学生的编号</td><td th:text="${student.studentName}" align="center">学生的姓名</td><td th:text="${student.studentClass}" align="center">学生的班级</td><td><a th:onclick="|deleteStudentById(${student.studentId},${pageInfo.currentPage})|" style="cursor: pointer">删除信息</a></td><td><a th:onclick="|toStudentInfoPage(${student.studentId},${pageInfo.currentPage})|" style="cursor: pointer">修改</a></td></tr></tbody><!--   页面导航的超链接    --><tr th:unless="${#lists.isEmpty(list)}"><td  colspan="5" align="center">共<span id="totalPage" th:text="${pageInfo.totalPage}">共多少页</span>页  第<span th:text="${pageInfo.currentPage}+1">第几页</span>页</td></tr ><tr th:unless="${#lists.isEmpty(list)}"><td colspan="5" align="center" ><input type="button" value="跳转"  onclick="showAppointPage()" /><input style="width:70px;" id="appointPage"  th:value="${pageInfo.currentPage+1}" onkeyup="checkPage()" />&nbsp;页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="button" value="首页"  onclick="getStudentListByPage(0)" /><input th:if="${pageInfo.previousPage != null}" type="button" value="上一页"  th:onclick="|getStudentListByPage(${pageInfo.previousPage})|" /><input th:if="${pageInfo.nextPage != null}" type="button" value="下一页"  th:onclick="|getStudentListByPage(${pageInfo.nextPage})|" /><input type="button" value="尾页"  th:onclick="|getStudentListByPage(${pageInfo.totalPage-1})|" /><br/></td></tr></table></div>
</div></body>
</html>

error.html

<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head><meta charset="UTF-8"><title>错误页面</title><script language="javascript" th:inline="javascript">//返回登录页面function backLogin() {window.location.href = "portalServlet";}</script><style type="text/css">.back-button{width: 65px;color: #fff;background-color: #337ab7;border-color: #2e6da4;-ms-touch-action: manipulation;border: 1px solid transparent;padding: 6px 12px;font-size: 14px;line-height: 1.42857143;border-radius: 4px;}</style>
</head>
<body><div align="center"><img src="image/pange.gif" ><h1 th:text="${errorMsg}">显示一个动态的错误信息</h1><input class="back-button" type="submit"  onclick="backLogin()" value="返回"><br/></div></body>
</html>

student-insertion.html

<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head><meta charset="UTF-8"><title>学生信息添加页面</title><base th:href="@{/}"/><script type="text/javascript" src="js/jquery-1.8.3.js"></script><link href="/bootstrap-3.4.1-dist/css/bootstrap.css" rel="stylesheet"><script src=".1.1/jquery.min.js"></script><script src=".3.7/js/bootstrap.min.js"></script><script type="text/javascript">function check() //onsubmit:return true:表单正常提交,return false表单终止{var sno=$("#stu_name").val();var sname=$("#stu_class").val();if(!(sno.length>1&&sno.length<10)){alert("填写姓名信息有误!");return false;}if(!(sname.length>2&&sname.length<10)){alert("班级信息有误!")return false;}return true;}</script>
</head>
<body><div class="container"><div class="row"><div class="col-md-12 "><form th:action="@{/student(method='insertStudent')}" method="post" class="form-horizontal" onsubmit="return check()"><!-- 表单区域--><fieldset><!--表单主题--><legend>填写新增学生信息</legend><!-- 每一个form-group都可以自定义布局--><tr ><a th:href="@{/student(method='LoginSuccess')}">返回</a></tr><div class="form-group"><!-- label表示文字提示标签,可以通过表单的组建的id提示--><label class="col-md-2 control-label" for="stu_name">学生姓名</label><div class="col-md-4"><input class="form-control" input type="text" id="stu_name" name="studentName"/></div></div><div class="form-group"><!-- label表示文字提示标签,可以通过表单的组建的id提示--><label class="col-md-2 control-label" for="stu_class">学生班级</label><div class="col-md-4"><input class="form-control" type="text" id="stu_class" name="studentClass"/></div></div><div class="form-group"><div class="col-md-6 col-md-offset-3"><input class="btn btn-primary" type="submit" value="添加"/><input class="btn btn-warning" type="reset" value="重置"/></div></div></fieldset></form></div></div>
</div>
</body>
</html>

student-update.html

<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head><meta name="viewport" content="width=device-width, initial-scale=1.0">
</head><body>
<div><div style="width: 75%;padding-left: 25%;padding-top: 2%"><!-- 表单区域--><form id="myForm"><fieldset><legend th:if="${student.studentId != null}">修改学生信息</legend><legend th:if="${student.studentId == null}">添加学生信息</legend><input type="hidden" name="method" value="updateOrAddStudent"><input type="hidden" name="currentPage" th:value="${currentPage == null ? -1 : currentPage}" placeholder="Appoint Page"><div class="form-group row"  th:if="${student.studentId != null}" ><label class="col-md-2 control-label" for="stu_id">学生学号</label><div class="col-md-4"><input class="form-control" readonly="readonly" type="text" id="stu_id" th:value="${student.studentId}" name="studentId" /></div></div><div class="form-group row"><label class="col-md-2 control-label" for="stu_name">学生姓名</label><div class="col-md-4"><input th:if="${student.studentId != null}" class="form-control" type="text" id="stu_name" th:value="${student.studentName}" name="studentName"/><input th:if="${student.studentId == null}" class="form-control" type="text" id="stu_name" th:value="${student.studentName}" name="studentName"/></div></div><div class="form-group row"><label class="col-md-2 control-label" for="stu_class">学生班级</label><div class="col-md-4"><input th:if="${student.studentId != null}" class="form-control" type="text" id="stu_class" th:value="${student.studentClass}" name="studentClass"/><input th:if="${student.studentId == null}" class="form-control" type="text" id="stu_class" th:value="${student.studentClass}" name="studentClass"/></div></div><div class="form-group"><div class="col-md-6 col-md-offset-3"><input th:if="${student.studentId != null}"class="btn btn-primary" type="submit" value="修改" onclick="updateOrAddStudent()"/><input th:if="${student.studentId == null}" class="btn btn-primary" type="submit" value="添加" onclick="updateOrAddStudent(-1)"/><input class="btn btn-warning" type="reset" value="重置"/></div></div></fieldset></form></div>
</div></body>
</html>

更多推荐

JavaWeb学生管理系统(详细源码+解析)

本文发布于:2023-12-06 00:13:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1665841.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:管理系统   源码   学生   详细   JavaWeb

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!