
简介面向Java初学者与课程设计学生这份学生信息管理系统项目基于EclipseMySQL开发实现登录注册并按管理员、学生、教师三种身份划分权限。管理员和教师可对学生信息及成绩进行增删改查学生仅可查询角色边界清晰是理解用户权限控制与简单业务分层的不错示范。压缩包共44个文件以17个Java源码和18个class文件为主另含两个源码zip、两个界面布局jar包、图片与工程配置文件整体仅616KB导入Eclipse即可查看运行。当前已有6474人学习浏览说明该练手项目在初学群体中拥有较高参考度。通过阅读和修改源码可掌握JDBC连接MySQL、Swing窗口搭建、基础模块组织方式以及围绕学生和成绩两套数据完成CRUD操作的完整思路适合以此为基础扩展成课程设计或毕业设计雏形。1. 一个 Java 学生信息管理系统eclipseMySQL到底在练什么不只是一份课设代码很多人的学生信息管理系统不是写不出来而是卡在第一步项目在别人电脑上是好的到自己这里一跑就报ClassNotFoundException或者Communications link failure。这也是为什么这类课设题目常年排在搜索榜靠前的位置。简单说Java学生信息管理系统eclipseMySQL就是一个用 Swing 写界面、用 JDBC 操作 MySQL 的桌面 CRUD 程序登录、学生信息的增删改查、按学号或姓名查一条数据。适合谁一是正在做课设或毕设的学生二是想把 JDBC 从零散语法落到一个完整项目里的 Java 初学者。下面按我自己的做法从版本选型、建库脚本、代码实现一直讲到几个常见的翻车点全部是可复现的路径。2. 环境选型先过一遍JDK、eclipse 与 MySQL 的版本组合怎么定2.1 为什么是这个技术栈Swing 界面 JDBC 是最稳的课设组合先说一个关键判断这个标题指向的是 JavaSE 桌面程序不是 Web 项目。别拿着 JSP/Servlet 的教程往上套那样要额外配置 Tomcat、web.xml、端口冲突环境问题比代码问题还多。桌面版的优点是启动简单一个main方法拉起登录窗口MySQL 负责存数据JDBC 负责搭桥验收时演示路径短。真正花时间的不是业务逻辑而是三个环境件的版本匹配。JDK 方面我用得最多的是 JDK 8 或 JDK 11配 2020 年之后的 eclipse 版本都很顺如果你装了 JDK 21建议优先考虑 Temurin 这类国内镜像下载的发行版然后确认 eclipse 版本足够新太老的 eclipse 打开 JDK 21 编译的工程会报 Unsupported class version。MySQL 方面5.7.44 和 8.0 都常见但两者在驱动配置上有明显差异这一点放到 2.3 详细说。给一张我常用的环境清单组件推荐版本理由JDK1.8 或 11稳定、eclipse 兼容性好、课设验收环境常见eclipse2021-09 及以后对高版本 JDK 支持更好自带 WindowBuilder 插件安装入口MySQL5.7.44 或 8.0.x两者皆可但驱动类名和连接参数不同JDBC 驱动mysql-connector-java 5.1.49配 5.7或 8.0.x配 8.0版本不匹配是最常见的启动即报错原因这套组合的另一个优势是你只需要装一个 eclipse不需要额外装 Tomcat、Maven 或 Spring 全家桶。对做课程设计的人来说环境越少翻车点越少。很多人在网上搜「eclipse 安装教程」「mysql 安装教程」时会发现教程之间互相矛盾——其实大部分矛盾都出在版本上先定版本再动手比照着教程一步步复制要靠谱得多。2.2 eclipse 导入别人项目的两种方式与 JDK 匹配检查拿到一份「Java学生信息管理系统」源码包时最常见的是别人已经建好的 eclipse 工程目录里面有.project和.classpath文件。导入方式有两种如果你的工程目录就在 eclipse 的 workspace 里用 File - Import - General - Existing Projects into Workspace直接选中目录即可如果你把代码下载到了任意位置也可以先复制进 workspace 再导入避免路径里带中文或空格带来的编译问题。导入后先不要急着点 Run做两件事。第一件右键项目 - Properties - Java Build Path - Libraries确认 JRE System Library 指向的本机 JDK和你实际安装的一致如果显示的是不可用的路径Remove 后重新 Add Library - JRE System Library。第二件右键项目 - Properties - Resource把 Text file encoding 设为 UTF-8这一步能提前避开后面中文乱码的一半问题。还有一个小习惯导入后立刻 Project - Clean 一次让 eclipse 重新编译全部源码很多「代码没问题但就是报错」的情况其实是增量编译缓存了旧的 class 文件。如果 Run 时报错提示「找不到或无法加载主类」先检查 Run Configuration 里的 Main class 是否指向了带main方法的类比如view.LoginFrame同时确认项目是否被 eclipse 正确识别为 Java 工程。这个报错在热词里还有另一个变体找不到或无法加载主类 org.apache.catalina.startup.bootstrap这类报错几乎都是把 Web 项目的 Tomcat 启动类当成 Java 主类来跑了确认你的工程是普通 Java 项目而不是 Dynamic Web Project 即可绕开。2.3 MySQL 5.7.44 与 8.0 的差异先定版本再选驱动MySQL 版本的选择直接决定两行代码驱动类名和 URL 参数。MySQL 5.7 时代JDBC 驱动类名是com.mysql.jdbc.Driver连接串写jdbc:mysql://localhost:3306/student_db就行到了 MySQL 8.0驱动类名变成com.mysql.cj.jdbc.Driver并且连接串里如果不带serverTimezoneAsia/Shanghai会直接报时区错误。更隐蔽的是认证插件差异8.0 默认用caching_sha2_password老版本驱动连上去会报Authentication plugin caching_sha2_password cannot be loaded解决方法是换 8.0.x 的驱动而不是去改 MySQL 的认证方式。安装方面5.7.44 的常见做法是用解压版把 zip 包解压到D:\mysql-5.7.44-winx64手动新建my.ini再用管理员权限执行mysqld --initialize-insecure最后net start mysql启动服务。8.0 的安装包通常自带安装向导但同样要注意bin目录有没有加进系统 PATH否则命令行里敲mysql -uroot -p会提示命令不存在。装好后先用SELECT VERSION();确认版本再决定你的DBUtil里写哪个驱动类名这一步能省下后面一整晚的排查时间。这里给一个判断口诀表格里写没写 MySQL 版本就看驱动 jar 的版本和数据库版本是否对齐对齐之后报错率会立刻下降一半。JDBC 驱动 jar 不需要额外找第三方渠道MySQL 官网下载页和 Maven 中央仓库都有下载时注意看文件名里的版本号别拿一个 5.1.49 去连 8.0 的库。3. 数据库设计到连接建库建表 SQL 与 JDBC 连接串的 5 个参数3.1 表结构设计学生表加管理员表字段按「够用但留扩展」来学生信息管理系统的核心数据就一张学生表外加一张管理员表用于登录。设计原则是「够演示、能扩展、不过度设计」不要一上来就加外键和触发器课设阶段外键在插入数据顺序不对时会变成第一个报错源头但主键、唯一键、默认值这些基础约束要齐全这是答辩时能讲清楚的加分项。学生表我一般设这几个字段id作为自增主键student_no作为学号并加唯一索引业务上不允许重复然后是姓名、性别、年龄、专业、电话和创建时间。性别用VARCHAR(4)而不是TINYINT是为了让 JTable 直接显示「男/女」而不是 1 和 0年龄用INT加默认值 18创建时间用DATETIME DEFAULT CURRENT_TIMESTAMP插入时不用手动赋值。管理员表只需要id、username、password三列课设阶段密码明文存储可以接受但你要知道这在生产环境是绝对不行的。字段设计还牵涉到后面代码里的一次性对齐问题Java 实体类的属性名、SQL 里的列名、Swing 表格的表头三者最好从一开始就统一。比如实体类叫studentNoSQL 列叫student_no到时候ResultSet.getString(student_no)没问题但表头要显示「学号」就得另写一层映射这些混乱会在地图式翻车现场一起爆发所以设计表时顺手把注释写清楚能省很多事。3.2 建库建表 SQL 脚本在命令行直接跑通的版本下面是建库建表脚本直接在 MySQL 命令行里执行即可CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE student_db; DROP TABLE IF EXISTS student; CREATE TABLE student ( id INT NOT NULL AUTO_INCREMENT COMMENT 主键, student_no VARCHAR(20) NOT NULL COMMENT 学号, name VARCHAR(50) NOT NULL COMMENT 姓名, gender VARCHAR(4) DEFAULT 男 COMMENT 性别, age INT DEFAULT 18 COMMENT 年龄, major VARCHAR(50) DEFAULT COMMENT 专业, phone VARCHAR(20) DEFAULT COMMENT 电话, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, PRIMARY KEY (id), UNIQUE KEY uk_student_no (student_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生表; DROP TABLE IF EXISTS admin; CREATE TABLE admin ( id INT NOT NULL AUTO_INCREMENT COMMENT 主键, username VARCHAR(30) NOT NULL COMMENT 用户名, password VARCHAR(50) NOT NULL COMMENT 密码, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT管理员表; INSERT INTO admin (username, password) VALUES (admin, 123456);这段脚本里有三个细节值得说。第一utf8mb4而不是utf8因为utf8在 MySQL 里最多存 3 字节遇到生僻字或 emoji 会直接报错utf8mb4才是完整的 UTF-8第二UNIQUE KEY uk_student_no保证学号不重复这会在 JDBC 插入重复数据时抛异常正好被我们捕获后弹出提示第三DROP TABLE IF EXISTS适合反复调试但生产环境千万别这么写会清掉已有数据。执行方式可以是在命令行里mysql -uroot -p student.sql也可以复制到 Navicat 或 DBeaver 的查询窗口里整段执行。建完表后顺手跑两行验证USE student_db;后DESC student;看看字段结构SELECT * FROM admin;确认初始管理员账号已经插入。先把表结构验证好后面 Java 代码跑不通时你就有了一个确定的排查边界问题要么在 SQL 层要么在 JDBC 层不会两边一起猜。3.3 JDBC 工具类连接串里的 encoding、useSSL、serverTimezone写一个DBUtil类把所有连接相关的参数集中管理。这是我反复用过的最简版本package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBUtil { private static final String DRIVER com.mysql.cj.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/student_db ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/Shanghai; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException ignored) {} } if (stmt ! null) { try { stmt.close(); } catch (SQLException ignored) {} } if (conn ! null) { try { conn.close(); } catch (SQLException ignored) {} } } }连接串里的 5 个参数逐个说明。useUnicodetrue和characterEncodingutf8是处理中文乱码的第一道关它们告诉 MySQL 驱动用 UTF-8 编码传输字符串useSSLfalse是因为本地开发没有配置 SSL 证书不关掉会看到一串 SSL 警告serverTimezoneAsia/Shanghai是 MySQL 8.0 的必填项不写会报时区错误。最后两个参数是 URL 里的用户信息和密码注意这里的账号密码必须和 MySQL 里实际能登录的一致我见过太多人改了数据库密码却忘记改这个常量。这段代码里的static块会在类加载时执行一次驱动注册Class.forName的作用是让驱动类被 JVM 加载早期的 JDBC 规范需要这样手动注册现在虽然 DriverManager 会自动发现驱动但保留这行兼容性更好。close方法把三个资源的关闭逻辑收敛到一个地方调用方不用每个方法里都写三遍 try-catch。注意close的顺序先关ResultSet再关Statement最后关Connection反了会报连接泄漏的警告。驱动 jar 的加载也要确认右键项目 - Build Path - Add External JARs找到你的mysql-connector-java-8.0.x.jar。只把 jar 复制进项目文件夹是不够的eclipse 不会自动把它加入编译路径这也是新手最容易困惑的一点。4. 代码实现从登录窗口到学生信息增删改查的完整链路4.1 DAO 层PreparedStatement 为什么不能省DAO 层是连接数据库和界面之间的桥梁。一个常见错误是直接在按钮事件里写 SQL这样代码会膨胀到无法维护按我习惯的做法把每个数据操作封装成一个方法界面只调用方法名。先写实体类Student属性对应表字段再写StudentDao每个方法负责一条 SQL 的执行和结果转换。下面是StudentDao里最核心的增删改查方法注意里面全部用的是PreparedStatementpackage dao; import java.sql.*; import java.util.ArrayList; import java.util.List; import util.DBUtil; import entity.Student; public class StudentDao { public boolean addStudent(Student s) { String sql INSERT INTO student(student_no, name, gender, age, major, phone) VALUES(?,?,?,?,?,?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, s.getStudentNo()); ps.setString(2, s.getName()); ps.setString(3, s.getGender()); ps.setInt(4, s.getAge()); ps.setString(5, s.getMajor()); ps.setString(6, s.getPhone()); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } } public ListStudent findAll() { String sql SELECT id, student_no, name, gender, age, major, phone FROM student; ListStudent list new ArrayList(); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { while (rs.next()) { Student s new Student(); s.setId(rs.getInt(id)); s.setStudentNo(rs.getString(student_no)); s.setName(rs.getString(name)); s.setGender(rs.getString(gender)); s.setAge(rs.getInt(age)); s.setMajor(rs.getString(major)); s.setPhone(rs.getString(phone)); list.add(s); } } catch (SQLException e) { e.printStackTrace(); } return list; } }代码里的try-with-resources语法是 Java 7 以后的标准写法它会在 try 块结束后自动关闭Connection、PreparedStatement和ResultSet这比手动在 finally 里写close更不容易漏。executeUpdate()返回受影响的行数大于 0 说明插入成功。findAll里while (rs.next())逐行把结果集的列映射到Student对象然后放进List返回。这里手工映射看起来很啰嗦但课设答辩时这是讲得最清楚的部分如果用 MyBatis 或者反射工具一键映射反而要解释半天的框架原理。为什么坚持用PreparedStatement而不是字符串拼接第一个理由是防注入如果写成SELECT * FROM student WHERE name name 用户在文本框里输入 OR 11就能绕过查询条件第二个理由是参数类型setInt(4, s.getAge())会让 JDBC 帮你做类型检查而拼字符串时age传进去的是字符串MySQL 端可能隐式转换一旦有非数字字符就直接 SQL 语法错误。第三个理由是可读性长 SQL 里一排?配合setXxx的参数说明比你数十几个加号要直观得多。4.2 登录窗口与主界面JTable 刷新的最小实现登录窗口用 Swing 的JFrame实现。核心逻辑是取文本框里的用户名和密码查 admin 表匹配成功则打开主窗口并关闭登录窗口。注意这里同样用PreparedStatementpublic boolean checkLogin(String username, String password) { String sql SELECT id FROM admin WHERE username? AND password?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { return rs.next(); } } catch (SQLException e) { e.printStackTrace(); return false; } }返回rs.next()为 true 表示查到了记录也就是用户名密码都对。登录成功后创建MainFrame里面放一个JTable展示学生列表。JTable的数据模型用DefaultTableModel它的好处是可以动态增删行DefaultTableModel model new DefaultTableModel( new Object[]{ID, 学号, 姓名, 性别, 年龄, 专业, 电话}, 0); JTable table new JTable(model);这里的第二个参数0表示初始行数为空之后调用model.addRow(new Object[]{...})就能一行行加数据。刷新列表的方法通常是先model.setRowCount(0)清空旧数据再遍历dao.findAll()的结果逐行加入这样每次增删改之后调用同一个方法就能保持界面和数据库同步。用JScrollPane把表格包起来否则表头在窗口尺寸变化时不会自动滚动。4.3 增删改查按钮的逻辑选中行、回填与刷新主界面上放四个按钮添加、修改、删除、刷新。添加按钮的逻辑是读文本框输入组装Student对象调dao.addStudent成功后刷新表格并清空输入框private void addStudent() { String studentNo txtNo.getText().trim(); String name txtName.getText().trim(); if (studentNo.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(this, 学号和姓名不能为空); return; } Student s new Student(); s.setStudentNo(studentNo); s.setName(name); s.setGender(cmbGender.getSelectedItem().toString()); s.setAge(Integer.parseInt(txtAge.getText().trim())); s.setMajor(txtMajor.getText().trim()); s.setPhone(txtPhone.getText().trim()); if (dao.addStudent(s)) { loadData(); clearInput(); } else { JOptionPane.showMessageDialog(this, 添加失败请检查学号是否重复); } }注意两个细节第一getText().trim()去掉首尾空格避免用户手滑打了一个空格导致数据看起来是空的实际不是第二Integer.parseInt有可能抛NumberFormatException如果你不想让界面崩溃可以给它包一层 try-catch或者用JFormattedTextField限制输入格式。修改按钮的难点在「回填」先table.getSelectedRow()拿到选中行再从模型里取出该行的 ID最后把其他列的值填回输入框用户改完点保存时按 ID 更新 SQL 里的 WHERE 条件。删除按钮则简单一些弹出确认框后按 ID 执行 DELETE然后刷新表格。loadData()方法要写成独立的私有方法而不是散落在每个按钮事件里这样每次调用时先model.setRowCount(0)再用findAll()重新填充能确保三个按钮共用一套刷新逻辑。到这里一个「登录 - 主界面 - 增删改查」的完整闭环就通了接下来要做的不是加功能而是把运行中最容易踩的坑提前排一遍。5. 避坑eclipse 连 MySQL 最常见的 5 个翻车现场5.1 启动与加载类问题找不到主类、MySQL 服务起不来、驱动没加载现象一在 eclipse 里点 Run控制台报找不到或无法加载主类 org.apache.catalina.startup.bootstrap或者项目里自己的类名报找不到或无法加载主类 view.LoginFrame。原因前一个报错是因为把 Tomcat 的启动类填进了 Java Application 的运行配置后一个则通常是工程的编译输出目录里 class 文件缺失或损坏。解决方式右键项目 - Run As - Run Configurations在 Main class 一栏手动填view.LoginFrame或者你实际的主类全限定名然后 Project - Clean 清理重新编译一次再 Run 基本就好。现象二命令行执行net start mysql时提示「服务正在启动 . . . 服务无法启动服务没有报告任何错误」。原因MySQL 安装目录下的my.ini配置错误常见是basedir和datadir路径写错、路径里的反斜杠没有转义或者 data 目录权限不足。解决打开 MySQL 安装目录下的data文件夹找一个主机名.err结尾的日志文件拉到最底部看最后的 ERROR 行它会明确告诉你哪一项配置出问题如果你实在不想排查在确认没有重要数据的前提下删掉 data 目录重新执行mysqld --initialize-insecure生成一个全新的数据目录这是最后的后悔药但动手前务必先备份已有库。现象三运行程序直接抛ClassNotFoundException: com.mysql.jdbc.Driver。原因驱动 jar 没有加入 Build Path或者你把 MySQL 8.0 的驱动类名写成了老版本的com.mysql.jdbc.Driver。解决右键项目 - Build Path - Configure Build Path - Libraries - Add External JARs选择你的驱动 jar然后回到代码检查DBUtil里的DRIVER字符串8.0 对应的是com.mysql.cj.jdbc.Driver而不是com.mysql.jdbc.Driver这两个类名长得像但差一个cj写错就只能看着报错干瞪眼。5.2 连接与数据问题时区报错、拒绝访问、中文乱码现象四代码里getConnection()抛出Communications link failure或Access denied for user rootlocalhost。原因前者是 MySQL 服务根本没启动、端口不是默认的 3306或者连接串里主机名写错后者是DBUtil里的账号密码和 MySQL 实际设置不一致。解决这个问题有一个固定的排查顺序先打开命令行输入mysql -uroot -p用同样的账号密码试试能不能登录命令行能进问题就在代码的连接串命令行进不去问题就在 MySQL 的账号权限或服务状态。按这个顺序走十分钟内能定位。现象五程序连上数据库了但读写中文全是乱码或者插入中文时数据库里显示??。原因这是三处编码没对齐——数据库没建成utf8mb4、连接串没带characterEncodingutf8、eclipse 工程文件本身不是 UTF-8 编码三处缺一不可。解决建库语句带上DEFAULT CHARACTER SET utf8mb4连接串里加useUnicodetruecharacterEncodingutf8eclipse 的 Window - Preferences - General - Workspace 把 Text file encoding 改成 UTF-8然后重新保存所有源码文件。做完这三步乱码就从「玄学」变成了确定性问题再遇到也能快速判断是哪一层没对齐。还有一类和连接相关的问题值得单独提醒MySQL 8.0 默认的认证插件是caching_sha2_password如果你用了 5.1.x 的老驱动登录时会报Authentication plugin caching_sha2_password cannot be loaded。解决办法不是去改 MySQL 的default_authentication_plugin而是直接换 8.0.x 的驱动 jar两行代码都不用动。排查这类问题时要记得看完整堆栈别只看第一行——很多真正的原因藏在Caused by里。6. 再往前一步模糊查询、分页思路与验收前的三条自查6.1 按姓名或学号模糊查询LIKE 参数化写法基础增删改查做完后加一个按关键字的模糊查询是性价比最高的进阶功能。实现方式是在StudentDao里加一个方法public ListStudent findByKeyword(String keyword) { String sql SELECT id, student_no, name, gender, age, major, phone FROM student WHERE name LIKE ? OR student_no LIKE ?; ListStudent list new ArrayList(); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { String like % keyword %; ps.setString(1, like); ps.setString(2, like); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { // 同 findAll 的映射逻辑 } } } catch (SQLException e) { e.printStackTrace(); } return list; }注意%通配符是加在参数值里的而不是拼进 SQL 字符串这样PreparedStatement的防注入能力才不会失效。界面上加一个搜索框和搜索按钮按钮事件里取关键字调用这个方法再把返回结果填充到表格模型。这个小功能在答辩时很加分因为它体现了你对用户场景的理解而不只是完成了必做功能。6.2 分页显示LIMIT 加页码变量的思路分页是另一个常见追问点。思路很简单SQL 语句加LIMIT ?, ?第一个参数是偏移量(page - 1) * size第二个参数是每页行数sizeDAO 方法签名可以设计成findByPage(int page, int size)。界面放「上一页」「下一页」两个按钮维护一个当前页码变量翻页时重新调用 DAO 并刷新表格。这不是什么高深技术但能讲清楚 LIMIT 的两个参数含义就说明对 SQL 执行机制有基本理解。6.3 验收自查表先确认这三项再交作业交作业或答辩前按下面这张表自查一遍能替你挡住大多数现场翻车检查项操作通过标准换环境可运行换一台只有 JDKMySQL 的电脑从导入工程到跑起来15 分钟内完成不依赖本机特殊配置依赖服务异常提示先关掉 MySQL 服务再点登录界面弹出中文错误提示而不是控制台堆栈中文数据全程正确新增一条含中文的学生记录重启程序再看列表、修改回填、数据库存储均无乱码我记得自己第一次做这个题目改完代码直接点 Run对着控制台里那一大串异常发了好一阵呆后来慢慢养成的习惯是先开 MySQL 服务再用命令行查一遍数据最后才启动界面。这个顺序看着笨但它把「代码问题」和「环境问题」隔离开了。希望帮到你。本文还有配套的精品资源点击获取