SpringBoot+Vue3+MyBatis实现兼职平台:从数据库设计到部署踩坑全记录

发布时间:2026/10/21 14:12:48
SpringBoot+Vue3+MyBatis实现兼职平台:从数据库设计到部署踩坑全记录 1. 这个系统到底做什么先想明白业务再写代码1.1 兼职平台的核心业务闭环最近我把一个学生项目的“蜗牛兼职网”从零到一完整实现了一遍用的技术栈是 Java SpringBoot Vue3 MyBatis数据库是 MySQL前后端完全分离。这套东西做完之后我有一个很直观的感受它名义上是个“毕业设计/课程设计”级别的项目但涉及的技术面和业务完整度已经足够帮你理清一整条企业级开发的套路了。先把这个项目的业务边界说清楚。所谓“兼职网”本质是一个信息撮合平台连接两端一端是有兼职需求的企业/雇主另一端是想找兼职的学生或社会人员。平台上最核心的动作是雇主发布职位信息兼职者浏览、检索、投递简历雇主筛选后录取被录取的人完成兼职任务最后平台结算报酬。再加上用户注册登录、个人信息维护、职位收藏、浏览历史、后台管理这些外围功能一套“蜗牛兼职网”就形成了一个可闭环的微型业务生态。很多同学拿到这个题目后第一反应是“不就是个 CRUD 吗”真动手才发现完全不是那么回事。光是一个“发布职位”的流程就牵扯到表单校验、富文本内容存储、薪资字段格式化、城市区域级联选择、上下架状态管理再往后做投递又牵扯到同一用户不能重复投递同一个职位、状态流转只能单向推进待处理→已查看→已录用→已结算等约束。说到底复杂的东西不在某个单独功能而在各个模块之间的交互规则。1.2 技术选型背后的理由这个项目选 SpringBoot Vue3 MyBatis MySQL绝不是一个随意的组合它恰好覆盖了当前国内中小型项目最主流、也最容易被面试官追问的一套技术栈。SpringBoot 解决的是后端基础设施问题。用 SpringBoot 2.x 起步内置 Tomcatstarter 依赖一拉一个可独立运行的 jar 包就能把整个后端跑起来。相比传统 SSMSpring SpringMVC MyBatis的 XML 配置地狱SpringBoot 用自动配置把大量样板工作消掉了这对课程设计和快速上手都是最友好的选择。Vue3 则是目前前端框架里的绝对主流。Vue3 比 Vue2 最大的变化在于 Composition API 和响应式系统的重构。在蜗牛兼职网这种中后台展示混合场景里Vue3 配合 Vite 构建工具开发体验明显比 Vue2 Webpack 轻快很多。而且 Vue3 生态已经非常成熟像 Element Plus 这类组件库对快速搭建后台管理界面极其顺手。MyBatis 是另一个有意思的选择。很多人纠结“为什么不用 MyBatis-Plus为什么不用 JPA”我的答案是MyBatis 的 SQL 可控性在课程设计答辩时反而是加分项。你可以拿着 xml 里的 SQL 当场讲清楚“这条语句为什么用 LEFT JOIN”“这个子查询能不能优化”这是 JPA 自动生成 SQL 很难做到的。如果项目里需要的恰好是几张表的关联查询和统计报表MyBatis 会让你在写 SQL 时对性能有更强的掌控力。MySQL 作为存储层没有悬念5.7 或 8.0 都行8.0 注意驱动和时区问题就好了。整个技术栈组合起来覆盖面广却不花哨做出来的东西既能看到完整效果又有充足的技术点可以做面试表达。2. 数据库设计与关键表结构地基不牢后面全是坑2.1 六张核心表怎么划分蜗牛兼职网的第一版数据库我设计成六张核心业务表加两张辅助表。核心业务表分别是用户表t_user、职位表t_job、投递记录表t_delivery、职位收藏表t_favorite、简历表t_resume、订单结算表t_order。辅助表是职位类别表t_category和管理员表t_admin。用户表是所有业务的入口字段别贪多够用就行。我用的几个关键字段是id、username用户名、passwordBCrypt 加密后的密文、phone手机号、role角色标识0-普通用户1-雇主2-管理员、status状态0禁用1启用、create_time、update_time。这里有个容易踩的坑很多同学喜欢用自增 id但分页和相关联插入时 MyBatis 需要回填主键所以 service 层一定要开启 useGeneratedKeys否则插入完拿不到 id 后续逻辑全断。职位表字段略多它是整个项目信息密度最高的一张表我列一下字段名类型说明idbigint主键titlevarchar(100)职位名称category_idint分类外键salary_mindecimal(10,2)最低薪资salary_maxdecimal(10,2)最高薪资cityvarchar(50)工作城市addressvarchar(255)详细地址job_typetinyint兼职类型日结/周结/月结detailtext职位描述publisher_idbigint发布者用户IDstatustinyint1-招聘中0-已下架view_countint浏览次数create_timedatetime发布时间薪资字段必须用 decimal(10,2)千万别用 float/double面试时如果被问到精度问题会非常难看。日结/周结/月结这种枚举语义的字段用 tinyint 存比用 varchar 省空间而且查询条件写起来干净。投递表是连接职位和用户的桥梁核心设计是一个唯一约束。组合唯一索引就建在 user_id job_id 上这样可以在数据库层面直接挡住重复投递不用在应用层先查一遍再加锁。表的字段包括id、user_id、job_id、resume_id投递时用的简历、status0-待处理1-已查看2-已录用3-已拒绝4-已取消、apply_time、update_time。状态流转是后面业务代码里的重头戏数据库层面用 status 字段配合一个简单的校验方法就可以管住非法流转。简历表主要是展示型数据采用和用户表 1:1 设计字段包括自我介绍、教育经历、工作经历、技能标签、期望薪资范围等。这里我用了非常大的 text 字段去存教育经历和工作经历其实在规范化设计里应该拆表但考虑课程设计的数据量级别单表单存反而让前后端联调简单很多这也是实际开发里常见的取舍。订单结算表是为了把“兼职完成后怎么给钱”这个闭环落地。字段包括 id、job_id、user_id、amount结算金额、status0-待确认1-已确认2-已完成、pay_time、备注。这张表同时记录了订单归属和金额状态后续做简单的数据统计比如平台累计发放兼职报酬就靠它。2.2 防坑细节字段类型、外键、时间字段数据库设计里有几个细节直接影响后面代码的写法我单独拎出来说一下。第一时间字段统一用 datetimeJava 端使用 LocalDateTime 对应。不要用 timestamp 存到 2038 年就溢出了虽然对课程设计没影响但这是个专业性的体现。MySQL 8.0 连接时还要在 JDBC URL 上加上 serverTimezoneAsia/Shanghai我这次用 8.0.33 的驱动没加这个参数直接报异常后面会详说。第二外键到底建不建我的方案是所有表只建普通索引不建物理外键约束。理由很简单物理外键在删除和更新时的连锁反应很难控制而且在分库分表、迁移数据时是累赘。业务关联的完整性在 service 层把好关就行。但索引一定要建尤其是 user_id、job_id、publisher_id 这类高频查询条件的字段。加索引的成本极低收益在数据量上来之后天差地别。第三varchar 长度不要一刀切。用户名定 32、手机号定 11、城市定 50职位标题定 100 就够了。很多同学喜欢所有字符串都 varchar(255)结果索引长度超标不说纯属偷懒。第四注意删除策略。用户表和职位表不建议物理删除用 status 或一个 is_deleted 字段做逻辑删除。兼职市场里经常有用户投递记录被撤销的诉求逻辑删除保留数据还能给后续做“浏览历史”和“行为分析”留余地。我在实现中用 MyBatis 的 update 代替 delete凡是 mapper 里的“删除”都是 UPDATE 语句把状态改成 1效果完全不一样。3. 后端关键模块实现从登录鉴权到业务逻辑3.1 JWT 认证怎么落地蜗牛兼职网的用户认证我用的 JWTJSON Web Token方案。选它而不是传统的 Session 是因为前后端分离的项目天然适合无状态认证后端不存会话前端拿到 token 后在请求头里携带即可跨域也好处理部署时也不需要考虑 Session 同步。JWT 的落地代码不复杂核心是引入 jjwt 依赖写一个 TokenService 负责生成和解析 token再写一个拦截器把需要登录的接口保护起来。token 里我放了三个信息用户 id、用户名、角色。过期时间定为 24 小时不要为了省事传“永久有效”后面你会后悔。// TokenService 核心逻辑 public String generateToken(Long userId, String username, Integer role) { return Jwts.builder() .setSubject(username) .claim(userId, userId) .claim(role, role) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() 86400000L)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); }拦截器方面我用的是 Spring MVC 的 HandlerInterceptor在 preHandle 方法里解析 Authorization 头。这里有两个实操心得一是解析失败要区分“token 过期”和“token 非法”两者返回的 HTTP 状态码不一样前端才好决定是弹提示还是跳登录页二是凡是公开接口如登录、注册、职位列表必须在 WebConfig 里放行后台管理接口还要单独校验管理员角色不支持简单的“非空即通过”。关于 password 存储务必用 BCrypt。Spring Security Crypto 模块里的 BCryptPasswordEncoder 可以直接引进来用每次加密结果都不一样数据库里存的是带盐的哈希。千万别用 MD5面试官看到 MD5 基本都会追问而且现实里 MD5 的确已经不安全了。3.2 职位发布与检索的 SQL 细节职位的发布相对简单就是往 t_job 插入一条记录但有一个小细节需要注意——插入时要把 detail 这个 text 字段做 XSS 过滤。前端很可能会给职位详情用一个富文本编辑器用户输入的内容如果直接入库再回显等于给自己留了一个存储型 XSS 漏洞。我后端的处理方式是封装了一个 HtmlUtil对

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询