ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

图书管理系统课程设计全解析:软工流程与SQL实现

图书管理系统课程设计全解析:软工流程与SQL实现 简介《图书管理系统软件工程课程设计报告》是一份面向软件工程专业学生与课程设计团队的完整项目文档以XX学院09信计开发小组的图书管理系统项目为实例系统说明了可行性研究、项目开发计划、需求分析、总体设计等内容覆盖读者管理、借阅管理、读者查询、图书管理等核心功能模块并给出客户机/服务器架构及Windows NTVisual C、LinuxOracle8的技术选型方案。文档内还包含数据流图、运行环境、验收标准等实用细节可作为软件工程课程设计的参考模板也可用于梳理复杂信息系统的开发流程。压缩包共1个doc文件大小5.29MB结构完整、便于查阅。已有6299人学习浏览适合需要借鉴完整课程设计报告或理解软件工程方法落地的读者。1. 为什么这份课程设计报告值得当成项目复盘你手上这份《图书管理系统软件工程课程设计报告》看起来是一份答辩材料实际上是一个完整的软件工程过程样本。它从可行性研究一路写到项目开发计划、需求规格说明书、概要设计说明书覆盖了图书管理系统最核心的模块书籍管理、用户管理、借阅管理、出版社信息管理。对正在做软件工程课程设计的人来说它的价值不在于代码写得有多漂亮而在于它把“一个系统是怎么被论证、拆分、定义、设计出来的”这条路走了一遍。图书管理系统本身不算复杂但涉及的角色多、状态转换多、数据关系清晰非常适合用来练习软件工程方法。本文不打算复述原文内容而是把它当作一个真实项目来拆可行性研究怎么落到可评估的结论上需求条目怎么转成数据字典和用例C/S架构下的数据库表怎么设计借阅和还书这些核心流程在SQL层面怎么写。中间章节给出的SQL、表和案例是我在实际项目中常用的做法你可以直接对照自己的课设来改。2. 可行性评估把“能不能做”变成可量化的指标2.1 技术路线选型的依据原文给出了一个很有意思的对比需求规格说明书里写的是“Windows 2000 Advanced Server IIS 5.0 SQL Server 2000”而概要设计说明书里写的是“服务器端Linux Oracle8”和“Access”。这其实是很多课设小组都会犯的问题——不同文档由不同人写技术栈没有对齐。真正做项目时第一件事就是把技术栈锁死。现在的图书管理系统课程设计主流方案有两个一是Java Web方向Spring Boot MyBatis MySQL Vue适合前后端分离的毕设演示二是C/S方向C# WinForm SQL Server适合强调数据库事务和存储过程的题目。原文用的C SQL Server 2005属于比较老的组合但胜在逻辑简单、演示直观。我一般建议选修数据库课的选C#选修软件工程的选Java Web因为后者能顺便展示架构分层。技术可行性评估至少要覆盖三个维度。第一是开发环境是否可用JDK或Visual Studio、数据库、版本控制工具能不能装齐。第二是团队能力是否匹配比如有没有人写过Spring Boot的拦截器有没有人写过SQL Server的存储过程。第三是数据量级评估图书管理系统在校园场景下图书表几万条、借阅记录几十万条这个量级用MySQL或SQL Server都绰绰有余不需要引入Redis缓存或分库分表。2.2 经济可行性和成本估算的简化做法原文用了一整页来做预算包括开发人员工资、硬件采购、维护费用。课设阶段不需要这么精细但可以用“人力成本 人数 × 工时 × 单价”这个公式估算一下。假设一个小组4人开发周期8周每周投入10小时按最低兼职标准每小时30元算人力成本就是4 × 80 × 30 9600元。再加上一台云服务器或本地虚拟机跑MySQL和Tomcat成本完全可以控制在1万元以内。把这个估算写进项目开发计划里比空喊“投资少”有说服力得多。经济可行性的关键结论不是说“省钱”而是算清楚ROI也就是投入产出比。校园图书馆引入系统后管理员从4人减少到2人按每人每月3000元工资算一年省下7.2万元一个学期就能收回开发成本。这个算法很简单但答辩时很加分。2.3 操作可行性谁在用这个系统操作可行性常常被忽略但图书管理系统有个特点——用户分三类读者、图书管理员、系统维护员。读者只想查书和续借管理员要处理借还书和图书入库维护员负责权限和数据备份。这三类人的操作水平差异很大读者可能完全不懂计算机所以查询界面要做到“输入书名就能搜”。管理员的操作路径要尽量短比如借书就是“扫条码 → 扫借阅卡 → 确认”三步完成。在设计阶段就要把这些约束写清楚否则做出来的系统会出现“功能都有但没人愿意用”的尴尬局面。3. 需求分析落地从功能清单到数据字典3.1 用例模型与功能边界原文功能需求部分列出了书籍管理、用户管理、借阅管理三大模块。这些模块的划分方式反映了典型的图书管理系统边界书籍管理关注“馆藏资源本身”用户管理关注“谁有权限借书”借阅管理关注“书和人的关系在时间轴上的状态变化”。用UML用例图建模时要画三个actor读者、图书管理员、系统维护员。读者有查询图书、查看个人借阅、续借三个用例管理员有图书入库、图书修改、图书注销、借书登记、还书登记、罚款登记六个用例维护员有用户信息管理、权限配置、数据备份三个用例。其中续借用例存在一个包含关系——系统需要先验证读者是否有超期未还的图书。这个约束改写成SQL就是后续要做的判断逻辑。3.2 核心业务规则的形式化描述需求规格说明书不能只写“读者可以借书”这种话要把规则写成可以测试的条目。以借书为例至少要定义以下约束读者必须有有效借阅卡且状态为“正常”挂失或暂停状态下不能借书。同一读者最多同时借5本图书。借阅期限默认30天超期每天罚款0.2元。图书状态必须为“在馆”已借出或已注销的图书不能出借。每次借书事务必须同时写入借阅记录表并更新图书状态两步要么都成功要么都失败。这些规则拿到答辩现场老师随便问“如果读者已经借了5本怎么办”“如果书被预约了怎么办”你都能直接回答。原文中的“查询速度不超过5秒”、“交互功能反应速度不超过3秒”这类性能指标也要保留但建议补一条更具体的在5万条图书数据和10万条借阅记录的存量下模糊查询响应时间不超过2秒。这个数字可以在做完性能测试后回填既真实又有说服力。3.3 数据字典与E-R图的工程化写法原文的数据字典比较简略比如“读书信息图书名作者出版社ISBN”。工程上建议用更规范的格式每个数据项都标注名称、类型、长度、取值范围、是否为空。举个例子数据项名类型长度是否可空说明book_idint11否图书ID自增主键isbnvarchar20否ISBN编号用于条码扫描titlevarchar100否书名authorvarchar50是作者可多作者用/分隔publishervarchar50是出版社category_idint11否分类ID外键关联图书分类表statustinyint4否状态0注销1在馆2已借出E-R图的核心是三个实体和两个关系。三个实体分别是图书、读者、借阅记录。图书实体的属性包括书名、ISBN、分类、出版社、状态读者实体的属性包括姓名、学号/工号、类型、状态借阅记录实体的属性包括借书时间、应还时间、实际还书时间、罚款金额。两个关系一个是“读者借阅图书”一个是“管理员处理借阅”。对应到数据库里就是借阅记录表同时外键关联读者表和图书表再加一个操作员ID字段记录管理员。原文给出的E-R图只有分图没有合并的总图建议补一张总体E-R图答辩时直接投影出来。以下是一个标准的借阅关系表SQL定义CREATE TABLE borrow_record ( record_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 借阅记录ID, reader_id INT NOT NULL COMMENT 读者ID关联reader表, book_id INT NOT NULL COMMENT 图书ID关联book表, operator_id INT NOT NULL COMMENT 操作员ID关联admin表, borrow_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 借出时间, due_date DATETIME NOT NULL COMMENT 应还时间默认借出时间30天, return_date DATETIME DEFAULT NULL COMMENT 实际归还时间NULL表示未还, fine_amount DECIMAL(10,2) DEFAULT 0.00 COMMENT 罚款金额超期自动计算, status TINYINT NOT NULL DEFAULT 0 COMMENT 0借出中 1已归还 2续借过, INDEX idx_reader (reader_id), INDEX idx_book (book_id), INDEX idx_due (due_date), CONSTRAINT fk_br_reader FOREIGN KEY (reader_id) REFERENCES reader(reader_id), CONSTRAINT fk_br_book FOREIGN KEY (book_id) REFERENCES book(book_id), CONSTRAINT fk_br_operator FOREIGN KEY (operator_id) REFERENCES admin(admin_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT借阅记录表;这段DDL有几个值得说明的设计点。record_id用自增主键而不是直接用reader_id book_id做联合主键原因是一个读者可以分多次借同一本书联合主键会限制同一本书再次借出。due_date单独建索引是因为超期查询是高频操作每天定时任务要扫描这张表找出所有due_date小于当前时间且status为0的记录没有索引会全表扫描。fine_amount字段设计成允许为0而不是用NULL是为了后续统计罚款总额时方便直接用SUM函数不用COALESCE处理。借阅状态用TINYINT而不是字符串一方面节省存储另一方面代码里用枚举映射避免字符串拼写错误导致状态判断失效。4. 概要设计要点C/S架构下的模块划分与接口约定4.1 为什么选C/S而不是B/S原文的配置是客户端Windows 服务器端Linux/Oracle这是典型的C/S架构。放在今天做课设选C/S还是B/S要看场景。如果题目强调事务一致性、强调数据库端逻辑比如“借书时库存和记录必须同时更新”那C/S配合存储过程比较顺手因为连接是长连接事务边界容易控制。如果题目强调多端访问、远程续借、在线查询那B/S是必须的因为浏览器就是客户端不需要为读者单独安装软件。原文提到“可通过互联网或图书馆内查询终端查询”严格来说这已经是B/S的功能需求了但架构还是C/S说明原型文档本身存在设计矛盾。你写报告时要注意功能描述和架构选型得自洽如果选了C/S就把在线查询定位成“管理员代查”或者“只在校内内网开放”不要自己给自己挖坑。4.2 模块图与层次关系概要设计说明书里一定要有模块结构图。图书管理系统可以拆成三个层级表现层、业务层、数据访问层。表现层就是登录窗口、图书管理窗口、借阅窗口、查询窗口。业务层处理规则比如借书时检查读者状态和配额、还书时计算罚款。数据访问层封装所有SQL操作对外暴露方法而不是表名比如BookRepository.getAvailableByIsbn(String isbn)。接口DIAGRAM建议用一张表格描述模块间传递的参数调用方被调方传递信息返回信息借阅窗口借书业务类readerId, bookId, operatorId成功/失败失败原因借书业务类图书数据访问类bookId图书实体或空借书业务类借阅记录数据访问类借阅记录实体自增recordId还书窗口还书业务类recordId, returnDate应罚款金额接口表的意义在于开发时能并行一个人写界面一个人写业务一个人写数据访问只要提前约定好方法签名互不阻塞。这也是软件工程课程设计考察的重点——不是看你代码写得多好是看你会不会组织多人协作。4.3 数据库表的关联设计与范式取舍数据库设计至少要有图书表、读者表、管理员表、图书分类表、读者类型表、出版社表、借阅记录表、罚款记录表这八张表。其中出版社表和图书分类表都是典型的字典表数据量小适合用InnoDB的row格式查询时用JOIN关联。有一点要注意原文在读者表里设计了余额字段和“是否VIP”这和真实图书馆的读者模型不太一致更接近电商模式。课设里可以有但如果不是题目硬性要求建议去掉因为余额字段会引入充值、扣费等一系列额外逻辑把答辩复杂度拉高。留着读者类型表就够了不同类型的读者可以设定不同的可借数量上限和借阅天数这个才是图书管理系统的核心规则。范式设计上遵循第三范式借阅记录表不冗余读者姓名和书名需要时JOIN查询。但有一个例外借阅记录表建议冗余外键对应的“应还时间”字段也就是due_date。这个字段是借出时根据读者类型规则算好的不是从别的表JOIN出来的所以不算违反第三范式。提前算好的好处是超期查询只扫一张表且不受读者类型规则修改的影响——如果临时调整了借阅天数已借出的记录不追溯变化保持业务语义一致。5. 图书管理系统核心流程实现借书、还书、续借与查询5.1 借书流程的SQL事务实现借书操作是图书管理系统最核心的事务必须保证“借阅记录插入”和“图书状态更新”两步原子完成。如果第一步成功但第二步失败会出现书显示在馆但读者能查到借阅记录的问题。下面的存储过程演示了完整流程并把检查逻辑放进事务里DELIMITER $$ CREATE PROCEDURE borrow_book( IN p_reader_id INT, IN p_book_id INT, IN p_operator_id INT, OUT p_code INT, OUT p_msg VARCHAR(255) ) proc_label: BEGIN DECLARE v_reader_status TINYINT; DECLARE v_book_status TINYINT; DECLARE v_borrow_count INT; DECLARE v_due_days INT DEFAULT 30; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SET p_code 500; SET p_msg 系统异常借书失败; END; START TRANSACTION; -- 1. 检查读者状态和未还图书数 SELECT status INTO v_reader_status FROM reader WHERE reader_id p_reader_id FOR UPDATE; IF v_reader_status ! 1 THEN SET p_code 4001; SET p_msg 读者状态异常无法借书; ROLLBACK; LEAVE proc_label; END IF; SELECT COUNT(*) INTO v_borrow_count FROM borrow_record WHERE reader_id p_reader_id AND status 0; IF v_borrow_count 5 THEN SET p_code 4002; SET p_msg 该读者已借满5本请先归还; ROLLBACK; LEAVE proc_label; END IF; -- 2. 检查图书状态 SELECT status INTO v_book_status FROM book WHERE book_id p_book_id FOR UPDATE; IF v_book_status ! 1 THEN SET p_code 4003; SET p_msg 图书不在馆或已注销; ROLLBACK; LEAVE proc_label; END IF; -- 3. 插入借阅记录并更新图书状态 INSERT INTO borrow_record(reader_id, book_id, operator_id, due_date) VALUES(p_reader_id, p_book_id, p_operator_id, DATE_ADD(NOW(), INTERVAL v_due_days DAY)); UPDATE book SET status 2 WHERE book_id p_book_id; COMMIT; SET p_code 0; SET p_msg 借书成功; END$$ DELIMITER ;这个存储过程里FOR UPDATE起了关键作用。在事务内用SELECT ... FOR UPDATE锁定读者记录和图书记录可以防止两个管理员同时给同一个读者借不同书时出现并发超借。比如读者剩余额度只有1本两个人同时操作不加锁的话可能都通过了检查最后实际借出2本。加了查锁后第二个事务会阻塞到第一个事务提交然后重新读取到更新后的额度走到4002分支。图书记录的锁防止同一本实体书同时被借给两个人。借阅天数v_due_days先写死为30天实际项目里应该改成从读者类型表查出比如教职工60天、研究生45天、本科生30天。EXIT HANDLER FOR SQLEXCEPTION捕获任何未处理的异常统一回滚并返回500避免存储过程半途中断导致数据不一致。5.2 还书流程与超期罚款计算还书流程的核心是先查出借阅记录然后计算是否超期如果超期就生成罚款记录最后更新图书状态为在馆。这里要特别处理“借阅记录未找到”的分支——有可能是图书条形码扫描错也可能是还的是别的馆的书不要直接报错应该提示操作员确认。DELIMITER $$ CREATE PROCEDURE return_book( IN p_book_id INT, IN p_operator_id INT, OUT p_code INT, OUT p_msg VARCHAR(255), OUT p_fine DECIMAL(10,2) ) proc_label: BEGIN DECLARE v_record_id INT; DECLARE v_due_date DATETIME; DECLARE v_overdue_days INT; DECLARE v_fine DECIMAL(10,2) DEFAULT 0.00; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SET p_code 500; SET p_msg 还书处理异常; END; START TRANSACTION; -- 1. 查找当前借出且未归还的记录 SELECT record_id, due_date INTO v_record_id, v_due_date FROM borrow_record WHERE book_id p_book_id AND status 0 LIMIT 1; IF v_record_id IS NULL THEN SET p_code 4004; SET p_msg 未找到在借记录; ROLLBACK; LEAVE proc_label; END IF; -- 2. 计算超期天数使用 TIMESTAMPDIFF SET v_overdue_days GREATEST(TIMESTAMPDIFF(DAY, v_due_date, NOW()), 0); IF v_overdue_days 0 THEN SET v_fine v_overdue_days * 0.20; INSERT INTO fine_record(record_id, reader_id, book_id, overdue_days, fine_amount, operator_id) SELECT v_record_id, reader_id, book_id, v_overdue_days, v_fine, p_operator_id FROM borrow_record WHERE record_id v_record_id; SET p_msg CONCAT(还书成功超期, v_overdue_days, 天罚款, v_fine, 元); ELSE SET p_msg 还书成功未超期; END IF; -- 3. 更新借阅记录和图书状态 UPDATE borrow_record SET return_date NOW(), status 1 WHERE record_id v_record_id; UPDATE book SET status 1 WHERE book_id p_book_id; COMMIT; SET p_code 0; SET p_fine v_fine; END$$ DELIMITER ;这里使用GREATEST函数的目的是把负超期天数归零。如果读者提前还书TIMESTAMPDIFF得到负数GREATEST(x, 0)直接返回0这样就不再需要IF嵌套判断是否有超期。罚款插入采用INSERT...SELECT直接从借阅记录表读出reader_id和book_id省去一次额外查询。需要留意的是超期天数按自然日算如果图书馆规则是“仅按工作日罚款”这里要改成自定义函数。5.3 续借的判断逻辑与限制续借不是把due_date直接加30天那么简单要满足三个条件没有超期、没有预约、续借次数小于限制。超期或已预约的书不允许续借因为可能有其他读者在等待。续借条件可以用一个存储过程实现DELIMITER $$ CREATE PROCEDURE renew_book( IN p_record_id INT, OUT p_code INT, OUT p_msg VARCHAR(255) ) proc_label: BEGIN DECLARE v_status TINYINT; DECLARE v_due_date DATETIME; DECLARE v_renew_count INT DEFAULT 0; START TRANSACTION; SELECT status, due_date INTO v_status, v_due_date FROM borrow_record WHERE record_id p_record_id FOR UPDATE; IF v_status IS NULL THEN SET p_code 4004; SET p_msg 借阅记录不存在; ROLLBACK; LEAVE proc_label; END IF; IF v_status ! 0 THEN SET p_code 4005; SET p_msg 该记录已归还不能续借; ROLLBACK; LEAVE proc_label; END IF; IF v_due_date NOW() THEN SET p_code 4006; SET p_msg 图书已超期请先归还并缴纳罚款; ROLLBACK; LEAVE proc_label; END IF; -- 假设最多续借1次判断是否已经续借过 IF v_renew_count 1 THEN SET p_code 4007; SET p_msg 已达最大续借次数; ROLLBACK; LEAVE proc_label; END IF; UPDATE borrow_record SET due_date DATE_ADD(due_date, INTERVAL 30 DAY), status 2 WHERE record_id p_record_id; COMMIT; SET p_code 0; SET p_msg 续借成功新的到期时间为 DATE_FORMAT( (SELECT due_date FROM borrow_record WHERE record_id p_record_id), %Y-%m-%d); END$$ DELIMITER ;续借流程里容易忽略的一个点是续借后超期检查的基准应该以续借后的due_date为准而不是借书时的due_date。这个存储过程先在事务内锁定记录防止并发下同一笔记录被重复续借两次——如果没有锁两个请求同时进来都检查到v_renew_count等于0然后都执行UPDATE就续借了两次。5.4 图书查询的索引设计与SQL写法查询模块的常见需求是支持书名模糊查询、按分类筛选、按出版社筛选、按ISBN精确查询。针对这些查询模式索引设计如下ALTER TABLE book ADD INDEX idx_title (title); ALTER TABLE book ADD INDEX idx_isbn (isbn); ALTER TABLE book ADD INDEX idx_category (category_id); ALTER TABLE book ADD INDEX idx_status (status);查询SQL写成动态拼接的方式适配多条件组合SELECT b.book_id, b.title, b.author, b.publisher, b.isbn, c.category_name, b.status FROM book b LEFT JOIN category c ON b.category_id c.category_id WHERE b.status 1 AND (?title IS NULL OR b.title LIKE CONCAT(%, ?title, %)) AND (?category_id IS NULL OR b.category_id ?category_id) AND (?isbn IS NULL OR b.isbn ?isbn) ORDER BY b.book_id DESC LIMIT ?offset, ?page_size;这段SQL使用占位符方式传参可以有效防止SQL注入同时支持任意条件组合。查询性能方面要注意一个常见坑直接在title字段上做LIKE %关键字%会触发全表扫描即使建了索引也用不上。如果检索量确实很大应该考虑全文索引或引入Elasticsearch课程设计量级下用LIKE 关键字%配合前缀索引就够了。字段长度超过一定阈值时前缀索引还能降低索引空间以title字段最常查询列为例ALTER TABLE book ADD INDEX idx_title_prefix (title(20));对书名这类非等值查询LIKE以通配符开头的条件无法命中索引这一点在答辩时被问到的概率很高。回答思路是先说明当前数据量在十万条以内MySQL优化器在扫描行数可控的情况下可能选择全表扫如果要优化可以改成全文索引或对检索词做分词。6. 收尾技巧测试用例设计、文档一致性与部署验证6.1 借阅流程的状态转换测试用例测试是课程设计报告里最容易空泛的部分建议不要只写“系统测试通过”而是给出可执行的状态转换测试矩阵。以借阅记录状态机为例从“借出中”转换到“已归还”中间要经过罚款计算和图书状态更新两个步骤测试用例编号场景描述预期结果TC-LOAN-001正常读者借在馆图书借阅记录插入图书状态改为已借出TC-LOAN-002无效读者ID返回4001事务回滚图书状态不变TC-LOAN-003读者已借满5本返回4002借阅失败TC-LOAN-004图书状态已借出返回4003提示图书不在馆TC-RET-001借期内归还记录关闭图书状态改为在馆无罚款TC-RET-002超期5天归还生成罚款罚款金额等于5*0.2元TC-RET-003归还未借出的书返回4004提示没有在借记录TC-REW-001未超期首次续借成功续借30天状态标记为续借TC-REW-002超期后申请续借返回4006提示先还书TC-REW-003同一记录第二次续借返回4007超过续借上限6.2 并发测试与数据一致性验证并发测试是验收环节的一个加分项在确保借阅流程可靠的前提下用脚本模拟两个管理员同时为同一个读者办理借书业务for i in 1 2; do (mysql -u root -p123456 library_db \ -e CALL borrow_book(1, 101, 1, code, msg); SELECT code, msg; ) done wait脚本作用是同一时刻发起两个借书请求。如果存储过程正确使用了FOR UPDATE锁那么其中一个调用会看到已经借满5本的情况另一个正常成功。如果不用锁两条记录可能同时通过检查数据库里出现6本在借记录就说明业务逻辑有漏洞。这个测试结果写进课程设计报告的“测试分析”章节会非常有说服力。6.3 文档一致性检查与答辩补充材料写课程设计报告最大的坑是各文档技术栈不一致、图表编号错乱、数据流图与数据库设计对不上。答辩前一天建议做一遍“交叉验证”对照需求规格说明书的功能编号在概要设计说明书的接口表里找到对应模块对照数据字典里的数据项在SQL建表语句里确认字段类型和约束。原文里“查询速度不超过5秒”和“反应速度不超过3秒”这两个指标在测试报告中一定要有对应的测试记录哪怕是在1万条数据下测的也把环境和数据量写清楚体现严谨性。另外原文里提到的“读者网上续借”“邮件通知超期”是典型的高阶功能电路设计说明书里没有展开。如果你有精力可以补充说明邮件通知采用的处理方式——定时任务每天扫描borrow_record表找出到期前3天且status0的记录调用SMTP接口发提醒。如果没做就在报告里如实写“该功能未纳入本次课设范围”不要跟需求规格说明书上的条目互相矛盾。最后提一个实打实的验证技巧部署完成后用Navicat或MySQL Workbench查看借阅记录表确认借书后图书状态从1变成2还书后从2变回1罚款记录表里自动出现超期的数据行。这三个状态对照通过系统的最核心链路就是通的答辩时被问“系统怎么验证”就直接给出这个回复相当于给自己留了一条后路。本文还有配套的精品资源点击获取
返回列表