1. 项目本质:一个老技术栈却五脏俱全的JavaWeb课设
1.1 这个系统解决了什么问题
先把话挑明:这是典型的JavaWeb课程设计/毕业设计项目,题目长这样——“JSP普洱捷达4S店预约试驾系统15z9e(1)”。拆开看,JSP代表技术栈,普洱捷达4S店是业务场景,预约试驾是核心功能,后面串的“程序+源码+数据库+调试部署+开发环境”是交付物。哪怕你没下载过、没打开过这个包,光看名字就能猜出它大概长什么样。
在4S店的真实业务里,试驾预约是一个高频但流程琐碎的场景。用户想看车、试车,先得电话沟通或者到店排队,销售顾问手工登记意向、安排时间,经常出现登记错、漏登记、客户来了车不在店里的情况。这个系统就是想把“用户发起试驾申请→管理员审核安排→用户查看结果”这条链路搬到网上,减少线下沟通成本,同时让4S店积累一批意向客户数据。放到课程设计的语境里,它同时覆盖了注册登录、增删改查、分页、表单提交、Session管理这些JavaWeb必考核点——老师爱出这类题,学生也相对好动手。
这个包里的源码、数据库脚本、部署文档是要一起配套使用的。网络上下载的这类项目包,通常还带一个README或者需求文档,里面会写清楚管理员账号、数据库连接配置、表结构等。先看文档再动手,比什么都重要。
1.2 为什么2025年了还在用JSP做新项目
我知道你心里大概率有个疑问:企业里早不用JSP写新系统了,Spring Boot + Vue不香吗?这个问题我在不止一个学生群里被问过。答案是:教学体系和企业技术栈之间有滞后,这很正常。
JSP作为视图层技术的核心价值在于:它让你直接面对HTTP请求、Session、Cookie这些Web最底层的东西,而不是被框架层层封装之后什么都看不见。用JSP写一套系统,你能亲手体会到“请求从浏览器发出去之后到底经过了什么”,这是框架给不了的经验。更何况很多学校《Java Web程序设计》课程大纲就是以JSP/Servlet为主线,期末考核、毕设选题自然围绕这个方向出。
从使用角度看,传统JSP项目也有它没被淘汰的理由:部署简单,一个Tomcat就能跑;维护成本低,逻辑全在JavaBean和Servlet里;对服务器配置要求极低。现在网上很多旧系统升级、内部管理系统维护,用的还是这套技术栈。所以如果你拿到的题目是“JSP+MySQL实现XX管理系统”,不用怀疑它的合理性,这是我见过最高频的毕设题目形态之一。
1.3 交付物清单里到底有什么
标题里那串括号不是凑字数,它基本约定了一个标准毕设压缩包里常见的结构:
- 程序源码:通常是IDEA或Eclipse的完整工程目录,包含src下的Java类、web目录下的JSP页面、web.xml配置文件、jar包(或者是Maven的pom.xml)。
- 数据库脚本:一个SQL文件,包含建库建表语句和演示数据。有的还会拆成
init.sql和data.sql两份。 - 调试部署说明:一个Word或者Markdown文档,写环境配置步骤、账号密码、常见问题。
- 开发环境:指JDK、Tomcat、MySQL、IDEA这些工具的版本要求和配置方式。
拿到压缩包第一件事,别急着解压导入。先把文档找出来通读一遍——确认JDK版本、Tomcat版本、MySQL版本、是否有Maven依赖、数据库连接串是硬编码还是配置文件。项目跑不起来,八成不是因为代码有问题,而是环境对不上。这一点后面展开细说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境准备:版本对了能少踩80%的坑
2.1 工具版本怎么配对
这类JSP课设项目最常见的技术组合是:JDK 1.8 + Tomcat 8/9 + MySQL 5.7/8.0 + IDEA/ Eclipse。为什么强调这个组合?因为这是“下载量最大、网上教程最多、踩坑答案最全”的组合。你要是自己装了个JDK 17再配Tomcat 10,不是不行,但Tomcat 10的Servlet API包名变了,很多老项目的代码会直接编译报错,光改名就要折腾半天,没必要。
具体版本上,我给你的参考是:
| 组件 | 推荐版本 | 不推荐的情况 |
|---|---|---|
| JDK | 1.8(8u202或更早) | 高版本JDK配合老Tomcat可能出现类加载问题 |
| Tomcat | 9.0.x | Tomcat 10以上API变更较大,老JSP项目不适配 |
| MySQL | 5.7 或 8.0 | 用8.0注意驱动版本和时区配置 |
| 连接驱动 | mysql-connector-java 5.1.49(对应5.7)/ 8.0.x(对应8.0) | 驱动和数据库版本不匹配会报各种连接错误 |
| IDE | IntelliJ IDEA 2021/2022/2023均可 | Eclipse也可,但配置方式略不同 |
这里有个很多人不知道的细节:Tomcat版本决定了你用的是Servlet 3.1还是4.0规范,而JSP课设项目里往往用到了@WebServlet注解或者web.xml配置,这两种方式对Tomcat版本要求不同。如果你看到源码里Servlet类既没有注解也没有web.xml映射,那就说明项目用了旧式配置,建议用Tomcat 8.5更稳。
2.2 IDEA里创建/导入JSP项目骨架
如果你拿到的包是现成工程,操作路径一般是:File -> New -> Project from Existing Sources,选到工程根目录,然后一路Next让IDEA识别为Web项目。如果包是裸源码(只有src和web目录,没有.idea文件夹),那就手动新建一个Java Web工程再拷代码。
IDEA新建JSP项目的正确打开方式是:新建Project时选择Jakarta EE或者Java Enterprise分类下的Web Application,别选普通的Java Project,否则你会发现没有web目录也没有Tomcat运行入口。项目骨架生成之后会自带web/WEB-INF/web.xml和index.jsp,这就是最基础的Web项目形态。
导入之后有一步特别重要:Project Structure(Ctrl+Alt+Shift+S)里把Artifacts配置好。这个步骤是很多人导入工程后无法启动的元凶——你需要把编译输出指定成WEB-INF/classes,然后把项目所有的jar包(注意是lib目录下的,不是Maven仓库里的)添加到Artifacts的Output Layout里。我之前接过很多学生的求助,截图发过来一看,要么没有Artifacts,要么依赖全是红的,这个不配好,启动Tomcat必然报“Artifact xxx: Server not connected”或者404。
2.3 Tomcat在IDEA里的集成配置
IDEA里跑Tomcat的逻辑不是“启动独立Tomcat”,而是IDE启动一个Tomcat实例,然后把你的Web项目部署上去。配置入口:Run/Debug Configurations -> 左上角加号 -> Tomcat Server -> Local。
这里要填几个东西:
- Application server:选择本地Tomcat安装目录。没有的话先
Download或者手动指定到解压好的Tomcat根目录。 - URL/端口:默认
http://localhost:8080/,如果你同时开了多个Tomcat实例,改一下端口比如8081,避免冲突。 - Deployment选项卡:点加号添加
Artifact,Application context一般填/(访问根路径)或者跟项目名一致,比如/jsp_car。
配置好之后,很多新手会遇到一个很迷惑的问题:启动Tomcat之后控制台日志显示Connected to server,但浏览器访问localhost:8080是Tomcat的默认首页,不是你的项目。原因就是Deployment里没加Artifact,或者Application context不对。这种情况把Artifact加上、重新启动就好。
2.4 数据库导入这条老路别再走弯了
数据库这块常见两种操作:命令行source,或者Navicat/DataGrip里的导入SQL文件。都行,但我要提醒三个高频翻车点。
第一,先建库再导表。SQL文件第一行通常是CREATE DATABASE或者USE xxx,如果文件里没写建库语句,你得先手动建一个库,再导入表。建的库名必须和项目里数据库连接串的jdbc:mysql://localhost:3306/xxx里的xxx一致,否则运行起来报Unknown database。
第二,MySQL 8.0的时区坑。8.0之后的连接串如果不加serverTimezone=Asia/Shanghai,会报The server time zone value '�й���ʱ��' is unrecognized,你会在数据库连接这一步卡到怀疑人生。正确连接串长这样:
code复制jdbc:mysql://localhost:3306/java_car?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
第三,MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver,5.7及以前是com.mysql.jdbc.Driver。驱动名字写错了,直接ClassNotFoundException。别小看这个,报错之后你以为是jar包没导入,翻半天Alt+Enter找依赖,其实只是类名没更新。
3. 数据库设计实战:预约业务的核心数据模型
3.1 核心表结构拆解
试驾预约系统的数据库设计,通常围绕“人、车、预约”三个核心词展开。我把这类项目最常见的表结构拆给你看,基本覆盖了90%同类开发需求:
- 管理员表(admin):管理员ID、账号、密码(MD5加密后的字符串)、姓名、创建时间。这是后台登录的凭证表。
- 用户表(user):用户ID、用户名、密码、真实姓名、手机号、身份证号(虚拟项目里一般只做字段占位)、驾驶证信息、注册时间。手机号和驾驶证这两个字段是试驾场景的重要前置条件,真实业务里要求必须填。
- 汽车信息表(car):汽车ID、车型名称、品牌、型号、排量、颜色、价格、图片路径、库存状态、简介。
- 预约试驾表(test_drive/appointment):预约ID、用户ID、汽车ID、预约日期、预约时间段、期望门店(4S店可能有分店)、状态(待确认/已确认/已完成/已取消)、备注、创建时间。
- 公告表(news):公告ID、标题、内容、发布时间。前台首页展示的部分。
这只是最简版设计。这套系统从表数量上看不算多,但胜在结构清晰,学生实现起来不费劲。有些版本还会加一个留言反馈表(message),用于用户给4S店留言,这就是“增删改查”里额外多出来的一组功能。
3.2 字段设计里的关键细节
外键关系上,预约表通过user_id关联用户表、通过car_id关联汽车表,这是理所当然的。但我要说的是两个容易被忽略的字段设计细节:
状态字段用int还是varchar? 很多新手喜欢用varchar直接存“待确认、已确认”这种中文,图省事。但更合理的做法是存int类型的数字(0待确认、1已确认、2已完成、3已取消),在Java代码里做枚举映射。原因有两个:一是int存储和查询效率更高,二是代码可维护性更强,你后续要加一个“已过期”状态,数字加一就行,不用动数据库表结构。
时间字段怎么存? 预约表一般存两个时间:预约创建时间(时间戳或datetime)和用户期望试驾的时间点。期望试驾时间建议拆成appointment_date(DATE)和time_slot(VARCHAR,存上午/下午这种),而不是存一个完整datetime。因为业务上查询“明天上午有谁预约”的场景特别多,拆开之后SQL简单得多。
3.3 导入演示数据的小技巧
SQL文件里一般会带几条演示数据,比如管理员的账号是admin/admin123,用户的账号是zhangsan/123456。导入数据等于把这个项目的“表演素材”备好,不然登录进去空荡荡的,什么功能都验证不了。
如果你手头的SQL文件里没有演示数据,建议自己插几条测试数据,尤其是汽车信息表。我之前让学生自己造过数据,发现一个规律:车型信息里图片路径尤为重要,别随便填。JSP页面上展示车型图一般用<img src="upload/xxx.jpg">这种相对路径,如果你没有把图片放到对应目录下,页面就会显示裂图。正确的做法是,把图片放在web/upload目录(或者/images目录),SQL里的路径跟实际目录保持一致。这一步不做好,后台管理加图片上传的时候也会栽。
4. 核心功能实现:从注册登录到试驾预约的完整链路
4.1 前台用户端的关键页面与交互流程
整个系统分前台和后台两个视角。前台面向用户,后台面向管理员。前台的核心链路是:注册登录 → 浏览车型 → 发起预约 → 查看预约记录。
注册登录是所有JSP课设里绕不开的环节。实现上一般用UserServlet接收请求,调UserDao查数据库,把用户信息存到Session里,跳转到首页或者指定页面。要注意的是,Session里存的应该是用户对象而不是用户名——很多新手图省事存个session.setAttribute("username", name),结果到了个人中心页要取手机号、身份证号的时候发现取不到,又得再查一次数据库。正确做法是注册成功或者登录成功后直接session.setAttribute("user", user),后续页面用${sessionScope.user.phone}这种EL表达式取,省事又高效。
车型浏览页一般是一个带分页的列表,用JSTL的<c:forEach>遍历数据,加上<c:if test="${page.currentPage > 1}">控制上一页下一页按钮的显示。这里有个很常见的JSTL依赖坑:JSP页面用JSTL标签却忘了引入jstl.jar和standard.jar。没有这两个jar包,页面直接报Unable to find taglib [c],或者500错误。查这个问题往往比写代码时间还长,务必提前加好。
用户发起预约的流程是这样的:在车型详情页点“预约试驾”,跳转到预约表单页,页面提交appointment_id、user_id、date、time_slot这些字段给AddAppointmentServlet。Servlet里先校验是否登录(从Session取user),再校验排期是否冲突(查数据库该车当天是否已有待确认预约),然后插入数据库。这块代码逻辑不复杂,但有一点必须注意——要控制好事务范围。虽然单条插入不需要事务,但如果你是“先查询再插入”的组合操作,最好在筛选完条件后、执行真正的INSERT之前,确保事务边界清晰,避免并发下同一辆车被约两次。
4.2 后台管理端:管理员审核如何实现
管理员登录后进入后台,核心功能是:用户管理、车辆管理、预约审核、公告发布。
预约审核是整个系统的“业务闭环”关键。管理员看到待确认的预约列表后,点“通过”或“驳回”。通过的时候,数据库要把状态从0改成1,可选的加分项是同时给用户发一条站内信或者短信通知。课程设计做到站内信就到顶了,发短信要对接第三方平台,不建议搞。
上传车辆信息后台,一般用一个CarServlet处理表单提交,图片部分用commons-fileupload组件处理。这里有个很多人都会踩的坑:Tomcat的文件上传临时目录权限,或者getRealPath路径为空。如果你发现图片上传成功了但页面看不到图,先检查项目部署路径下的磁盘位置,比如C:\Users\xxx\AppData\Local\Temp,八成是文件被写到了临时目录,而不是你项目的upload目录。解决方式:在Servlet中显式指定上传目录为request.getServletContext().getRealPath("/upload"),然后确保upload目录真实存在。
4.3 预约状态机:一个容易被忽略但很出彩的设计
很多学生写完预约功能后,状态就永远是“待确认”,因为没有人去实现状态流转的后半段。这里我建议你补全一个简单的状态机逻辑:
- 状态0:待确认(用户提交预约,管理员还没有处理)
- 状态1:已确认(管理员审核通过,用户可以按计划到店试驾)
- 状态2:已完成(试驾结束,管理员在后台确认完成)
- 状态3:已取消(用户取消或管理员驳回)
状态机不必做得特别复杂,但在代码里看起来非常加分。前后台的查询接口都通过状态值过滤结果:前台用户查看“我的预约”,按状态显示对应的操作按钮(状态0时可以取消,状态1时只能查看);后台管理员对状态0的记录显示“确认/拒绝”按钮,对状态1的记录显示“标记完成”按钮。这一步做完,整个系统的业务完整性立刻拉高一个档次,老师在验收时往往会主动加分。
5. 调试部署:从IDEA跑到独立Tomcat,别让项目烂在本地
5.1 本地部署的标准流程
把环境全部理顺之后,部署其实就三步:配置数据源、启动服务、验证页面。
第一步,改数据库连接配置。看项目里数据库配置是写死在.java文件里,还是在db.properties或者c3p0-config.xml里。写死在Java文件里的最麻烦,改错了得重新编译;写在配置文件里的,改完直接重启就生效。不管哪种,核心就是把数据库地址、库名、账号密码改对。
第二步,编译部署到Tomcat。在IDEA里直接跑Artifact,然后在浏览器访问。注意看Tomcat控制台有没有报错,日志里最常见的两行错误是ClassNotFoundException和Communications link failure。前者查jar包,后者查MySQL服务是否启动、连接串是否正确。
第三步,验证页面和功能。先用admin登录后台,看看车辆管理能不能列表展示、新增车、编辑、删除。再注册一个普通用户,走一遍“登录→选车→预约→后台审核→查看状态”的完整链路。这里有个很实在的建议:验证功能时,把每一个操作都试一遍,不要只点几个主菜单就当成功了。很多包里的删除功能有外键约束问题,删不掉;或者新增功能日期格式不对,直接500。这些要提前发现提前修。
5.2 传统JSP项目怎么打包war
虽然IDEA里能直接跑,但作为课程设计交付,老师可能要你打包成一个war(或者至少能拷到别的电脑上跑)。传统JSP项目打包war的方式有两种:
第一种,在IDEA里选Build -> Build Artifacts -> xxx:war,等待构建完成,war包生成在out/artifacts/目录下。这种方法最快,前提是前面Artifacts已经配置好。
第二种,如果是Maven项目(pom.xml存在),执行mvn clean package,然后去target/目录拿war包。Maven项目打包有一个坑要注意:JSP文件默认被编译进war包的根目录,WEB-INF/classes和lib也都会自动组装好,一般不会有问题,除非你手动改了packaging类型。
打包好war之后怎么部署到独立Tomcat?把war包扔进Tomcat的webapps目录,启动Tomcat,它会自动解压。然后访问http://localhost:8080/项目名/。这里注意一个问题:如果你本地IDEA里部署的Application context是/,打包后独立Tomcat访问需要带项目名(war包名称,如jsp_car),响应的页面里的所有相对路径都要能自适应,否则会出现“CSS样式加载不出来”“图片全裂”这种尴尬状况。
5.3 从IDEA运行改为独立Tomcat运行的特殊处理
独立Tomcat环境和IDEA内置环境最大的区别是:没有IDE替你编译,也没有IDE把classes目录和lib目录自动塞给你。所以你会遇到很多“在IDEA里好好的,一部署就不行”的问题。
最常见的是JSTL依赖问题。IDEA里你通过Add Library引入的jstl.jar只在开发环境有效,打包的时候如果你忘了把jar放进来,war包里的WEB-INF/lib就是空的,独立Tomcat一跑JSP页面必然要报JSPException: Unable to load class。这个问题的标准解法是:确保所有第三方jar包都在WEB-INF/lib下面,或者用Maven的mvn dependency:copy-dependencies把依赖拷贝到target/xxx/WEB-INF/lib再打包。
另一个高频问题是JDBC驱动类名和URL前缀不匹配。IDEA里因为你用的是MySQL 5.7,驱动是5.1.49;部署到测试服务器如果那边是MySQL 8.0,就会报Public Key Retrieval is not allowed。这个报错的解决办法是在连接串后面加allowPublicKeyRetrieval=true。建议直接把连接串写成综合兼容的形式,既兼容5.x也兼容8.x,省得部署一次改一次。
5.4 给“换了台电脑就跑不起来”的人一个保底方案
每年毕业季我都看到有人抱着笔记本哭:项目在自己电脑上跑得好好的,换到答辩教室的电脑上就罢工。这种场景百分之九十九是环境差异导致的。想彻底避免这种尴尬,有一个保底思路:除了导出war包之外,把整个开发环境也打包——比如把JDK、Tomcat、MySQL、项目源码、SQL脚本、部署说明全部放进一个文件夹,压缩成zip。答辩前在目标机器上解压,按文档把环境装一遍。这个方法听起来笨,但它是唯一能保证“换机器也能跑”的方案,比你说一万遍“我代码没问题”都有说服力。
6. 常见问题排查实录:把最容易被卡住的地方一次说透
6.1 高频问题速查表
| 现象 | 根本原因 | 处理方式 |
|---|---|---|
| Tomcat启动后访问404 | Deployment中未添加Artifact | Run Configurations里加入项目Artifact |
| 页面报500且日志有ClassNotFoundException | 缺jar包或驱动类名不对 | 把依赖jar放入WEB-INF/lib,检查驱动类名 |
| 数据库连接失败Communications link failure | MySQL服务未启动或连接串错误 | 启动mysql服务,核对host、端口、库名、账号密码 |
| JSP页面报taglib找不到 | 缺jstl.jar和standard.jar | 将JSTL相关jar加入lib目录 |
| 中文乱码 | JDBC连接串未指定utf8,或页面编码不对 | 连接串加characterEncoding=utf8,JSP页面pageEncoding="utf-8" |
| 时间字段报错无法保存 | 日期格式字符串不匹配 | 前后台统一日期格式yyyy-MM-dd |
| 图片上传后显示不出来 | 路径写死或上传到临时目录 | 用getRealPath指定上传目录 |
| 启动Tomcat报端口占用 | 8080被其他进程占用 | 改用8081或者杀掉占用端口的进程 |
6.2 最经典的三个坑,我展开讲讲
第一个坑,“我明明导入了jstl.jar,怎么还报taglib找不到”。为什么?因为你在IDEA的Modules里加了jar依赖,但没在Artifacts -> Output Layout里把jar放进WEB-INF/lib。IDEA的依赖和部署的依赖是两码事。检查办法:File -> Project Structure -> Artifacts,看Output Layout下的lib目录里有没有这个jar。没有就右键Create -> Copy of available element,把它加进去,重新构建war。这个问题我一年能看到几十次。
第二个坑,数据库密码带特殊字符导致连接失败。数据库连接串如果写在配置文件里,密码里有@、#、&这类字符,会被解析成URL特殊字符,导致连接串被截断或者解析出错。解决办法是URL编码,比如@写成%40,或者在配置里用Properties类读取而不是直接拼URL字符串。很多人项目跑不通,查半天最后发现是密码里有字符没转义,这个细节很少有人写。
第三个坑,页面数据可以查出来,但提交表单永远失败。这种情况多半是web.xml里的Servlet映射有问题,或者表单的action路径不对。传统JSP项目里路径有两种写法:绝对路径和相对路径。绝对路径以/开头,会被解析到http://localhost:8080/项目名/xxx;相对路径相对于当前页面所在目录。页面放在web/manage/下和放在web/下,同样的action="login"指向完全不同的地址,这就导致了奇怪的表单提交失败。最稳妥的写法是在JSP页面前面统一加<base href="${pageContext.request.contextPath}/">,或者提交路径写${pageContext.request.contextPath}/servlet/xxx,这样不管页面在哪个目录都能提交正确。
6.3 一套排查思路,适用90%的报错
你不需要记住所有报错的具体含义,但需要一套标准的排查顺序。我自己的排查顺序是:
先看控制台Tomcat日志,重点找Caused by后面的内容,这个才是问题根源,往上翻几行往往是套了层的异常包装;然后看请求路径,用浏览器开发者工具看Network请求,确认URL是否正确、请求是否真的发到了对应的Servlet;再确认数据库,在数据库客户端里手动执行一遍SQL,看数据和SQL本身是否有问题;最后检查部署产物,WEB-INF/classes和WEB-INF/lib是不是完整存在。
按这个顺序走下来,绝大多数问题都能定位。最忌讳的是看到报错代码片段就随手改一行,改完再试,试完再改——这样大概率把原本好的地方改坏。另外提醒一句:JSP课设项目报错信息往往非常直白,比如The requested resource (/car/list) is not available就是告诉你URL错了,不是服务器坏了,也不是代码有问题。很多新手一看到英文报错就慌,其实认真读一遍,比自己瞎猜强得多。
7. 项目跑通之后,怎么让它看起来更有价值
这套JSP预约试驾系统,按部就班跑通拿高分是保底目标。但我个人建议,跑通之后多花半天时间,给它加两个“一眼就能看出来是独立思考”的小功能。
第一个建议是做一个简单的数据统计页,比如后台首页用高德地图或者纯表格展示“本月预约量Top5车型”“各状态预约数统计”。可以不做图表,只写几个聚合SQL加在后台首页即可。比如:
sql复制SELECT car_id, COUNT(*) AS cnt
FROM appointment
WHERE status = 1
GROUP BY car_id
ORDER BY cnt DESC
LIMIT 5;
配上JSTL循环展示到页面上,答辩时明确说一句“我增加了一个预约热度统计”,老师瞬间会觉得你不只是抄了个模板。
第二个建议是给用户模块加上手机号格式校验和身份证校验。前端用onsubmit加一个简单的正则校验,后端Servlet里再校验一次。虽然代码量不大,但“前端校验+后端校验”的思路能体现你对Web安全的意识,这在答辩里是高频加分项。
最后再分享一个我自己的体会:很多学生纠结“要不要把项目改成Spring Boot版,显得更高大上”。我的建议是别折腾。既然题目明确是JSP,就用JSP把它做到最好。你能把传统JSP项目的请求-响应流程、Session管理、JDBC操作讲明白,比那些用框架但一问三不知的人强得多。跑通这套系统,你收获的不只是一份能交差的代码,而是一整套“从环境搭建到部署上线”的完整心智模型。这套东西放到之后学框架、做项目,都能用得上。
