学生成绩管理系统(JAVA
作者:mmseoamin日期:2023-12-14

提示:该系统是基于Java界面编程+mysql的

文章目录

  • 一、功能展示
  • 二、技术选型
  • 三、表结构的创建
  • 四、工能分析
  • 五、代码实现
    • Druid数据库连接池读取properties文件
    • 六、代码获取
    • 七、心得总结

      一、功能展示

      SAMS学生成绩管理系统功能展示

      二、技术选型

      IDEA开发工具

      Java界面编程

      jdk1.8

      mysql8.0.26

      Druid数据连接池

      MVC三层架构模型

      exe4j可执行文件生成工具(将jar包变成可运行的exe程序)

      三层架构简单介绍:

      三层架构是指:视图层 View、服务层 Service,与持久层 Dao。它们分别完成不同的功能。

      View 层:用于接收用户提交请求的代码在这里编写。

      Service 层:系统的业务逻辑主要在这里完成。

      Dao 层:直接操作数据库的代码在这里编写。

      MVC简单介绍:( Model 模型、View 视图,及 Controller 控制器)。

      View:视图,为用户提供使用界面,与用户直接进行交互。

      Model:模型,承载数据,是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据

      其分为两类:

      一类:称为数据承载 Bean:实体类,专门用户承载业务数据的,如 Student、User 等 。

      二类:称为业务处理 Bean,指 Service 或 Dao 对象,专门用于处理用户提交请求的。

      Controller:控制器,用于将用户请求转发给相应的 Model 进行处理,并根据 Model 的计算结果向用户提供相应响应。


      三、表结构的创建

      该小系统纯纯自己写的,表关系也是自己在写的过程中,不断试错完善的,如有不对的地方,请私信我,咱么共同学习进步

      学生成绩管理系统(JAVA,在这里插入图片描述,第1张

      建库建表语句(该版本是mysql8.0版,其他版本的注意那个字符编码方式,不然容易报错)

      这里我在插一嘴啊:

      • 国际上的UTF-8,在MySQL中,对标的是uft8mb4。
      • 在MySQL中,实际只有utf8mb4和utf8mb3。至于uft8,在 V8.0 还是指代的utf8mb3,未来的会变为uft8mb4。
      • 好消息是MySQL在未来会改正uft8的命名:“在未来的MySQL版本中会删除utf8mb3,请改用utf8mb4。虽然utf8目前是utf8mb3的别名,但在未来某个时候,utf8将指代utf8mb4。为了避免对utf8的含义产生歧义,可以考虑直接把字符集引用指定为utf8mb4,而不是utf8。”
      -- 例如创建一个sams库
      create database sams;
      -- 选中该库
      use sams;
      -- 关闭外键检查,确保表的成功创建和数据的插入
      -- 主要是管理员用户的sno在student表中没有参照对象(sno是建立外键约束的)
      SET FOREIGN_KEY_CHECKS=0;
      -- 创建课程表
      CREATE TABLE `course` (
        `Cno` int NOT NULL AUTO_INCREMENT,
        `Cname` varchar(20) NOT NULL,
        `Ccredit` smallint NOT NULL,
        PRIMARY KEY (`Cno`),
        UNIQUE KEY `Cname` (`Cname`)
      ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      INSERT INTO `course` VALUES (1,'数据库',4),(2,'数学',2),(3,'信息系统',4),(4,'操作系统',3),(5,'数据结构',3),(6,'数据处理',4),(7,'C语言',2),(10,'数字图像',4),(11,'英语',3);
      -- 创建成绩表
      CREATE TABLE `sc` (
        `Sno` char(11) NOT NULL,
        `Cno` int NOT NULL,
        `Grade` int DEFAULT '0',
        PRIMARY KEY (`Sno`,`Cno`),
        KEY `Cno` (`Cno`),
        CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`Sno`) REFERENCES `student` (`Sno`) ON DELETE CASCADE,
        CONSTRAINT `sc_ibfk_2` FOREIGN KEY (`Cno`) REFERENCES `course` (`Cno`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      -- 创建院系表
      CREATE TABLE `sdept` (
        `id` int NOT NULL AUTO_INCREMENT,
        `sdept_name` varchar(20) DEFAULT NULL,
        PRIMARY KEY (`id`),
        UNIQUE KEY `sdept_name` (`sdept_name`)
      ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      INSERT INTO `sdept` VALUES (4,'商学院'),(6,'外语学院'),(2,'数学学院'),(3,'机械学院'),(5,'电器学院'),(8,'艺术学院'),(1,'计算机学院'),(7,'飞行学院');
      -- 创建人员表
      CREATE TABLE `student` (
        `Sno` char(11) NOT NULL,
        `Sname` varchar(10) NOT NULL,
        `Ssex` char(1) DEFAULT NULL,
        `Sage` smallint NOT NULL,
        `Sdept_id` int DEFAULT '0',
        PRIMARY KEY (`Sno`),
        KEY `Sdept_id` (`Sdept_id`),
        CONSTRAINT `student_ibfk_1` FOREIGN KEY (`Sdept_id`) REFERENCES `sdept` (`id`),
        CONSTRAINT `student_chk_1` CHECK (((`Ssex` = _utf8mb4'男') or (`Ssex` = _utf8mb4'女')))
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      INSERT INTO `student` VALUES ('20021010203','王老师','女',30,2),('20021010410','张美丽','女',23,6),('20031010209','王小明','男',20,4),('20031010301','张晓明','男',21,3),('20031010302','李晓红','女',20,3),('20031010303','罗志祥','男',19,3);
      -- 创建用户表(Sno前四位:2001是管理员类,2002是教师一类,2003是学生一类)
      CREATE TABLE `user` (
        `Sno` char(11) NOT NULL,
        `username` varchar(20) NOT NULL,
        `password` varchar(20) NOT NULL,
        PRIMARY KEY (`Sno`),
        CONSTRAINT `user_ibfk_1` FOREIGN KEY (`Sno`) REFERENCES `student` (`Sno`) ON DELETE CASCADE
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
      INSERT INTO `user` VALUES ('20011010001','管理员','hyl123456'),('20021010410','张美丽','hyl123456'),('20031010301','张晓明','hyl123456');
      -- 表和数据都正常插入后再次打开外键检查
      SET FOREIGN_KEY_CHECKS=1;
      

      四、工能分析

      登录界面

      工(学)号、用户名、密码格式的校验

      根据上述信息查询User表,进行登录验证

      根据工(学)号的前4位,跳转打开对应的页面

      2001:打开管理员界面

      2002:打开教师界面

      2003:打开学生界面

      注册界面

      工(学)号、用户名、密码格式的校验

      工(学)号,与身份的对应关系的校验

      2003:是学生

      2002:是教师

      注册时有一个身份的选择,在提交时会进行校验

      密码校验,密码输入两次,输入内容有一致性检验

      提交注册,信息都符合要求会在User表中,插入该用户

      学生界面

      欢迎提示语(欢迎XXX同学)

      修改自己的密码:

      密码格式的校验

      输入旧密码,与User表中的密码做校验

      输入新密码(上述旧密码与表中一致,实现修改)

      成绩查询:根据学号查询Sc表,返回该学生的所有课程成绩

      教师界面

      欢迎提示语(欢迎XXX同学)

      修改自己的密码:

      密码格式的校验

      输入旧密码,与User表中的密码做校验

      输入新密码(上述旧密码与表中一致,实现修改)

      查询成绩(院系选择、课程选择、学号):

      返回字段:学号+姓名+课程名+得分

      查询情况分类:

      无学号:

      1、所有院系所有课程(查sc全表)

      2、所有院系某一课程(指定查询sc表)

      3、某一院系所有课程(指定查询sc表)

      4、某一院系某一课程(指定查询sc表)

      有学号:(学号是一个学生的主键,知道学号就能锁定学生,此时院系不在影响查询)

      1、某一学生所有课程(指定查询sc表)

      2、某一学生某一课程(指定查询sc表)

      成绩录入界面

      学号,成绩格式的校验

      学号与身份的校验(为学生录入成绩,必须是2003开头的)

      提交在sc表中插入一条数据

      管理员界面

      各种输入的格式校验

      重置除管理员外的所有其他用户(学生,老师)的密码

      添加老师或学生

      添加院系或课程

      修改用户信息(姓名,性别,年龄,院系)

      删除用户(从student表中进行删除,删除后User表里和Sc表里与其相关的所有数据都会被删掉)

      User表和Sc表里的Sno属性与student表里的Sno属性都建立了外键约束,并且添加了删除级联。

      所以删除时要 — 慎用!慎用!慎用!

      信息修改界面

      填写的信息的格式校验

      信息的回显:在管理员点击修改后,依据工(学)号,查询student表,返回信息在对应的修改框中

      提交修改,更新student表中的数据


      五、代码实现

      包结构:

      学生成绩管理系统(JAVA,在这里插入图片描述,第2张

      lib包

      学生成绩管理系统(JAVA,在这里插入图片描述,第3张

      dao包

      学生成绩管理系统(JAVA,在这里插入图片描述,第4张

      domain包

      学生成绩管理系统(JAVA,在这里插入图片描述,第5张

      service包

      学生成绩管理系统(JAVA,在这里插入图片描述,第6张

      utils包

      学生成绩管理系统(JAVA,在这里插入图片描述,第7张

      View包

      学生成绩管理系统(JAVA,在这里插入图片描述,第8张

      还有一个重要的properties文件(直接放在src层级下,就是说与上述包是同一等级的)

      学生成绩管理系统(JAVA,在这里插入图片描述,第9张

      Druid数据库连接池读取properties文件

      通过小伙伴给我的反应,好多人刚接触不懂这个连接数据库,读取配置文件这一块儿,说下载的代码在本地不能正常跑,本身我以为上图给大家指出的已经挺详细的的了。不过没关系,这里我在说明一下:

      唉,你们下载的代码那个druid.properties文件里面的配置信息是我本地的,你们使用要变更成你们对应的配置信息(端口号,用户名,密码,要连接的库)

      请看这篇文章,专门又为小伙伴们写的

      https://blog.csdn.net/m0_58730471/article/details/128161470

      BasicDao

      package com.hyl.sams.dao;
      import com.hyl.sams.utils.Jdbc_Druid_Utils;
      import org.apache.commons.dbutils.QueryRunner;
      import org.apache.commons.dbutils.handlers.BeanHandler;
      import org.apache.commons.dbutils.handlers.BeanListHandler;
      import org.apache.commons.dbutils.handlers.ScalarHandler;
      import java.sql.Connection;
      import java.sql.SQLException;
      import java.util.List;
      /**
       * 是其它dao的父类
       * 有update(增删改) 多行返回,单行返回,单行单列返回
       * @author hyl
       */
      public class BasicDao {
          private QueryRunner qr=new QueryRunner();
      	//统一说明:Object... parameters
      	// 是动态传参,参数个数0-n
      	
          /**
           *  插入、更新或删除
           * @param sql
           * @param parameters
           * @return
           */
          public int update(String sql,Object... parameters){
              Connection connection=null;
              try {
                  connection= Jdbc_Druid_Utils.getConnection();
                  int update = qr.update(connection, sql, parameters);
                  return update;
              } catch (SQLException e) {
                  throw new RuntimeException(e);
              }finally {
                  Jdbc_Druid_Utils.Close(null,null,connection);
              }
          }
          /**
           * 返回多行记录
           * @param sql
           * @param tClass
           * @param parameters
           * @param 
           * @return
           */
          public  List queryMulti(String sql, Class tClass, Object... parameters){
              Connection connection=null;
              try {
                  connection= Jdbc_Druid_Utils.getConnection();
                  return qr.query(connection, sql, new BeanListHandler(tClass), parameters);
              } catch (SQLException e) {
                  throw new RuntimeException(e);
              }finally {
                  Jdbc_Druid_Utils.Close(null,null,connection);
              }
          }
          /**
           * 返回单行
           * @param sql
           * @param tClass
           * @param parameters
           * @param 
           * @return
           */
          public  T querySingle(String sql, Class tClass, Object... parameters){
              Connection connection=null;
              try {
                  connection= Jdbc_Druid_Utils.getConnection();
                  return qr.query(connection, sql, new BeanHandler(tClass), parameters);
              } catch (SQLException e) {
                  throw new RuntimeException(e);
              }finally {
                  Jdbc_Druid_Utils.Close(null,null,connection);
              }
          }
          /**
           * 返回单行单列
           * @param sql
           * @param parameters
           * @return
           */
          public Object queryScalar(String sql,Object...parameters){
              Connection connection=null;
              try {
                  connection= Jdbc_Druid_Utils.getConnection();
                  return qr.query(connection, sql, new ScalarHandler<>(),parameters);
              } catch (SQLException e) {
                  throw new RuntimeException(e);
              }finally {
                  Jdbc_Druid_Utils.Close(null,null,connection);
              }
          }
      }
      

      StuSelectPlus:javaBean类用于数据传输比较简单,写一个意思一下就ok了

      package com.hyl.sams.domain;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/19-18:06
       * 用于教师界面查询成绩的
       * 包含的属性字段
       * 学号+姓名+课程名+课程得分
       */
      public class StuSelectPlus {
          private String Sno;
          private String Sname;
          private String Cname;
          private int Grade;
          public String getSno() {
              return Sno;
          }
          public void setSno(String sno) {
              Sno = sno;
          }
          public String getSname() {
              return Sname;
          }
          public void setSname(String sname) {
              Sname = sname;
          }
          public String getCname() {
              return Cname;
          }
          public void setCname(String cname) {
              Cname = cname;
          }
          public int getGrade() {
              return Grade;
          }
          public void setGrade(int grade) {
              Grade = grade;
          }
          @Override
          public String toString() {
              return "StuSelectPlus{" +
                      "Sno='" + Sno + '\'' +
                      ", Sname='" + Sname + '\'' +
                      ", Cname='" + Cname + '\'' +
                      ", Grade=" + Grade +
                      '}';
          }
      }
      

      AdminService

      package com.hyl.sams.service;
      import com.hyl.sams.dao.BasicDao;
      import com.hyl.sams.domain.Student;
      import com.hyl.sams.domain.User;
      import com.hyl.sams.domain.sdept;
      import java.util.List;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/16-20:49
       * 管理员相关功能类
       */
      public class AdminService {
          private BasicDao dao =new BasicDao();
          /**
           * 重置除管理员外的其他用户的密码
           * @param pwd
           * @return
           */
          public boolean updatePwd(String pwd){
              int update = 0;
              try {
                  update = dao.update(" UPDATE USER SET PASSWORD=? WHERE SUBSTRING(sno,1,4)='2002' OR SUBSTRING(sno,1,4)='2003'",pwd);
              } catch (Exception e) {
                  System.out.println("密码重置失败");
              }
              return update>0;
          }
          /**
           * 查询返回院系列表
           * @return
           */
          public List findAllSName(){
              List list = dao.queryMulti("select * from sdept", sdept.class);
              return list;
          }
          /**
           * 根据院系id,返回某个院系名
           * @param id
           * @return
           */
          public String findOneSName(int id){
              String sname =(String) dao.queryScalar("select sdept_name from sdept where id=? ", id);
              return sname;
          }
          /**
           * 添加新的人员
           * @param Sno 工(学)号
           * @param name 姓名
           * @param sex 性别
           * @param age 年龄
           * @param sdeptName 学院
           * @return Boolean
           */
          public boolean addPerson(String Sno,String name,String sex ,byte age,String sdeptName){
              int update = 0;
              int id=0;
              try {
                   id =(int)dao.queryScalar("select id from sdept where sdept_name=?", sdeptName);
                  update = dao.update("insert into student values(?,?,?,?,?)",Sno,name,sex,age,id);
              } catch (Exception e) {
                  System.out.println("添加人员失败");
              }
              return update>0;
          }
          public int findSID(String sdeptName){
              return (int)dao.queryScalar("select id from sdept where sdept_name=?", sdeptName);
          }
          /**
           * 添加课程
           * @param cname 课程名称
           * @return Boolean
           */
          public boolean addCourse(String cname,byte Ccredit){
              int update = 0;
              try {
                  update = dao.update("insert into course values(null,?,?)",cname,Ccredit);
              } catch (Exception e) {
                  System.out.println("课程添加失败");
              }
              return update>0;
          }
          /**
           * 添加院系
           * @param name
           * @return
           */
          public boolean addSdept(String name){
              int update = 0;
              try {
                  update = dao.update("insert into sdept values(null,?)",name);
              } catch (Exception e) {
                  System.out.println("院系添加失败");
              }
              return update>0;
          }
          /**
           * 通过工(学)号,查询人员信息
           * @param sno
           * @return
           */
          public Student findBySno(String sno){
              Student student = dao.querySingle("select * from student where Sno=?", Student.class, sno);
              return student;
          }
          /**
           * 更新人员信息
           * @param s 封装的Bean
           * @return
           */
          public boolean updatePerson(Student s){
              int update = 0;
              try {
                  update = dao.update("update student set Sname=?,Ssex=?,Sage=? ,Sdept_id=? where Sno=? ",
                          s.getSname(),s.getSsex(),s.getSage(),s.getSdept_id(),s.getSno());
              } catch (Exception e) {
                  System.out.println("信息修改失败");
              }
              return update>0;
          }
          /**
           * student的sno与User表和Sc表的sno都建立外键关系
           * 并且添加了删除级联
           * 当从student表中删除一个人员时,也会同时删除User和Sc表中与其关联的所有信息
           *
           * 慎用!!!!!!
           *
           * @param s 工(学)号
           * @return
           */
          public boolean delPerson(String s){
              int update = 0;
              try {
                  update = dao.update("delete from student where Sno=? ", s);
              } catch (Exception e) {
                  System.out.println("人员删除失败");
              }
              return update>0;
          }
          /**
           * 检查要删除的人员还在不在
           * @param Sno 学号
           * @return 在-TRUE 不在-FALSE
           */
          public boolean delCheck(String Sno){
              User user=null;
              user = dao.querySingle("select * from User where Sno=?", User.class, Sno);
              return user!=null;
          }
      }
      

      TeacherService

      package com.hyl.sams.service;
      import com.hyl.sams.dao.BasicDao;
      import com.hyl.sams.domain.Course;
      import com.hyl.sams.domain.StuSelectPlus;
      import com.hyl.sams.domain.sdept;
      import java.util.List;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/16-20:48
       * 教师的相关功能类
       */
      public class TeacherService {
          private BasicDao dao=new BasicDao();
          /**
           * 根据学号查询旧密码
           * @param sno
           * @return
           */
          public String findPwd(String sno){
              String pwd =(String) dao.queryScalar("select password from User where Sno=?",sno);
              return pwd;
          }
          /**
           * 更新密码
           * @param pwd
           * @param Sno
           * @return
           */
          public boolean updatePwd(String pwd,String Sno){
              int update = 0;
              try {
                  update = dao.update("update User set password=? where Sno=?",pwd,Sno);
              } catch (Exception e) {
                  System.out.println("密码更新失败");
              }
              return update==1;
          }
          /**
           * 根据课程名查找对应的课程id
           * @param cname 课程名
           * @return
           */
          public int findCID(String cname){
              int Cno = (int)dao.queryScalar("select Cno from course where Cname=?",cname);
              return Cno;
          }
          /**
           * 添加学生课程得分
           * @param sno 学号
           * @param cname 所学课程名
           * @param grade 得分
           * @return
           */
          public boolean addSc(String sno,int cname , int grade){
              int update = 0;
              try {
                  update = dao.update("insert into sc values(?,?,?)",sno,cname,grade);
              } catch (Exception e) {
                  System.out.println("课程添加失败");
              }
              return update>0;
          }
          /**
           * 查询返回所有课程
           * @return
           */
          public List findCourse(){
              List list = dao.queryMulti("select * from course", Course.class);
              return list;
          }
          /**
           * 查询返回院系列表
           * @return
           */
          public List findAllSName(){
              List list = dao.queryMulti("select * from sdept", sdept.class);
              return list;
          }
          /**
           * 无学号情况下
           * 所有院系所有课程
           * @return
           */
          public List findAllSc(){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade` " +
                      " FROM sc,student,course WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno`; ",StuSelectPlus.class);
              return list;
          }
          /**
           * 无学号情况下
           * 所有院系某一课程
           * @param cname
           * @return
           */
          public List findAllSc1(String cname){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade` " +
                      " FROM sc,student,course WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno` and Cname=?; ",StuSelectPlus.class,cname);
              return list;
          }
          /**
           * 无学号情况下
           * 某一学院所有课程
           * @param sdept_name
           * @return
           */
          public List findAllSc2(String sdept_name){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade`" +
                      " FROM sc,student,course,sdept " +
                      " WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno` AND sdept.`id`=student.`Sdept_id` " +
                      " AND sdept.`sdept_name`=?;", StuSelectPlus.class, sdept_name);
              return list;
          }
          /**
           * 无学号情况下
           * 某一学院某一课程
           * @param sdept_name 学院
           * @param Cname 课程
           * @return
           */
          public List findAllSc3(String sdept_name,String Cname){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade`" +
                      " FROM sc,student,course,sdept " +
                      " WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno` AND sdept.`id`=student.`Sdept_id` " +
                      " AND sdept.`sdept_name`=? AND course.`Cname`=?;", StuSelectPlus.class, sdept_name,Cname);
              return list;
          }
          /**
           * 有学号的情况下
           * 院系信息已经无影响了
           * 查询该学生全部课程
           * @param sno 学号
           * @return
           */
          public List findGrade1(String sno){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade` " +
                      "FROM sc,student,course WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno` AND sc.`Sno`=?;", StuSelectPlus.class, sno);
              return list;
          }
          /**
           *有学号的情况下
           *院系信息已经无影响了
           *查询该学生某一课程成绩
           * @param sno 学号
           * @param cname 课程名
           * @return
           */
          public List findGrade2(String sno,String cname){
              List list = dao.queryMulti("SELECT sc.`Sno`,student.`Sname`,course.`Cname`,sc.`Grade` " +
                      "FROM sc,student,course WHERE sc.`Sno`=student.`Sno` AND sc.`Cno`=course.`Cno` " +
                      "AND sc.`Sno`=? and course.`Cname`=?;", StuSelectPlus.class, sno,cname);
              return list;
          }
      }
      

      Jdbc_Druid_Utils

      package com.hyl.sams.utils;
      import com.alibaba.druid.pool.DruidDataSourceFactory;
      import javax.sql.DataSource;
      import java.io.FileReader;
      import java.io.InputStream;
      import java.sql.Connection;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.Statement;
      import java.util.Properties;
      /**
       * 德鲁伊连接池工具类
       * 连接池工具类,连接数据库
       * @author hyl
       */
      public class Jdbc_Druid_Utils {
          private static DataSource source;
          //初始化连接
          static {
              Properties properties = new Properties();
              try {
                  //使用ClassLoader加载配置文件,获取字节输入流
                  InputStream is = Jdbc_Druid_Utils.class.getClassLoader().getResourceAsStream("druid.properties");
                  properties.load(is);
                  source = DruidDataSourceFactory.createDataSource(properties);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          //获取连接
          public static Connection getConnection() throws SQLException {
              return source.getConnection();
          }
          /**
           * 释放连接(不是断掉连接,而是归还释放)
           * @param resultSet
           * @param statement
           * @param connection
           */
          public static void Close(ResultSet resultSet, Statement statement, Connection connection){
              try {
                  if (resultSet!=null) {
                      resultSet.close();
                  }
                  if (statement!=null) {
                      statement.close();
                  }
                  if (connection!=null) {
                      connection.close();
                  }
              } catch (SQLException e) {
                  throw new RuntimeException(e);
              }
          }
      }
      

      SetMyStyle

      package com.hyl.sams.utils;
      import javax.swing.*;
      import java.awt.*;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/19-10:02
       * 给组件设置不同的样式
       */
      public class SetMyStyle {
          private static Font font1 = new Font("宋体", Font.BOLD, 30);
          private static Font font = new Font("宋体", Font.BOLD, 16);
          private static Font font2 = new Font("宋体", Font.BOLD, 12);
          /**
           * 提示语样式设置
           * @param name 提示语
           * @param a 选择标签
           * @return Jlabel
           */
          public  static JLabel SetMyFont1(String name, int a){
              JLabel p=new JLabel(name);
              p.setForeground(Color.WHITE);
              if (a==1){
                  p.setFont(font1);
              }else if (a==2){
                  p.setFont(font);
              }else if(a==3){
                  p.setForeground(Color.CYAN);
                  p.setFont(font);
              }else if(a==4){
                  p.setForeground(Color.RED);
                  p.setFont(font2);
              }else if(a==5){
                  p.setForeground(Color.RED);
                  p.setFont(font);
              }
              return p;
          }
          /**
           * 按钮的样式设置
           * @param name
           * @param a
           * @return
           */
          public  static JButton SetMyButton1(String name,int a){
              JButton p=new JButton(name);
              p.setForeground(Color.WHITE);
              if (a==1){
                  p.setFont(font2);
              }else if(a==2){
                  p.setForeground(Color.RED);
                  p.setFont(font2);
              }else if(a==3){
                  p.setForeground(Color.RED);
                  p.setFont(font);
              }else if(a==4){
                  p.setFont(font);
              }
              return p;
          }
          /**
           * 设置下拉框风格
           * @param x
           * @return
           */
          public static JComboBox setMyJComboBox(int x){
              //下拉框
              JComboBox jcb = new JComboBox();
              //设置组件的宽和高
              Dimension dim = new Dimension(200, 30);
              jcb.setPreferredSize(dim);
              if(x==1){
                  jcb.setFont(font);
              }else if(x==2){
                  jcb.setFont(font1);
              }else{
                  jcb.setFont(font2);
              }
              return jcb;
          }
      }
      

      ValidationUtil

      package com.hyl.sams.utils;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      import static java.util.regex.Pattern.*;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/18-20:47
       * 校验输入字符的合法性
       * 用户名(汉字、字母、数字的组合):^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$
       *
       * 密码(6-16位数字和字母的组合):^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$
       *
       * 年龄(1岁--120岁):^(?:[1-9][0-9]?|1[01][0-9]|120)$
       *
       * 电话号码:^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$
       */
      public class ValidationUtil {
          /**
           * 校验学号是不是11位,并且是不是都是数字,开头三位必须得是200
           * @param str 输入的学号
           * @return
           */
          public static boolean checkSno(String str){
              Pattern pattern = compile("^200\\d{8}");
              Matcher isNum = pattern.matcher(str);
              if( !isNum.matches() ){
                  return false;
              }
              return true;
          }
          /**
           * 性别的校验
           * @param sex
           * @return
           */
          public static boolean checkSex(String sex){
              if ("男".equals(sex)){
                  return true;
              }else if("女".equals(sex)){
                  return true;
              }
              return false;
          }
          /**
           * 正则校验年龄在1-120之间
           * @param age
           * @return
           */
          public static boolean checkAge(String age){
                Pattern pattern=compile("^(?:[1-9][0-9]?|1[01][0-9]|120)$");
              Matcher isName = pattern.matcher(age);
              if (!isName.matches() ){
                  return false;
              }
              return true;
          }
          /**
           * 检查分数的合法性(0-100)
           * @param grade
           * @return
           */
          public static boolean checkGrade(String grade){
              Pattern pattern=compile("^(?:[0-9][0-9]?|100)$");
              Matcher isName = pattern.matcher(grade);
              if (!isName.matches() ){
                  return false;
              }
              return true;
          }
          /**
           * 校验名字是不是中文,并且是2,6位之间(包含)
           * @param name
           * @return
           */
          public static boolean checkName(String name){
              Pattern pattern=compile("^[\\u4e00-\\u9fa5]{2,6}$");
              Matcher isName = pattern.matcher(name);
              if (!isName.matches() ){
                  return false;
              }
              return true;
          }
          /**
           * 校验密码数字和字母的组合(6-16位)
           * @param pwd
           * @return
           */
          public static boolean checkPassword(String pwd){
              Pattern pattern=compile("^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$");
              Matcher pwds = pattern.matcher(pwd);
              if(!pwds.matches()){
                  return false;
              }
              return true;
          }
          /**
           * 校验添加的课程名开头可以为字母
           * @param name
           * @return
           */
          public static boolean checkCname(String name){
              Pattern pattern=compile("^[a-zA-Z\\u4e00-\\u9fa5]{2,10}$");
              Matcher isName = pattern.matcher(name);
              if (!isName.matches() ){
                  return false;
              }
              return true;
          }
          /**
           * 校验院系名称(中文+最后二字为学院)
           * @param name
           * @return
           */
          public static boolean checkSdept(String name){
              Pattern pattern=compile("^[\\u4e00-\\u9fa5]{3,10}$");
              Matcher isName = pattern.matcher(name);
              StringBuffer buffer=new StringBuffer(name);
              int len=buffer.length();
              String s = buffer.substring(len - 2, len);
              //System.out.println("s="+s);
              if (!isName.matches() ){
                  return false;
              }else if(!"学院".equals(s)){
                  return false;
              }
              return true;
          }
          /**
           * 检查学分1-5之间的任意值
           * @param credit
           * @return
           */
          public static boolean checkCredit(String credit){
              Pattern pattern=compile("[1-5]");
              Matcher isName = pattern.matcher(credit);
              if (!isName.matches() ){
                  return false;
              }
              return true;
          }
      }
      

      View_Father

      package com.hyl.sams.view;
      import javax.swing.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.net.URL;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/15-16:08
       * 所有窗体的父类
       */
      public class View_Father extends JFrame {
          private ImageIcon background;
          private JPanel myPanel;
          private JLabel label;
          private JButton b1,b2;
          public View_Father(){
              b1=new JButton("退出系统");
              b1.setBounds(800,5,80,20);
              b2 = new JButton("回到登录页");
              b2.setBounds(2,5,90,20);
              this.add(b1);
              this.add(b2);
              /**
               * 加载图标
               */
              URL u = View_Father.class.getResource("imgs/tou.png");
              ImageIcon icon=new ImageIcon(u);
              this.setIconImage(icon.getImage());
              /**
               * 加载背景图片
               */
              URL url = View_Father.class.getResource("imgs/bg.jpg");
              background=new ImageIcon(url);
              //把背景图片添加到标签里
              label = new JLabel(background);
              //把标签设置为和图片等高等宽
              label.setBounds(0, 0, background.getIconWidth(),background.getIconHeight());
              //把我的面板设置为内容面板
              myPanel = (JPanel)this.getContentPane();
              //把我的面板设置为不可视
              myPanel.setOpaque(false);
              //把我的面板设置为流动布局
              myPanel.setLayout(null);
              b1.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      //关闭窗口释放屏幕资源
                      System.exit(0);
                  }
              });
              b2.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      new View1();
                      //关闭当前页面
                      setVisible(false);
                      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  }
              });
              //把分层面板的布局置空
              this.getLayeredPane().setLayout(null);
              //设置窗口不可改变,固定窗口大小
              this.setResizable(false);
              //把标签添加到分层面板的最底层
              this.getLayeredPane().add(label, new Integer(Integer.MIN_VALUE));
              this.setTitle("SAMS学生成绩管理系统");
              this.setBounds(300, 300, background.getIconWidth(),background.getIconHeight());
              //窗体弹出位置始终保证在屏幕中央
              this.setLocationRelativeTo(null);
              this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          }
      }
      

      View1

      package com.hyl.sams.view;
      import com.hyl.sams.domain.User;
      import com.hyl.sams.service.LoginService;
      import com.hyl.sams.utils.SetMyStyle;
      import com.hyl.sams.utils.ValidationUtil;
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/14-16:57
       * 登录界面
       */
      @SuppressWarnings("{all}")
      public class View1 extends View_Father {
          private LoginService service=new LoginService();
          //工号和用户名文本框
          private JTextField jtf1,jtf2;
          //密码框
          private JPasswordField jpf1;
          //提示语
          private JLabel jlb1,jlb2,jlb3,jlb4;
          //登录,退出,注册按钮
          private JButton jb1,jb2,jb3;
          //设置大标题
          private JLabel labTitle ;
          //设置几个字体样式
          Font font1 = new Font("宋体", Font.BOLD, 50);
          Font font = new Font("宋体", Font.BOLD, 16);
          public static String loginName ="";
          public static User myUser=null;
           View1(){
               super();
               labTitle = SetMyStyle.SetMyFont1("学生成绩管理系统",1);
               labTitle.setBounds(340,30,600,100);
               this.add(labTitle);
              //设计对话框及密码框的长度
               jtf1 = new JTextField(15);
               jtf2 = new JTextField(15);
               jpf1 = new JPasswordField(15);
              //设置按钮和其他字体
               jlb1 = new JLabel("用户名: ");
               jlb2 = new JLabel("密 码: ");
               jlb3 = new JLabel("没有账号,请先注册");
               jlb4 = new JLabel("工(学)号:");
               jlb1.setFont(font);
               jlb1.setForeground(Color.WHITE);
               jlb2.setFont(font);
               jlb2.setForeground(Color.WHITE);
               jlb3.setFont(font);
               jlb3.setForeground(Color.PINK);
               jlb4.setFont(font);
               jlb4.setForeground(Color.WHITE);
               jlb4.setBounds(230,150,600,80);
               jlb1.setBounds(230,220,600,80);
               jlb3.setBounds(710,100,600,80);
               jlb2.setBounds(230,290,600,80);
               jtf1.setBounds(350,175,250,30);
               jtf2.setBounds(350,240,250,30);
               jpf1.setBounds(350,310,250,30);
               this.add(jlb1);
               this.add(jlb2);
               this.add(jlb3);
               this.add(jlb4);
               this.add(jtf1);
               this.add(jtf2);
               this.add(jpf1);
              jb1 = new JButton("登录");
              jb2 = new JButton("退出");
              jb3 = new JButton("注册账号");
              jb1.setFont(font);
              jb2.setFont(font);
              jb3.setFont(font);
              jb1.setBounds(320,430,100,30);
              jb2.setBounds(500,430,100,30);
              jb3.setBounds(730,160,100,30);
              this.add(jb1);
              this.add(jb2);
              this.add(jb3);
              //在组件都加载完后,才显示
              this.setVisible(true);
              //登录按钮功能
              jb1.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent arg0) {
                      String sno = jtf1.getText().trim();
                      String username=jtf2.getText().trim();
                      String password = new String(jpf1.getPassword()).trim();
                      User u=null;
                      if(sno.length()==0||username.length()==0||password.length()==0){
                          JOptionPane.showMessageDialog(null,"工号用户名密码不允许为空","message",JOptionPane.ERROR_MESSAGE);
                      }
                      else if (!ValidationUtil.checkSno(sno)) {
                          JOptionPane.showMessageDialog(null, "工号输入有误", "message", JOptionPane.ERROR_MESSAGE);
                      } else {
                          if (!ValidationUtil.checkName(username)||!ValidationUtil.checkPassword(password)) {
                              JOptionPane.showMessageDialog(null, "用户名或密码有误", "message", JOptionPane.WARNING_MESSAGE);
                          }
                          //与数据库信息比较
                          else if ((myUser=service.loginCheck(sno,username,password))!=null) {
                              //JOptionPane.showMessageDialog(null, "登录成功");
                              //判断学号或者工号与身份是否对应 2002开头是老师 2003开头是学生
                              String trim = jtf1.getText().trim();
                              StringBuffer buffer = new StringBuffer(trim);
                              String s = buffer.substring(0, 4);
                              //System.out.println(s);
                              if ("2003".equals(s)) {
                                  //打开学生页面
                                  //System.out.println("成功!");
                                  View1.loginName=myUser.getUsername();
                                  new View3();
                              }else if ("2002".equals(s)){
                                  //打开教师页面
                                  View1.loginName=myUser.getUsername();
                                  new View4();
                              }else if ("2001".equals(s)){
                                  //打开管理员页面
                                  View1.loginName=myUser.getUsername();
                                  new View5();
                              }
                              //关闭当前页面
                              setVisible(false);
                              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                          } else {
                              JOptionPane.showMessageDialog(null, "登录失败,请检查工(学)号用户名或密码", "message", JOptionPane.ERROR_MESSAGE);
                          }
                      }
                  }
              });
              //退出功能
              jb2.addActionListener(new ActionListener() {
                  //设置监听
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      //关闭窗口释放屏幕资源
                      System.exit(0);
                  }
              });
              //注册页面
              jb3.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      //关闭当前页面
                      setVisible(false);
                      //跳转到注册页面
                      new View2();
                      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  }
              });
          }
      }
      

      View3

      package com.hyl.sams.view;
      import com.hyl.sams.domain.StudentSelect;
      import com.hyl.sams.service.StudentService;
      import com.hyl.sams.utils.SetMyStyle;
      import com.hyl.sams.utils.ValidationUtil;
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.util.List;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/14-18:42
       * 学生页面
       * 修改密码
       * 查询成绩
       */
      public class View3 extends View_Father{
          private static Font font = new Font("宋体", Font.BOLD, 16);
          private StudentService service=new StudentService();
          private JLabel labTitle,login ;
          private JLabel p1,p2,p3,p4,p5;
          private JPasswordField pwd1,pwd2;
          private JButton b1,b2;
          private JPanel bp;
          /**
           * JScrollPane是Container类的子类,也是一种容器,但是只能添加一个组件,滚动窗体
           */
          private JScrollPane scpDemo;
          private JTable tabDemo;
          public View3(){
              super();
              //标题和登录欢迎
              labTitle = SetMyStyle.SetMyFont1("学生界面",1);
              labTitle.setBounds(360,10,300,50);
              login=SetMyStyle.SetMyFont1("欢迎 "+View1.loginName+" 同学",5);
              System.out.println("loname:"+View1.loginName);
              login.setBounds(750,40,200,50);
              //其他提示语
              p1=SetMyStyle.SetMyFont1("修改密码",3);
              p1.setBounds(100,50,200,50);
              p2=SetMyStyle.SetMyFont1("旧密码:",2);
              p3=SetMyStyle.SetMyFont1("新密码:",2);
              p2.setBounds(250,100,100,50);
              p3.setBounds(250,150,100,50);
              pwd1=new JPasswordField(15);
              pwd2=new JPasswordField(15);
              pwd1.setBounds(340,110,250,30);
              pwd2.setBounds(340,160,250,30);
              b1=SetMyStyle.SetMyButton1("提交修改",2);
              b1.setBounds(600,160,80,30);
              b1.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      //获取输入的信息
                      String trim1 = new String(pwd1.getPassword()).trim();
                      String trim = new String(pwd2.getPassword()).trim();
                      //校验旧密码,保存新密码
                      String pwd = service.findPwd(View1.myUser.getSno());
                      if(trim.length()==0||trim1.length()==0){
                          JOptionPane.showMessageDialog(null,"新旧密码不允许为空","message",JOptionPane.ERROR_MESSAGE);
                      }else if(!ValidationUtil.checkPassword(trim)||!ValidationUtil.checkPassword(trim1)){
                          JOptionPane.showMessageDialog(null,"密码格式不正确","message", JOptionPane.ERROR_MESSAGE);
                      } else if (!pwd.equals(trim1)){
                          JOptionPane.showMessageDialog(null,"输入的旧密码不正确","message", JOptionPane.ERROR_MESSAGE);
                      }else if(trim.equals(trim1)){
                          JOptionPane.showMessageDialog(null,"新旧密码一样","message",JOptionPane.ERROR_MESSAGE);
                      }else{
                              boolean flag = service.updatePwd(trim, View1.myUser.getSno());
                              if (flag){
                                  JOptionPane.showMessageDialog(null,"修改成功,即将重新登录");
                                  setVisible(false);
                                  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                                  new View1();
                              }else{
                                  JOptionPane.showMessageDialog(null,"抱歉,密码更新失败!");
                              }
                          }
                  }
              });
              //查询成绩
              p4=SetMyStyle.SetMyFont1("查询本学年的选课成绩",3);
              p4.setBounds(100,200,200,50);
              b2=SetMyStyle.SetMyButton1("查询成绩",2);
              b2.setBounds(340,210,80,30);
              scpDemo = new JScrollPane();
              //底部bp
              bp=new JPanel();
              bp.setBounds(150, 240, 580, 300);
              bp.setLayout(null);
              //从数据库获取
              String sdept =service.findSdept(View1.myUser.getSno());
              if (sdept==null){
                  sdept="未知";
              }
              String tit="院系:"+sdept+" 学号:"+View1.myUser.getSno()+" 姓名: "+View1.myUser.getUsername();
              p5=SetMyStyle.SetMyFont1(tit,4);
              p5.setBounds(130,0,580,20);
              bp.add(p5);
              b2.addActionListener(new ActionListener() {
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      // 将查询获得的记录数据,转换成适合生成JTable的数据形式
                      //count为数据库查询的记录数
                      List list = service.findGrade(View1.myUser.getSno());
                      int num=list.size();
                      int count=0;
                      Object[][] info = null;
                      String[] title = {"课程编号", "课程名称", " 课程得分"};
                      double sum=0;
                      if (num==0){
                          info = new Object[num+1][3];
                          info[count][2]="课程平均分"+0.0;
                      }else{
                          info = new Object[num+1][3];
                          for (StudentSelect stu : list) {
                              info[count][0]=stu.getCno();
                              info[count][1]=stu.getCname();
                              info[count][2]=stu.getGrade();
                              sum+=(double) (Integer)info[count][2];
                              count++;
                          }
                          info[count][2]="课程平均分"+sum/count;
                      }
                      info[count][0]="共选课程"+count+"门";
                      info[count][1]="课程总分:"+sum;
                      // 创建JTable
                      tabDemo = new JTable(info, title);
                      // 获得tabDemo的表头,并设置字体样式
                      tabDemo.getTableHeader().setFont(font);
                      scpDemo.setBounds(0,20,580,280);
                      // 将JTable加入到带滚动条的面板中
                      scpDemo.getViewport().add(tabDemo);
                      bp.add(scpDemo);
                  }
              });
              this.add(bp);
              this.add(b2);
              this.add(p4);
              this.add(b1);
              this.add(pwd1);
              this.add(pwd2);
              this.add(p2);
              this.add(p3);
              this.add(p1);
              this.add(labTitle);
              this.add(login);
              this.setVisible(true);
          }
      }
      

      Main

      package com.hyl.sams.view;
      /**
       * @author hyl
       * @version 1.0
       * @date 2022/10/14-10:29
       *  启动类
       */
      public class Main {
          public static void main(String[] args) {
              //窗体美化
              try {
                  for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                      if ("Nimbus".equals(info.getName())) {
                          javax.swing.UIManager.setLookAndFeel(info.getClassName());
                          break;
                      }
                  }
              }catch(Exception e) {
                  System.out.println(e);
              }
              new View1();
          }
      }
      

      六、代码获取

      私信博主加qq

      源码加配套软件:15元

      学生成绩管理系统(JAVA,在这里插入图片描述,第10张学生成绩管理系统(JAVA,在这里插入图片描述,第11张

      举例:maven安装说明(怎么配置写的很详细,不清楚,还可以问我)

      学生成绩管理系统(JAVA,在这里插入图片描述,第12张

      如果:需要远程控制操作的25元(包配置+包运行+大作业文档docx)。

      非诚勿扰,多谢!!!

      最开始博主是免费公开的,也有同学私信,加博主好友,博主都是免费给远程操作,讲解的,有时候一弄就好几个小时,博主也是个学生,也有好多事情要做。而小伙伴们相信我,来找我,我也不好拒绝,但是人一多我就忙不过来,而且我的时间也没了,所以… 还请大家见谅。(代码和资源也是我费力搞的,所以后边有谁需要这个了,就按上面的来,实在不好意思,不好意思!)

      七、心得总结

      嗯,首先说声抱歉啊!上述代码我并没有全部展示(这个我上面说了,是拿来当软工大作业的,我们大概到12月份左右才考核。所以我怕到时候尴尬,就不放全部了,有需要的可以私我),但是大部分比较重要的上述代码都包含了,剩下的那些思路跟上面是一样,没啥技术含量。

      • 这个是本菜鸟自己纯纯手写的,没啥难度就是JavaGui界面编程(组件的拼装+组件监听),外加上一些基本的mysql增删改查语句。难一点的就是与数据库建立上连接,也就是常说的JDBC。
      • 这个写法我也是借鉴了韩顺平老师的满汉楼小系统,模仿着他的思路。(有兴趣的可以B站了解一下,韩老师的java入门课,真的很详细)。
      • 最后,希望我们都可以做到像欧阳修的《卖油翁》中的老翁一样(我亦无他 ,唯手熟尔)。