0


学生成绩管理系统(JAVA_GUI+Mysql)

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

文章目录


一、功能展示

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

代码获取(两个分支,两种版本):点击获取
白瞎了,大作业变web了,啊啊~~

二、技术选型

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表中的密码做校验
输入新密码(上述旧密码与表中一致,实现修改)

成绩查询:根据学号查询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表中的数据


五、代码实现

包结构:
在这里插入图片描述
lib包
在这里插入图片描述
dao包
在这里插入图片描述
domain包
在这里插入图片描述
service包
在这里插入图片描述
utils包
在这里插入图片描述
View包
在这里插入图片描述
还有一个重要的properties文件(直接放在src层级下,就是说与上述包是同一等级的)
在这里插入图片描述

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 intupdate(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 <T>
     * @return
     */
    public <T> List<T>queryMulti(String sql, Class<T> tClass, Object... parameters){
        Connection connection=null;
        try {
            connection= Jdbc_Druid_Utils.getConnection();return qr.query(connection, sql, new BeanListHandler<T>(tClass), parameters);}catch(SQLException e){
            throw new RuntimeException(e);}finally {
            Jdbc_Druid_Utils.Close(null,null,connection);}}/**
     * 返回单行
     * @param sql
     * @param tClass
     * @param parameters
     * @param <T>
     * @return
     */
    public <T> T querySingle(String sql, Class<T> tClass, Object... parameters){
        Connection connection=null;
        try {
            connection= Jdbc_Druid_Utils.getConnection();return qr.query(connection, sql, new BeanHandler<T>(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 voidsetSno(String sno){
        Sno = sno;}

    public String getSname(){return Sname;}

    public voidsetSname(String sname){
        Sname = sname;}

    public String getCname(){return Cname;}

    public voidsetCname(String cname){
        Cname = cname;}

    public intgetGrade(){return Grade;}

    public voidsetGrade(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<sdept>findAllSName(){
        List<sdept> 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 intfindSID(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 intfindCID(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<Course>findCourse(){
        List<Course> list = dao.queryMulti("select * from course", Course.class);return list;}/**
     * 查询返回院系列表
     * @return
     */
    public List<sdept>findAllSName(){
        List<sdept> list = dao.queryMulti("select * from sdept", sdept.class);return list;}/**
     * 无学号情况下
     * 所有院系所有课程
     * @return
     */
    public List<StuSelectPlus>findAllSc(){
        List<StuSelectPlus> 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<StuSelectPlus>findAllSc1(String cname){
        List<StuSelectPlus> 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<StuSelectPlus>findAllSc2(String sdept_name){
        List<StuSelectPlus> 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<StuSelectPlus>findAllSc3(String sdept_name,String Cname){
        List<StuSelectPlus> 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<StuSelectPlus>findGrade1(String sno){
        List<StuSelectPlus> 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<StuSelectPlus>findGrade2(String sno,String cname){
        List<StuSelectPlus> 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 staticvoidClose(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);}elseif(a==2){
            p.setFont(font);}elseif(a==3){
            p.setForeground(Color.CYAN);
            p.setFont(font);}elseif(a==4){
            p.setForeground(Color.RED);
            p.setFont(font2);}elseif(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);}elseif(a==2){
            p.setForeground(Color.RED);
            p.setFont(font2);}elseif(a==3){
            p.setForeground(Color.RED);
            p.setFont(font);}elseif(a==4){
            p.setFont(font);}return p;}/**
     * 设置下拉框风格
     * @param x
     * @return
     */
    public static JComboBox<String>setMyJComboBox(int x){//下拉框
        JComboBox<String> jcb = new JComboBox<String>();//设置组件的宽和高
        Dimension dim = new Dimension(200,30);
        jcb.setPreferredSize(dim);if(x==1){
            jcb.setFont(font);}elseif(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;}elseif("女".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;}elseif(!"学院".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 voidactionPerformed(ActionEvent e){//关闭窗口释放屏幕资源
                System.exit(0);}});
        b2.addActionListener(new ActionListener(){
            @Override
            public voidactionPerformed(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 voidactionPerformed(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);}elseif(!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);}//与数据库信息比较elseif((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();}elseif("2002".equals(s)){//打开教师页面
                            View1.loginName=myUser.getUsername();
                            new View4();}elseif("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 voidactionPerformed(ActionEvent e){//关闭窗口释放屏幕资源
                System.exit(0);}});//注册页面
        jb3.addActionListener(new ActionListener(){
            @Override
            public voidactionPerformed(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 voidactionPerformed(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);}elseif(!ValidationUtil.checkPassword(trim)||!ValidationUtil.checkPassword(trim1)){
                    JOptionPane.showMessageDialog(null,"密码格式不正确","message", JOptionPane.ERROR_MESSAGE);}elseif(!pwd.equals(trim1)){
                    JOptionPane.showMessageDialog(null,"输入的旧密码不正确","message", JOptionPane.ERROR_MESSAGE);}elseif(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 voidactionPerformed(ActionEvent e){// 将查询获得的记录数据,转换成适合生成JTable的数据形式//count为数据库查询的记录数
                List<StudentSelect> 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 staticvoidmain(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();}}

六、心得总结

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

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

本文转载自: https://blog.csdn.net/m0_58730471/article/details/127421582
版权归原作者 想要登顶的菜鸟 所有, 如有侵权,请联系我们删除。

“学生成绩管理系统(JAVA_GUI+Mysql)”的评论:

还没有评论