提示:该系统是基于Java界面编程+mysql的
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 的计算结果向用户提供相应响应。
该小系统纯纯自己写的,表关系也是自己在写的过程中,不断试错完善的,如有不对的地方,请私信我,咱么共同学习进步
建库建表语句(该版本是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表中的密码做校验
输入新密码(上述旧密码与表中一致,实现修改)
教师界面
欢迎提示语(欢迎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表中的数据
包结构:
lib包
dao包
domain包
service包
utils包
View包
还有一个重要的properties文件(直接放在src层级下,就是说与上述包是同一等级的)
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 ListfindAllSName(){ 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 ListfindCourse(){ 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 JComboBoxsetMyJComboBox(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为数据库查询的记录数 Listlist = 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元
举例:maven安装说明(怎么配置写的很详细,不清楚,还可以问我)
如果:需要远程控制操作的25元(包配置+包运行+大作业文档docx)。
非诚勿扰,多谢!!!
最开始博主是免费公开的,也有同学私信,加博主好友,博主都是免费给远程操作,讲解的,有时候一弄就好几个小时,博主也是个学生,也有好多事情要做。而小伙伴们相信我,来找我,我也不好拒绝,但是人一多我就忙不过来,而且我的时间也没了,所以… 还请大家见谅。(代码和资源也是我费力搞的,所以后边有谁需要这个了,就按上面的来,实在不好意思,不好意思!)
嗯,首先说声抱歉啊!上述代码我并没有全部展示(这个我上面说了,是拿来当软工大作业的,我们大概到12月份左右才考核。所以我怕到时候尴尬,就不放全部了,有需要的可以私我),但是大部分比较重要的上述代码都包含了,剩下的那些思路跟上面是一样,没啥技术含量。
- 这个是本菜鸟自己纯纯手写的,没啥难度就是JavaGui界面编程(组件的拼装+组件监听),外加上一些基本的mysql增删改查语句。难一点的就是与数据库建立上连接,也就是常说的JDBC。
- 这个写法我也是借鉴了韩顺平老师的满汉楼小系统,模仿着他的思路。(有兴趣的可以B站了解一下,韩老师的java入门课,真的很详细)。
- 最后,希望我们都可以做到像欧阳修的《卖油翁》中的老翁一样(我亦无他 ,唯手熟尔)。