
SpringBoot Vue 校园管理系统适合当毕设的完整项目到底该怎么拆做Java Web毕设的同学十个里有八个会选“校园管理系统”这个方向。原因很简单业务场景大家天天都在用理解成本低功能边界清晰不像是电商系统那样要处理订单状态机、支付回调这类容易失控的复杂逻辑技术栈又是当前主流的SpringBoot加Vue前后端分离对企业招聘方来说熟悉度足够高。这篇内容我打算从一个比较完整的项目交付物出发把“源码、SQL脚本、接口文档”这三样东西从头到尾拆开聊。你会看到这个系统里的权限是怎么控制的、接口文档应该关注哪些信息、数据库表为什么会这样设计以及拿到源码包后常见的坑和跑通流程。不管你是准备拿它当毕设、课程设计还是想照着做一个自己的管理系统这篇都能给你省下不少弯路。1. 校园管理系统为什么适合当毕设项目以及整体设计思路先说结论校园管理系统是“难度适中、工作量足够、评审友好”的典型题目。毕设选题有个很现实的平衡点。题目太简单比如做一个单页面的个人博客论文写不满答辩时老师三两句话就问完了显得工作量不足题目太难比如做一个带实时音视频的在线教育平台以本科生的开发能力和几个月的时间投入很容易做到一半做不下去最后草草收场。校园管理系统恰好落在这个舒适区里。它至少包含学生管理、教师管理、班级管理、课程管理、成绩管理、用户登录与权限控制这几大块每个模块都有完整的增删改查逻辑前后端加起来工作量足够撑起一篇论文。同时它又是传统的信息管理系统不涉及太复杂的算法、消息队列、分布式事务技术风险可控。这类项目放在简历上也不难解释。“SpringBoot Vue前后端分离JWT做无状态认证MySQL做数据持久化Nginx部署前端后端打jar包跑在服务器上”这一句话面试官就完全知道你做的是什么在什么水平也比较好往下聊。整体设计上优秀的校园管理系统一般会遵循这么几个原则按角色划分功能边界。管理员管全局教师管自己教的课程和成绩学生看课表、查成绩。不能让所有用户进去看到一样的菜单这既是业务需求也是权限设计是否合格的一道送分题。前后端完全分离。后端只出接口前端只负责页面渲染和交互。接口用JSON格式交互不做服务端模板渲染。这个架构的好处是前端可以单独开发、单独部署代码职责清晰。数据库设计遵循第三范式但实际操作上会适当冗余。比如学生表里直接冗余一个班级名称字段省得每次查学生列表都要连班级表。这是一个非常实际的取舍适合写进论文里的“数据库优化”部分。2. 核心功能模块与数据库表设计细节2.1 功能模块的划分方式功能模块不要一开始就往细了做先抓主干。一个典型的校园管理系统主模块应该是模块主要功能使用角色登录认证账号密码登录、退出、Token校验全部学生管理学生信息增删改查、按班级/学号/姓名检索、导入导出管理员教师管理教师信息维护、授课信息维护管理员班级管理班级信息维护、班级与辅导员关联管理员课程管理课程信息维护、开课时间与地点管理员、教师选课管理学生选课、退课、选课名单查看学生、教师成绩管理录入成绩、成绩查询、按课程统计教师、学生菜单与用户菜单权限控制、用户角色分配管理员真正做一个系统的第一步不是先写代码而是先用表格把模块理清楚。你会发现上面这些模块之间是有关联的学生归属班级、班级归属专业、教师负责课程、学生选课程、教师录成绩。这些实体之间的关联关系直接决定了数据库的建模方式。2.2 数据库表的常规建模思路我见过不少设计得比较规范的校园管理系统数据库大体上会包含这些表用户表user保存登录账号、密码、角色、头像、状态。注意这里说的用户表不等于学生表学生表和教师表是业务扩展表用户表只管登录。学生表student学号、姓名、性别、出生日期、手机号、班级ID以及一个关联到用户表的user_id。教师表teacher工号、姓名、职称、院系、手机号、user_id。班级表class班级名称、专业、入学年份、辅导员。课程表course课程编码、课程名称、学分、学时、授课教师ID、上课时间地点。选课表student_course学生ID、课程ID、选课时间联合主键或者自增主键加唯一约束都行。这里有个细节值得说学生表和用户表为什么要分开因为用户在系统里是一个身份概念不只是学生教师和管理员也要登录。如果把学生信息直接当登录账号字段用那教师和管理的账号就没法统一处理了。分开之后登录逻辑只需要面对一张用户表业务逻辑再根据角色拿对应的扩展表信息这是很标准的设计。还有一个细节是班级表与学生的关系。一个学生属于一个班级一个班级有多个学生这是典型的一对多关系所以学生表里有一个class_id外键。而课程和学生的关系是多对多一个学生选多门课一门课有多个学生选所以需要一个中间表student_course。这就是为什么关系型数据库要设计多对多中间表因为直接在学生表里加课程ID没法表达一对多的反向关系会出现数据冗余和更新异常。2.3 SQL脚本里的初始化数据与密码处理拿到的项目里如果有SQL脚本通常它不只是建表语句还包含初始化的管理员账号、菜单数据、甚至演示用的学生和教师数据。这些初始化数据对调试非常重要没有它们你登录进去就是空白系统连菜单都看不到。一个比较关键的点是密码的存储方式。早期毕设项目很多是明文密码现在稍微讲究一点的会用MD5加盐或者BCrypt加密。如果你看到的SQL脚本里密码字段是一个MD5字符串那说明登录校验时会把用户输入的密码做同样的MD5加密再比对如果用了BCrypt密文是一段带随机盐的字符串每次加密结果都不一样校验时用BCrypt的check方法去匹配。我强烈建议毕设项目用BCrypt因为论文里你能写一句“采用了Spring Security推荐的BCrypt加盐哈希算法有效防止彩虹表攻击”这就是一个很自然的亮点还不费力。3. 技术选型解析SpringBoot和Vue为什么是黄金组合3.1 后端为什么是SpringBoot如果倒退到七八年前Java Web的标配还是SSHSpring Struts Hibernate没过几年又流行SSMSpring SpringMVC MyBatis。它们的共性是配置极其繁琐XML配置文件动辄几十行。SpringBoot会用自动配置把这些约定好的东西全部包起来你想做Web项目引入spring-boot-starter-web内置Tomcat写一个Controller就能跑起来不用再配置一堆DispatcherServlet的映射规则。主要体现在这几个方面内置Tomcat打包成jar直接运行不像以前要打war包扔到外置Tomcat的webapps目录里。Starter机制按需引入依赖。要做数据库操作加mybatis-plus-boot-starter要做接口参数校验加validation-starter。不会像以前的Maven工程那样自己拼版本号SpringBoot的父级POM已经帮你管理好了版本兼容性。配置文件集中到application.yml里。数据源、端口、日志级别、MyBatis的mapper位置全在一个文件里管理对毕设来说非常直观。3.2 前端为什么是Vue前端选择Vue而不是React或者Angular最大的原因是学习曲线和国内生态。Vue的中文文档完善周边资料基本都面向初学者比如Element UI或者现在的Element Plus提供了一整套现成的后台管理组件表格、表单、弹窗、分页、菜单、日期选择器全部齐全。校园管理系统这种典型的CRUD页面用Element组件拼接效率极高。项目如果是前后端分离的Vue工程源码结构里通常会有这些目录src/api/按模块封装接口请求比如student.js里全是xx/api/student开头的请求。src/router/路由配置决定访问路径对应渲染什么页面。src/store/Vuex或Pinia管理全局状态比如登录后保存的token和用户信息。src/views/页面组件按功能模块分文件夹。3.3 数据访问层的选择持久层框架目前最常见的有两种选择一个偏传统的MyBatis一个偏便捷的MyBatis-Plus。MyBatis不是ORM框架它本质上是一个半自动化的SQL映射器。你写SQL它负责把结果集映射成对象你传参数它负责把参数装配进SQL。它的好处是SQL完全由你控制出问题时能精确定位。它的缺点是每个简单的查询你都要写一大堆XML或者注解版SQL比较啰嗦。MyBatis-Plus是MyBatis的增强版内置了通用Mapper单表增删改查直接调用BaseMapper的selectById、insert、updateById方法连SQL都不用写。它还提供了一个分页插件做分页查询非常方便。毕设项目我基本都推荐MyBatis-Plus理由很简单你能少写50%的重复代码把精力放在业务逻辑和细节优化上。论文答辩时老师问“你这个数据访问层用的什么框架为什么用它”你可以说“MyBatis-Plus在MyBatis基础上封装了通用单表操作减少了重复SQL编写同时保留了自定义SQL的灵活性配合分页插件解决了列表查询的分页性能问题”。这个回答已经比很多应届生强了。3.4 认证方案的取舍JWT 拦截器登录认证怎么做很多同学在Spring Security、Shiro、JWT之间犹豫。我的建议是不要用Spring Security。它是个重武器配置起来概念很多什么过滤器链、AuthenticationManager、UserDetailsService对毕设来说学习成本不成比例。你可能会花三天时间卡在配置上而这三天本来够你写出所有的接口了。主流且性价比高的方案是JWT加一个HandlerInterceptor拦截器。它的工作流程是登录成功后服务端生成一个JWT令牌里面包含用户ID、用户名、角色等信息用密钥加签名然后把令牌返回给前端。前端把它存在本地一般是localStorage或sessionStorage每次请求时在请求头里带上“Authorization: Bearer 令牌”。后端写一个拦截器拦截需要登录的接口从请求头里取出令牌校验签名和过期时间。校验通过就把用户信息放进去通过ThreadLocal保存Controller里直接取出来用。为什么用JWT而不是传统的Session因为Session是存储在服务器内存里的后端如果是多实例部署Session就没办法共享要做Session集群同步或者引入Redis存储Session。而JWT本身是无状态的服务器不保存用户会话每个请求带上的令牌本身就是身份凭证。这对前后端分离的项目很友好前端可以是浏览器、小程序、AppToken可以通用。3.5 为什么不上微服务有些同学为了简历好看想在毕设里塞Nacos、网关、Feign这些微服务组件。说实话我不建议。理由有三个都很现实第一个工作量撑不起。微服务架构的核心价值是独立部署、分布式扩展对一个校园管理系统来说根本没有这个业务压力。你强行拆成三四个服务只会徒增服务间通信、配置中心、链路追踪这些跟业务无关的问题。第二个答辩风险高。本科生对微服务的理解多半停留在“会启动Nacos、会写Feign调用”的层面。导师追问“你这个服务拆分的依据是什么”“服务之间数据一致性怎么保证”如果答不上来反而给答辩减分。第三个评审可能失衡。有的评审老师认为你堆砌了太多与业务无关的技术属于“过度设计”。与其在架构上炫技不如在工程细节上下功夫接口统一返回格式、参数校验、异常处理、权限控制、前端路由守卫、日志记录。这些才是真正体现工程能力的地方。4. 接口文档应该怎么看、怎么用一个完整的接口文档价值不比源码低。源码能告诉你代码是怎么写的接口文档能告诉你这个系统对外提供了什么样的服务参数长什么样返回结构是什么。拿到接口文档后先别急着翻代码按这个顺序看第一看全局约定。BASE_URL是什么请求头要不要带token状态码0代表成功还是200代表成功分页参数是page/pageSize还是pageNum/pageSize。这些全局约定决定了后面每个接口的解读方式。第二看登录接口。因为撑过登录接口你才能拿到token后续所有业务接口的调试才有入口。登录接口一般就是POST /api/login参数是用户名和密码返回数据里会带一个token字段。第三看学生管理模块的接口列表。通常是最直观的CRUD结构GET /api/student/list分页查询学生列表参数page、size、keywordPOST /api/student新增学生请求体是学生对象PUT /api/student更新学生信息DELETE /api/student/{id}删除学生第四看返回结果结构。规范的项目会有一个统一的Result包装类比如下面这种{ code: 200, message: 操作成功, data: { records: [...], total: 100, size: 10, current: 1 } }前端axios拦截器里会根据code做统一判断如果code不是200就弹出错误提示不需要每个页面都写一遍错误处理逻辑。接口文档里最常被忽略的是“参数示例”和“返回示例”。但恰恰这两块在实际联调时最有用。只看参数列表你不知道name是中文名还是用户名不知道gender传的是“男”还是“0”而一个具体的JSON示例能够直接消除歧义。实际操作中我发现很多同学掉进过一个坑接口文档里写的参数是studentName后端实体类里的字段是studentName但前端传的时候写成了name结果后端收到的值是null接口联调调一晚上调不通最后一行一行对参数才发现是命名不一致。这套问题完全可以通过看接口文档的请求示例来避免。5. 前端项目结构设计与权限控制5.1 入口与路由前端页面一般通过Vue Router来管理路由。在后台管理系统中路由不是一个单纯的一一对应关系它和菜单、权限是绑在一起的。页面加载时前端会向后端请求一份“当前用户的菜单权限”比如管理员返回的是全部菜单学生返回的是个人中心、课表查询、选课中心、成绩查询。前端拿到菜单后动态生成侧边导航栏并把这些路由动态注册进Router实例中。这就是常说的动态路由。它的好处是用户即使知道某条页面的URL直接改了地址栏没有对应路由也进不去这是一种前端层面的页面访问控制。5.2 拦截器与路由守卫前端还有一道防线叫做路由守卫。Vue Router允许我们在跳转前做一个拦截判断逻辑很简单如果要去的是登录页放行。如果本地没有token跳转到登录页。如果有token但访问的是不在自己权限列表里的页面跳转到403页面。这道防线是前端层面的不能取代后端接口的鉴权。后端接口才是真正的安全边界因为接口可以被绕过前端直接用Postman调用。所以后端的拦截器必须校验tokenController里也必须根据角色做权限判断。5.3 后台管理页面的三板斧打开任何一套后台管理系统你会发现页面骨架惊人的一致左侧导航栏、顶部栏、主体内容区。主体内容区里最常出现的就是三个组件搭出来的页面——el-table展示列表数据、el-dialog包裹表单弹窗、el-pagination处理分页。这套组合几乎是后台管理系统的最小范式它的工作流是页面加载时请求第一页数据把列表渲染到表格里点击“新增”按钮时打开一个空的弹窗表单点击“编辑”按钮时先把当前行的数据复制一份到表单里再打开弹窗提交表单时根据是新增还是编辑调用不同的接口成功后刷新列表。这个模式熟悉之后页面开发效率提升非常明显。你会意识到校园管理系统的前端页面虽然多本质上都是这个模板在不同表结构上的重复应用真正需要个性化开发的是登录页、权限控制、数据统计这类页面。6. 实操复盘从零跑通一个完整的前后端分离项目这套流程我反反复复做过很多次按步骤来能省下大量时间。6.1 环境准备JDK 1.8或以上我用的是JDK 1.8稳定毕设足够。Maven 3.6以上。MySQL 5.7或8.x。Node.js 14以上尽量用16或18 LTS版本Node版本太旧或太新都容易出奇怪问题。IDE后端IDEA前端VSCode或IDEA都行。6.2 导入数据库用Navicat或MySQL命令行执行SQL脚本。这一步常见坑有三个第一个数据库版本不一致导致导入报错。MySQL 8的驱动和MySQL 5的驱动连接字符串写法不同如果你用的MySQL 8但后端配置的是com.mysql.jdbc.Driver连不上的。正确写法是com.mysql.cj.jdbc.Driver。第二个字符集问题。导入时要注意表结构和数据使用的字符集是否为utf8mb4如果默认是latin1中文字段会乱码。如果SQL脚本里没有指定CHARSET最好在数据库连接参数里强制指定characterEncodingutf8。第三个外键约束导致删除数据失败。如果先删了父表再删子表或者反过来就会报“Cannot delete or update a parent row”。这就是为什么导入脚本时最好一次性执行整个脚本不要分句执行。导入完成后检查一下几个关键表里有没有数据。特别是用户表如果管理员密码是加密的你可以找找SQL脚本注释里有没有写明默认密码或者直接调用后端写好的密码加密方法来生成一个新密码再update进去。6.3 启动后端后端拿到手后直接用IDEA打开作为Maven项目导入等待依赖下载完成。然后修改application.yml里的数据源配置spring: datasource: url: jdbc:mysql://localhost:3306/school_manager?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver启动之前在IDEA里确认一下项目编译级别和JDK一致不然可能会出UnsupportedClassVersionError。启动成功后控制台会看到SpringBoot的启动日志最后一行一般是Tomcat started on port(s): 8080。这时候先别急着测接口用浏览器或者Postman访问一下后端的Swagger地址如果项目里集成了Swagger你会看到一个文档页面能在页面上直接做接口测试这个对于联调排查非常有价值。6.4 启动前端前端工程需要在命令行里先执行npm install安装依赖。这一步的网络状况和依赖版本决定成败。如果npm install很慢或者报错可以把镜像源切到国内建议用如下命令npm config set registry https://registry.npmmirror.com/再执行npm install就不会卡半天了。依赖安装完成后npm run serve或者npm run dev启动开发服务器。开发模式下前端默认跑在8080端口如果后端也占用8080就会冲突我遇到过很多次这个问题解决方案有两个要么改后端端口为9090要么改前端的devServer端口为3000。但改了前端端口之后记得要让前端请求的接口地址指向后端的实际地址。前端项目里通常有一个配置文件或者环境变量文件比如vue.config.js里的devServer.proxy配置或者src/utils/request.js里的baseURL配置。本地联调时最省事的方式是配一个代理让前端开发服务器的/api路径自动转发到后端地址这样就可以避免跨域问题。6.5 首次登录与自测清单登录之前看看接口文档里默认的管理员账号是什么。大部分项目初始账号是admin密码可能是admin123或123456。登录进去之后按下面的清单快速自测一遍管理员能看到全部菜单能新增学生、修改学生、删除学生退出登录再登录后删除操作被禁止。老师账号登录后能录入成绩但看不到学生管理菜单。学生账号登录后能选课、查成绩但改不了自己的学号信息。在不同浏览器里登录验证token的有效性和会话保持。如果某个功能点了没反应先看浏览器F12控制台有没有红色报错再看Network面板里对应请求的响应状态码。403通常意味着后端认为你没有权限或者token校验失败500通常是后端代码异常可以去后端控制台看堆栈日志。7. 常见问题与排查技巧实录7.1 端口被占用启动时报Web server failed to start. Port 8080 was already in use.这种情况百分之百是某个进程占用了8080。Windows下用netstat -ano | findstr 8080查出来占用端口的进程PID然后任务管理器结束它。或者最简单把后端端口改成8081前端代理相应改一下就行。开发阶段端口无所谓只要前端能调到后端就行。7.2 数据库连接失败报错常见的有这么几类第一个是Access denied for user rootlocalhost。这就是用户名密码或权限不对检查application.yml里的账号密码。第二个是Public Key Retrieval is not allowed。这是MySQL 8的一种安全机制在JDBC连接串末尾加allowPublicKeyRetrievaltrue就能解决。第三个是The server time zone value is unrecognized。解决办法是连接串里加serverTimezoneAsia/Shanghai。不同系统上的默认时区不同MySQL 5.7和8的表现也不一样加上时区参数永远是最省心的。7.3 跨域问题浏览器控制台报CORS或者Access-Control-Allow-Origin这就是跨域。表现是前端能发起请求但响应被浏览器拦截打开Network能看到那个请求是红色的Response里没有跨域相关头。跨域的本质是浏览器的同源策略协议、域名、端口三者有任一不同就会被视为跨域。本地开发时前端在8080后端在8081端口不同所以跨域。简单的办法是在后端加一个CorsFilter或者加CrossOrigin注解但更推荐的是用前端的proxy代理。它的原理是浏览器请求的是前端开发服务器的地址开发服务器再把请求转发到后端浏览器的视角里请求没有跨域后端的视角里请求来自同源服务器两边都满意。生产环境下前端部署到Nginx就用Nginx的proxy_pass把/api转发到后端服务地址思路一样。7.4 前端接口返回的数据格式不对有一种情况是前端表格没显示数据但Network里接口响应正常data也有数据。这时打开响应体看一眼十有八九是数据结构对不上。比如后端返回的是{ code: 200, data: { list: [...], total: 100 } }前端组件里写的是{ records: res.data.records, total: res.data.total }那records当然是undefined。这种问题不能只靠看代码找错直接把响应体结构和前端代码里引用的字段名对照一遍效率最高。7.5 编辑弹窗里回显数据改了不生效很多人遇到过点编辑弹窗里出现了数据但把某个字段改了以后提交发现后端收到的还是旧值。这个问题大多数出在表单的初始值只赋值了一次后续打开弹窗时使用的还是之前那个对象引用。解决办法也很简单每次打开弹窗时都用浅拷贝或者深拷贝生成一个新对象再赋给表单绑定的data。具体写法上用JSON.parse(JSON.stringify(row))做一个深拷贝就够了学生对象都是普通对象没有Date、函数这些会丢失的类型。7.6 分页查询的数据与总条数对不上这种情况往往是SQL里用了多表join统计总条数时没有去重或者where条件里的关联字段造成了数据膨胀。比如学生表和选课表join后一个学生选了三门课就会变成三行分页时会出现同一个学生出现在不同页的情况。解决办法是查询列表用join但是分页之前要先按主表的id做去重统计或者直接用子查询SELECT COUNT(DISTINCT s.id) FROM student s LEFT JOIN student_course sc ON sc.student_id s.id WHERE s.class_id #{classId}这个SQL是MyBatis里写的最典型也最爱错的点每次做完记得用日志打印出来的SQL去数据库里手工执行一遍看看count和实际列表条数是否一致。7.7 后台上传头像失败如果系统里有文件上传功能比如学生头像最容易出现的报错是multipart请求被拦截、文件保存路径不存在、响应头里没有文件访问地址。排查顺序是先看后端的application.yml配了没有文件上传大小限制再看有没有创建保存上传文件的目录再看前端图片预览的URL是否加了静态资源映射。SpringBoot默认的静态资源路径是static和public如果是自定义上传目录要么用resources映射要么单独提供一个获取文件的接口。8. 拿下源码后如何把它包装成一份漂亮的毕设有人拿到项目后直接原封不动交上去这是大忌。导师一眼就能看出这是哪来的更重要的你在答辩时会被追问到“这个功能怎么实现的”“某张表为什么这样设计”自己没跑过、没改过很容易漏馅。正确的做法是在原项目基础上做二次开发至少做到这几件事第一加一个原项目没有的小模块。比如原系统没有公告管理你可以加一个公告发布模块包含公告的增删改查、置顶、学生端公告展示、已读未读状态。这种模块技术难度不高但从论文角度可以写好几页。第二把项目里某个模块改造得更深入一点。比如成绩管理原项目可能只做简单的录入和查询你可以扩展成绩的统计分析按班级统计平均分、及格率生成柱状图、饼图。这里会用到前端图表库如ECharts后端只需要多写几个聚合查询接口。这个改造能成为一个论文要点题目可以写“基于SpringBootVue的校园管理系统成绩分析模块设计与实现”。第三给项目加一层更完整的操作日志。原项目大多没有操作日志你可以结合AOP做一个切面在用户执行增删改操作时自动记录操作人、操作时间、操作类型、操作内容。这也是一个非常有价值的二次开发点。论文写这部分的时候注意一个技巧先写设计再写实现。不要只贴代码截图要先讲表结构、接口设计、前后端交互流程再重点截图实现效果。篇幅一下就充实了还显得有设计感。9. 平时容易忽略但答辩时老师会追问的几个点这里我列几个高频追问提前准备好回答答辩就不会慌。“你的登录认证怎么实现的”答前端登录后后端生成JWT返回给前端前端存储并在请求头携带后端拦截器对非白名单接口做token校验再通过角色比对控制权限。“为什么用前后端分离”答前端开发和后端开发可以并行部署灵活前端可以独立部署到Nginx接口可以给多端复用职责边界清晰。“数据库表为什么这样设计”答学生表、教师表和用户表分离既统一了登录账号体系又让业务表独立扩展课程和学生的多对多关系通过中间表解决。“分页是怎么实现的”答用了MyBatis-Plus的分页插件传入当前页码和每页条数插件自动生成COUNT查询和LIMIT语句返回分页对象。“如果用户量变大这个系统会有什么瓶颈”答初期瓶颈会在数据库的连接数和查询性能可以考虑做缓存、索引优化、读写分离。导师听到你能说出以数据库为瓶颈的定位就说明你有基本的性能意识。这些问题不需要长篇大论每个讲到点子上就够了。根据我个人做这类项目的体会最值得投入时间的地方不是把代码跑通而是把设计逻辑彻底吃透。你可以把前面提到的表关系、认证流程、分页实现、权限控制这些内容画成图、写成笔记做到不用看代码也能给导师讲清楚整个系统怎么跑起来、每个模块怎么运作。到这一步这个项目才是真正属于你的东西源码本身反而只是起点。