
简介这是一份基于Java语言、MySQL数据库与控制台交互的学生信息管理系统完整项目适合Java SE课程设计或初学者参考学习。系统为单管理员模式登录后可在控制台完成学生信息的增加、删除、修改和查询数据持久化到MySQL目录与代码层次清楚便于理解JDBC连接、SQL操作和基础CRUD流程。资源包共33个文件大小约37.67MB主要包含6个Java源码、6个class字节码、3个SQL建库脚本、3个MySQL驱动jar包、1份技术说明书docx、1份运行必读txt以及1个演示视频mp4和若干运行截图png覆盖从代码到运行说明的完整链路。Eclipse/MyEclipse工程配置齐全导入后可直接运行。已有66人学习下载。配套演示视频和登录、增删改查截图可帮助读者快速复现整个管理系统完成从建库、连接、功能实现到调试排错的全流程体验对课程设计、期末实训和简历项目都颇具参考价值。1. 用 Java 控制台 MySQL 做学生信息管理系统为什么这组合是课设里最稳的选择期末和毕业设计季“学生信息管理系统”是出现频率最高的题目。很多人一上来就选 Swing 拖界面拖到一半发现布局调不动换 JavaWeb又卡在 Tomcat 和版本冲突上。标题里的“控件台”其实就是控制台程序Console Application——没有花哨界面只靠命令行菜单和 JDBC 操作 MySQL。这个组合看着简陋却是我在课程设计里最推荐的选择。它把 JDBC 连接、SQL 注入、事务回滚这些老师必问的点全摊开摆在代码里。这篇文章从一个最小可用系统讲起覆盖建库、连接、登录、增删改查、事务最后是常见报错和演示视频的录制脚本。刚学完 Java 基础的人能跟着跑通已经写过简单 JDBC 的人也能补齐事务和打包这两块短板。2. 先把技术底座立住JDBC 选型、项目骨架与建库脚本2.1 为什么控制台程序也要拆成 DBUtil、DAO、Main 三层很多初学者的第一个念头是控制台程序不就一个 main 方法从头写到尾吗是能跑但维护不了。学生信息管理系统至少要支持登录、查列表、增删改每个功能都涉及连接、SQL、结果集处理。如果全部堆在 main 里一个方法写到 300 行改一个查询条件要上下翻半天答辩时老师问“加一个年龄区间的筛选功能你改哪里”你很难当场指出来。常见做法是拆三层DBUtil只负责拿到 Connection是全局唯一访问数据库的入口。StudentDao每一个方法对应一条 SQL只做数据库读写不做菜单交互。Main只处理 Scanner 输入的菜单循环收到用户指令后调用 Dao 方法。这样拆完之后Main 里看不到任何jdbc:mysql开头的字符串也不会出现 Connection 变量满天飞的情况。层与层之间通过实体类传值后续想换成 Swing 界面或者把 Dao 的 SQL 换成 MyBatisMain 不用动Dao 内部替换就行。控制台程序意味着没有 Web 容器不需要部署 Tomcat也没有前端页面。它把“数据怎么进数据库、怎么从数据库拿出来验证”这件事放到最大这正好是课程设计考察的重点也是面试里 Java 基础部分最喜欢追问的地方。给实体类、Dao 再加一层 Service 也可以但课设就十个功能不到的时候Service 往往只是把 Dao 方法转一圈徒增代码量我一般不建议加。什么时候加你准备往 Spring Boot 方向扩展、想把它当简历项目写的时候再加不迟。2.2 Maven 坐标还是手动导入 jar两种驱动引入方式对比JDBC 连 MySQL 的第一步是拿到驱动包。现在主流是 MySQL 8.0.x驱动类名是com.mysql.cj.jdbc.Driver。引入方式有两种我倾向 Maven。用 Maven 的话在 pom.xml 里加dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version /dependency注意MySQL Connector/J 从 8.0.31 开始Maven 坐标从mysql:mysql-connector-java改成了com.mysql:mysql-connector-j。网上很多老教程还在写前者用起来容易解析出旧版本。如果你们老师指定 MySQL 5.7 环境驱动类名要用com.mysql.jdbc.Driver版本选mysql:mysql-connector-java:5.1.49这类配套版本。选哪个版本看你本机装的 MySQL 版本不要光照着抄。手动导入 jar 的场景也常见有些机房不能访问外网或者只给了离线 jar 包。操作是把 jar 放到项目根目录的 lib 文件夹IDEA 里右键 jar → Add as Library。这个方式对新手最直观坑也最明显换一台电脑classpath 配置经常丢运行时报ClassNotFoundException还不知道去哪查。Maven 只要 pom.xml 在依赖就在所以能用 Maven 就用 Maven。项目骨架长这样student-management/ ├── pom.xml ├── src/main/java/ │ └── com/course/stu/ │ ├── Main.java # 控制台菜单入口 │ ├── util/DBUtil.java # 连接工具类 │ ├── dao/AdminDao.java # 管理员登录 │ ├── dao/StudentDao.java # 学生增删改查 │ └── entity/Student.java # 学生实体类 └── src/main/resources/2.3 建库建表脚本字段类型、枚举和字符集一次到位数据库脚本是地基。字符集选 utf8mb4不要选 utf8因为 MySQL 的 utf8 最多存 3 字节存不下 emoji 和部分生僻字。课程设计的字符集问题经常在“姓名”这一栏翻车姓“”这种字在 utf8 库里直接存不进去。如果你还在按零散的 mysql 安装教程配环境装好后第一件事就是把下面这段脚本跑通。CREATE DATABASE IF NOT EXISTS student_db DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE student_db; CREATE TABLE admin ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password CHAR(32) NOT NULL COMMENT MD5 密文 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) NOT NULL UNIQUE COMMENT 学号, name VARCHAR(50) NOT NULL, gender ENUM(男,女) NOT NULL DEFAULT 男, age INT NOT NULL DEFAULT 18, class_name VARCHAR(50) NOT NULL COMMENT 班级, phone VARCHAR(20), create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; INSERT INTO admin(username, password) VALUES (admin, MD5(123456));参数说明gender用 ENUM省去在 Java 里做“0 表示男、1 表示女”的映射。如果觉得 ENUM 不够灵活用 TINYINT 加注释也完全没问题。student_no加 UNIQUE 约束从数据库层面保证学号不重复。这是学生信息管理系统里最重要的业务约束比在 Java 代码里循环判重靠谱得多。admin.password用 CHAR(32) 存 MD5 结果后面登录时 Java 侧把输入密码做一次 MD5 再比对。表引擎用 InnoDB。这是因为后面章节讲事务时MyISAM 不支持事务别用。执行脚本用命令行或 Navicat 都可以mysql -u root -p student_db.sql执行完用SHOW TABLES;确认三张表都在。在 Windows 上手动装 MySQL 8.0 后经常遇到“mysql 不是内部或外部命令”的报错这是没把 MySQL 的 bin 目录加进系统 PATH属于 java 环境配置和数据库环境配置叠加的经典问题。环境变量改完要重开命令行窗口才生效。3. 把 JDBC 连接和登录模块跑通DBUtil 与管理员认证3.1 DBUtil 连接参数逐个解释DBUtil 是所有功能的入口写错了后面全动不了。先给完整代码package com.course.stu.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/student_db ?useUnicodetruecharacterEncodingutf8 useSSLfalse serverTimezoneAsia/Shanghai allowPublicKeyRetrievaltrue; private static final String USER root; private static final String PASSWORD 你自己的密码; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL 驱动加载失败请检查 jar 包是否引入, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }逐个说参数为什么这么写useUnicodetruecharacterEncodingutf8和建库时的 utf8mb4 配套。漏掉这个控制台输入中文进库就变成问号。URL 里写characterEncodingutf8会自动映射到 utf8mb4这是 Connector/J 的默认行为。useSSLfalse本地开发关掉 SSL省去证书告警。生产环境才考虑开启。serverTimezoneAsia/ShanghaiMySQL 8.0 对时区极其敏感不写会报The server time zone value错误。有些教程让写serverTimezoneUTC能跑但create_time会比北京时间慢 8 小时。allowPublicKeyRetrievaltrue专门解决 MySQL 8.0 使用 caching_sha2_password 认证插件时第一次连接报Public Key Retrieval is not allowed。本地开发开着方便生产环境建议关。static 块里那句Class.forName其实是保留的老式写法。JDBC 4.0 之后驱动会自动注册不写也能连上。保留它的意义在于当 jar 包缺失时错误会在这里第一时间暴露而不是等到getConnection()时才抛出一堆看不懂的堆栈。这种“让错误早一点出现”的写法排查问题能省一半时间。3.2 登录认证的实现密文比对而不是明文比对登录模块的核心是用用户名和密码去 admin 表匹配。给 AdminDaopackage com.course.stu.dao; import com.course.stu.util.DBUtil; import java.security.MessageDigest; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class AdminDao { public static boolean login(String username, String password) { String md5Pwd md5(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, md5Pwd); try (ResultSet rs ps.executeQuery()) { return rs.next(); } } catch (SQLException e) { e.printStackTrace(); return false; } } private static String md5(String input) { try { MessageDigest md MessageDigest.getInstance(MD5); byte[] bytes md.digest(input.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : bytes) { sb.append(String.format(%02x, b)); } return sb.toString(); } catch (Exception e) { throw new RuntimeException(MD5 加密失败, e); } } }逻辑说明查询条件里的两个问号是占位符通过ps.setString按顺序传值。永远不要用字符串拼 SQL例如SELECT * FROM admin WHERE username username 。控制台输入一旦包含单引号就可能把 SQL 拼成注入句式。这是面试必问的安全问题也是老师最爱问的点。PreparedStatement 的预编译机制会让?处的值以参数形式传递不会还原成可拼接的 SQL 片段——这句话答辩时能当面讲清楚比写十个功能都加印象分。参数说明password 在 admin 表里存的是MD5(123456)的结果所以这里先把用户输入做一次同样的 md5再进 SQL 比对。为什么不在 SQL 里直接写WHERE passwordMD5(?)也可以但那样哈希在数据库端算应用层拿到明文的机会更早密文处理放 Java 侧更常见。另外要主动说明MD5 在真实生产环境不够安全应该用 BCrypt 加盐但课程设计用 MD5 能把“密码不能明文入库”这个原则讲清楚就行主动指出 MD5 局限反而是加分项。3.3 连接泄漏隐患try-with-resources 的正确用法注意 login 方法的写法Connection、PreparedStatement、ResultSet 都写在 try 后面的括号里。这是 Java 7 引入的 try-with-resources方法结束或者抛异常时三个资源会自动按逆序关闭不需要 finally 块。我见过大量课设代码是这样写的Connection conn null; Statement stmt null; try { conn DBUtil.getConnection(); stmt conn.createStatement(); // 业务代码 } catch (SQLException e) { e.printStackTrace(); } finally { // 要么忘了关要么关了半天还判空 }这种写法的大坑不是代码长而是很多人 finally 里只关 Connection漏掉 Statement 和 ResultSet或者关闭顺序写错。MySQL 默认最大连接数是 151控制台程序每次查询都不关连接连续操作二三十次就会报Too many connections重启程序才能恢复。答辩演示时当着老师的面翻车是最亏的。用 try-with-resources 能从代码结构上杜绝这个隐患这是 JDK 7 之后写 JDBC 的默认姿势没有例外。登录成功后Main 里用 boolean 变量接住 login 的返回值false 就继续循环让用户重试true 就进入学生信息管理菜单。这个流程不需要额外代码讲解控制台应用的最小骨架就一个 switch 加一个 while建议写的时候把菜单循环放到单独方法里别塞在 main 中免得 main 越来越长。4. 学生信息的增删改查与事务主功能区的可复现代码4.1 增改删的核心代码PreparedStatement 的 ? 参数与防 SQL 注入学生实体类先定义好字段package com.course.stu.entity; public class Student { private Integer id; private String studentNo; private String name; private String gender; private Integer age; private String className; private String phone; // 每个字段的 getter/setter 此处省略 }字段类型和 student 表一一对应。id 用包装类型Integer是为了让“数据库里没值”可以表示为 null而不会把 0 当有效数据。新增学生的 Dao 方法public boolean addStudent(Student s) { String sql INSERT INTO student(student_no, name, gender, age, class_name, 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.getClassName()); ps.setString(6, s.getPhone()); return ps.executeUpdate() 1; } catch (SQLException e) { e.printStackTrace(); return false; } }逻辑说明executeUpdate()返回受影响行数插入成功返回 1直接拿等号判断比if (rows 0)更干脆。PreparedStatement 的预编译机制让 SQL 骨架先送驱动解析特殊字符不会还原成可拼接的 SQL 片段这就是防注入的根因。修改和删除只是 SQL 换掉public boolean updateStudent(Student s) { String sql UPDATE student SET name?, gender?, age?, class_name?, phone? WHERE id?; // 同样 try-with-resourcesps.setString/setInt 按顺序设参executeUpdate() 1 } public boolean deleteStudent(int id) { String sql DELETE FROM student WHERE id?; // 同样 try-with-resources最后返回 executeUpdate() 1 }注意 update 条件用主键 id不要用student_no。学号虽然也建了唯一索引但一旦需求允许“学号录错后修改”学号作为修改条件就和业务矛盾了。delete 同理。这两个方法结构跟 addStudent 完全一样抄改时最容易出错的地方是参数顺序写错一个就全串位。4.2 查询列表与按学号搜索ResultSet 映射到实体类的写法查询是学生管理系统里最常用的操作列表查询代码public ListStudent queryAll() { String sql SELECT id, student_no, name, gender, age, class_name, phone FROM student ORDER BY id; ListStudent students 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.setClassName(rs.getString(class_name)); s.setPhone(rs.getString(phone)); students.add(s); } } catch (SQLException e) { e.printStackTrace(); } return students; }逻辑说明ResultSet 的游标初始位置在结果集第一行之前rs.next()每调用一次下移一行返回 false 表示没数据了所以while (rs.next())是遍历结果集的标准姿势。取值用列名而不是列下标能少踩两种坑SELECT 字段顺序一调整数字下标全错列名语义清晰代码可读性也高。按学号搜索复用同一个骨架只需要把 SQL 改成加WHERE student_no?再补一个ps.setString。模糊搜索按姓名查时用LIKE CONCAT(%, ?, %)注意不要写LIKE %?%——问号在引号里只是普通字符不是占位符。这个细节是新手最容易踩的 SQL 坑课设代码里十份有六份在这翻过车。4.3 批量操作要用事务setAutoCommit(false) 的提交与回滚单条增删改查都好办一旦涉及批量操作比如一键导入 50 个学生、按班级批量删除就必须用事务。不用事务时导入到第 25 条失败前 24 条已经落了库数据一半新一半旧事后对账能对到怀疑人生。public boolean batchInsert(ListStudent list) { Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); String sql INSERT INTO student(student_no, name, gender, age, class_name, phone) VALUES(?, ?, ?, ?, ?, ?); try (PreparedStatement ps conn.prepareStatement(sql)) { for (Student s : list) { ps.setString(1, s.getStudentNo()); ps.setString(2, s.getName()); ps.setString(3, s.getGender()); ps.setInt(4, s.getAge()); ps.setString(5, s.getClassName()); ps.setString(6, s.getPhone()); ps.addBatch(); } ps.executeBatch(); } conn.commit(); return true; } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); return false; } finally { if (conn ! null) { try { conn.setAutoCommit(true); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }逻辑说明setAutoCommit(false)之后每条 SQL 不会立即落盘而是进入当前事务的缓冲区。全部成功commit()一次性提交任何一条失败rollback()回滚到开始前状态。批处理还额外用了addBatch()/executeBatch()把多条 INSERT 打包发给服务端比逐条executeUpdate()少很多网络往返。注意 try-with-resources 在这里不覆盖 Connection因为事务要求一个 Connection 贯穿全部操作Connection 必须手动 close。PreparedStatement 仍然可以自动关闭它 close 不影响已提交的事务。事务能生效的前提是 InnoDB 引擎这也是建表脚本里写明 ENGINEInnoDB 的原因。如果不想手写这套也可以写 MySQL 存储过程配合事务但课设建议把事务写在 Java 里老师想看的是你对 JDBC 事务 API 的理解不是存储过程的调用。5. 常见问题排查与避坑驱动版本、认证插件、乱码与关键字这一章不贴长代码写我帮人调过无数遍课设后总结出的 5 个高频坑。每条都按“现象 → 原因 → 解决”的结构写可以直接对着查。5.1 驱动类找不到 ClassNotFoundException现象运行 DBUtil 的 static 块直接抛java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因jar 包没进 classpath。手动导入 jar 的项目最容易出现换了电脑或重开项目IDEA 的 Library 配置丢失Maven 项目则可能两个驱动坐标混用mysql:mysql-connector-java和com.mysql:mysql-connector-j同时存在依赖解析混乱。解决手动导入 jar 的检查 IDEA 的 Project Structure → Modules → Dependencies 里有没有 jar 记录Maven 项目删掉其中一个坐标。先跑mvn dependency:tree看依赖树实际解析出什么版本。最土也最有效的办法是删掉本地仓库对应目录重新拉很多诡异报错都是缓存导致的。5.2 Access denied 与 caching_sha2_password 认证失败现象连接时报Access denied for user rootlocalhost或者Public Key Retrieval is not allowed。原因前者八成是密码写错或者 root 的 host 限制不是 localhost后者是 MySQL 8.0 默认用 caching_sha2_password 认证插件而驱动版本太老或连接 URL 里少了allowPublicKeyRetrievaltrue。解决密码错误就去重置 root 密码ALTER USER rootlocalhost IDENTIFIED BY 新密码;然后FLUSH PRIVILEGES;。认证插件问题优先升级驱动到 8.0.x并在 URL 补参数。本地学习环境也可以把插件改回mysql_native_password但新驱动能解决的问题就别动插件配置免得给自己埋一个不兼容的雷。5.3 中文乱码库、表、连接三个位置都要 utf8mb4现象控制台输入“张三”数据库里查出来是“”或者数据库里是对的控制台读出来却是乱码。原因要么建库时字符集不是 utf8mb4要么连接 URL 少了characterEncodingutf8要么 Windows 控制台的代码页和 Java 默认编码不一致。三个位置只要有一个不是 UTF-8全链路就断了。解决先确认三层对齐建库脚本带DEFAULT CHARACTER SET utf8mb4URL 带useUnicodetruecharacterEncodingutf8Windows 在 IDEA 的 VM options 加-Dfile.encodingUTF-8或命令行跑之前先chcp 65001。机房老电脑有时还要把控制台字体改成 Consolas不然中文显示成方块。检查时可以用SHOW CREATE DATABASE student_db;快速确认库字符集。5.4 表名或字段名撞上 SQL 关键字现象SQL 看起来没问题但执行报SQLSyntaxErrorException提示某个词附近语法错误。原因字段名起名时撞了关键字。我碰到过最典型的两个是desc排序关键字和orderORDER BY 的 ORDER。MySQL 允许关键字做字段名但必须用反引号包起来。很多代码是从旧项目抄来的表结构没校验过。解决字段命名主动回避关键字。已经建好表的SQL 写成desc、order反引号在 MySQL 里是合法的标识符引用符。更推荐的做法是建表时改字段名比如sort_no、order_no一劳永逸。这里有个 mysql 数据库常用命令的小技巧建表前用SHOW COLUMNS FROM student;把字段过一遍心里有数。5.5 程序退出但连接不释放导致 Too many connections现象控制台程序多开几次或反复登录退出报java.sql.SQLException: Too many connections。原因连接泄漏。Connection 没关MySQL 侧连接数被耗尽默认上限 151。更具体地说是代码里只关了 ResultSet 没关 Connection或者静态方法里 new 了 Connection 却没放进 finally。解决把管理数据库资源的代码全部改成 try-with-resources。排查存量代码登录 MySQL 执行SHOW PROCESSLIST;看当前连接列表Sleep状态且时间很长的基本都是泄漏点。改完代码后再跑一次批量操作连接数会稳定在低位。这个命令也是面试常问的 mysql 排查指令写进简历项目描述里比写“熟练使用 MySQL”更有说服力。这五条拆开看都是小问题组合起来就是课设演示当场翻车的全部片场。写代码时每开一个 Connection 就立刻把关闭代码写出来别等最后统一补这是避免连接泄漏最土也最有效的方法。6. 进阶与收尾打包成可执行 jar以及演示视频的录制脚本6.1 用 Maven 打包成带依赖的 jar验证“换一台电脑也能跑”课程设计交的不只是源码很多老师要求当场运行或提交可执行文件。控制台程序最方便的交付形态是java -jar就能跑的 jar。Maven 项目配置 maven-assembly-plugin或者用 IDEA 的 Artifacts 功能把依赖打进去两种都可以。关键点是普通 jar 里没有驱动类换台机器运行就会报 ClassNotFoundException。所以要么打成 fat jar把所有第三方类并到一个文件里要么把依赖 jar 放 lib 目录在 MANIFEST 的 Class-Path 里逐条写明。对课设来说 fat jar 更省事双击就能跑。打包后本机验证一次java -jar xxx.jar再找一台只有 JDK、没有 IDEA 的机器验证一次。这一步能暴露所有 classpath 问题。我自己的习惯是打包前先mvn clean不然 target 里残留的旧 class 会带出很多说不清的怪毛病。6.2 演示视频按脚本录别开录后才边想边敲标题里写了含演示视频视频内容要有节奏不是把操作过程干录一遍就完。我建议按四段脚本录第一段展示建库脚本和项目结构第二段启动程序演示一次登录失败和一次登录成功第三段演示增删改查各一次第四段演示事务回滚——故意让最后一条数据重复插入让大家看到前面几条也都没进去。录制用 OBS 或系统自带录屏都行分辨率不用高但控制台文字必须清晰。录之前把控制台字号调大字体调成 Consolas执行chcp 65001避免中文乱码入镜。录制前自己先完整走一遍流程哪些位置容易输错字、哪条 SQL 执行得慢都心中有数再开录。演示视频有个加分操作在删除或插入时口头说一句“我用的 PreparedStatement所以这段输入不会造成 SQL 注入”老师会觉得你真懂而不是只会跑通。我自己的习惯是录完导出后对照代码把 URL 里每个参数的意义用字幕备注补上去比如serverTimezone为什么设 Asia/Shanghai。这样一份演示视频配合前面的代码已经超过绝大多数课设的交付质量。希望帮到你。本文还有配套的精品资源点击获取