拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Vue前后端分离客户关系管理系统(CRM)设计与实现

SpringBoot+Vue前后端分离客户关系管理系统(CRM)设计与实现 先从标题说起吧。这两年总有人问我“客户关系管理系统怎么做”尤其是一堆做毕业设计的学生和刚转Java岗的新人问的最多的就是“基于SpringBootVue这种前后端分离的项目到底怎么从零搭出来”。我前阵子刚完整带人做了一套公司客户关系管理信息系统从需求梳理到数据库设计再到前后端联调和部署整条链路走下来踩了不少坑也沉淀了不少心得。这篇博客不聊虚的就围绕这套系统的设计与实现把我实际操盘过程中认为最关键的部分全拆开讲清楚为什么这么选型、数据库该建几张表、后端认证怎么做、Vue前端怎么组织、联调时会遇到哪些问题、部署生产环境要注意什么。不管你是准备拿这个题目做毕设还是公司里真需要一套轻量级的CRM这份内容都能给你一个可以直接照着走的完整方案。1. 项目整体设计与技术选型解析1.1 核心需求盘清CRM到底在管什么拿到题目别急着写代码先把业务逻辑理顺。客户关系管理系统英文叫CRM本质上就是把公司的客户资源、销售跟进动作、商机转化过程全部线上化让管理层能看到每一个客户从线索到成交的完整链路。我在这套系统里明确了三类角色超级管理员负责系统配置和用户管理销售员工负责录入客户、记录跟进、维护商机销售经理则要看到整个团队的客户数据看板、跟进效率报表。围绕这三个角色核心功能模块划分为五个大块客户管理客户档案、客户公海、客户分配、联系人管理一对一客户的联系人列表、跟进记录每次拜访或电话的记录时间线、商机管理不同阶段的转化漏斗、合同管理成交后的合同登记。辅助模块还有数据统计看板、消息通知、系统权限管理。这套划分基本覆盖了中小型公司CRM的80%常见场景做毕设或者做企业内部工具都够用。如果业务再复杂一点可以往后追加工单模块或售后模块但第一版先把主链路跑通最重要。1.2 技术栈选型与选型理由技术选型是题目里给定的SpringBootVue我在实际实现中配合选用了这样一套组合技术项选型选型理由后端框架SpringBoot 2.7.x快速构建、自动装配、生态成熟内置Tomcat省去额外配置持久层框架MyBatis-Plus开发效率极高内置分页插件和条件构造器减少样板代码数据库MySQL 8.0中小型系统首选免费稳定InnoDB事务机制可靠缓存与验证码Redis存验证码、Token生命周期管理提升并发处理能力前端框架Vue 2.7 Element UIVue生态稳定Element UI组件库完整适合后台管理系统快速开发状态管理Vuex管理登录用户信息、侧边栏菜单状态、全局共用数据HTTP客户端Axios统一处理请求拦截、响应拦截、Token注入等认证方式JWT前后端分离场景下天然合适无状态认证、跨域友好接口文档Swagger / Knife4j联调效率提升明显自测后端接口非常方便项目构建Maven 3.8大多数Java团队的标准构建工具这里解释一下几个关键选择背后的逻辑方便新手理解为什么是它们而不是别的。SpringBoot之所以成为主流最核心的点是自动装配机制和起步依赖。以前用SSM框架组合光搭环境就需要写大量XML配置一个配置错误就可能折腾一整天。SpringBoot通过内部的starter模块把常用场景的依赖全部打包好比如引入spring-boot-starter-web就自动带上了SpringMVC和内置Tomcat再配合EnableAutoConfiguration扫描并装配项目的结构瞬间简化了一大截。而且SpringBoot的社区资料极其丰富遇到任何问题基本都能在Stack Overflow上搜到答案。Vue在后台管理系统这个场景下优势也很明显。一个纯Java工程师如果去写JSP加jQuery页面交互一多逻辑就会变得混乱维护成本极高。Vue的组件化思想和双向绑定让页面状态管理变得直观。配合Element UI表格、表单、分页、弹窗、穿梭框这些后台系统的高频组件只要引入后就能直接用开发速度翻倍。选Vue2而不是Vue3主要是考虑到Element UI等老牌组件库对Vue2的兼容性最好对毕设或者公司内部工具这个量级的项目来说稳定性比追新更重要。当然如果你愿意Vue3Element Plus组合也完全可行核心思路不变。MyBatis-Plus为什么值得推荐而不是用原生MyBatis对比一下原生MyBatis写一条简单查询需要写mapper接口、写映射XML、再写SQL语句动作量很大。而MyBatis-Plus内置了通用CRUD方法继承一个BaseMapper接口后单表的增删改查不需要写一行SQL。加上它条件构造器QueryWrapper把动态拼SQL这个场景做成了链式调用代码看起来非常清爽。分页查询配合分页插件一行代码就能完成分页。2. 数据库设计与核心模块拆解2.1 数据库表设计思路与核心表结构数据库是整个系统最不能将就的一部分前期表设计得不好后期写代码时就会出现各种别扭比如字段含义不明、冗余复杂、统计SQL越写越痛苦。我设计这套CRM系统一共规划了8张核心业务表简单列一下用户表sys_user、角色表sys_role、客户表crm_customer、联系人表crm_contact、跟进记录表crm_follow_record、商机表crm_business、合同表crm_contract、登录日志表sys_login_log。这几张表里最关键的是客户表我把核心字段设计成了这样字段名类型说明idbigint主键自增customer_namevarchar(100)客户名称industryvarchar(50)所属行业customer_leveltinyint客户等级如1重要/2普通/3潜在sourcevarchar(50)客户来源如线上广告、转介绍owner_idbigint归属人ID当前负责销售的员工IDstatustinyint客户状态1公海/2已分配/3跟进中/4已成交next_follow_timedatetime下次跟进时间create_timedatetime创建时间update_timedatetime更新时间deletedtinyint逻辑删除标记0未删除 1已删除这里特意加了owner_id和status两个字段它们是客户公海和客户分配逻辑的基础。所谓公海池就是未被销售认领或已被回收的客户池任何人可以从中领取客户。这个机制能有效防止客户资源被个别员工囤积而无人跟进很多公司真正的运营规则也依赖这个功能。为了防止误删数据所有业务表都采用逻辑删除而不是物理删除查询SQL里统一加上deleted 0这个条件即可。create_time和update_time在代码里用MyBatis-Plus的自动填充注解处理插入时自动写入时间更新时自动刷新不需要每次手动set当前时间。跟进记录表的设计也同样需要花心思。这张表是CRM中产生数据量最大的表字段包括所属客户ID、跟进人ID、跟进方式电话/拜访/微信、跟进内容、下次跟进时间、跟进结论。其中“下次跟进时间”这个字段特别关键因为围绕它可以做后续的待办提醒和客户回收判断。2.2 权限模型与核心流程的实现要点权限管理我采用的是经典的RBAC模型即用户-角色-权限三层关系。用户表关联角色表角色表关联权限表。前端根据登录用户的角色动态渲染侧边栏菜单后端在每个需要权限的接口上通过自定义注解方式校验角色权限。具体实现上权限数据表包含角色表和菜单权限表菜单权限表记录每个页面按钮的唯一标识符例如“customer:add”、“customer:assign”等。用户在登录后一次请求后端会根据其角色把对应的权限集合返回给前端。前端拿到权限列表后首先在路由层面控制哪些页面能进再通过结合v-permission指令控制页面内按按钮显隐。这个方案的优点是第一层可见可防第二层按钮级权限精细控制。这里要特别注意一个问题前端隐藏菜单不意味着后端接口就安全所有接口必须再做一层后端鉴权不能只依赖前端隐藏。因为在前后端分离场景中任何接口都是可以通过网络请求直接访问的前端隐藏只解决体验问题真正的数据安全完全靠后端把关。CRM还有一个独特的权限场景数据权限。简单说普通销售只能看自己名下的客户销售经理能看全部门的客户数据而超级管理员能看到所有租户或者整个公司全部数据。实现思路也很直白在查询客户列表时后端会根据当前用户的角色信息在SQL条件中自动拼接上归属人过滤条件。如果角色是普通销售则强制加上owner_id 当前用户id如果是经理则可以加上dept_id 当前用户部门id。这个拼接逻辑要放在service层统一处理不要散落到各个controller里否则后期非常难维护。3. 后端SpringBoot核心实现与踩坑记录3.1 项目工程搭建与自动装配要点SpringBoot项目创建本身很傻瓜式用IDEA的Spring Initializr直接勾选依赖即可。我创建项目的时候选择了Java 8、SpringBoot 2.7.18、MySQL Driver、MyBatis-Plus相关依赖。这里有一个容易踩的坑SpringBoot的高版本3.x及以上要求JDK 17才能运行但很多学校或公司的服务器Java环境还是8所以如果不确定服务器环境尽量用2.7.x版本兼容性最好。项目内部的包结构我统一按照职责分层controller负责接口定义、service负责业务逻辑、mapper负责数据库操作、entity是数据库表对应的实体类、common放统一返回结果和异常处理、config放配置类、utils放工具类。这样的包结构看起来千篇一律但恰恰是团队协作时沟通成本最低的方式新成员看一眼就知道东西在哪。在实际开发中我特别注意了SpringBoot自动装配原理的理解。简单说SpringBoot启动类上的SpringBootApplication组合注解里面包含了EnableAutoConfiguration它会在项目启动时扫描所有依赖jar包里的META-INF/spring.factories配置文件把其中声明的配置类全部加载进来再通过条件注解如ConditionalOnMissingBean、ConditionalOnProperty判断当前环境中是否满足条件满足才装配。比如在引入了Redis依赖时自动配置类读取到spring.redis.host配置就自动创建一个RedisTemplate实例放到容器中。理解这个机制最大的价值在于遇到“组件引了但是没生效”的奇怪问题时能快速定位到是不是自动配置被某个条件拦住了。SpringBoot还提供了一招排查利器在配置文件中加上debugtrue启动时控制台会输出全部自动配置的报告哪些生效、哪些被排除一目了然。这个功能虽然不起眼但帮我解决过好几次环境类疑难杂症。3.2 登录认证与JWT完整流程前后端分离架构下Session机制用起来很不舒服。主要原因是后端的Session存在服务器内存里而前后端分离后前端可能部署在另一个域名甚至CDN上每次请求要拿着Cookie去匹配Session跨域场景下Cookie的处理又格外繁琐。所以我选择了JWTJSON Web Token来做认证。JWT的核心结构是Header、Payload、Signature三段。Header里说明加密算法Payload里存放用户的id、用户名、角色信息Signature是服务端用密钥对前两部分签名后的结果。用户登录成功后后端生成一个JWT串返回给前端前端把它存到本地存储里之后每发请求时在请求头加上Authorization: Bearer 令牌后端通过拦截器解析校验。在我的系统中实现流程分为几步走第一步登录接口接收用户名和密码调用PasswordEncoder的matches方法比对密文密码同时校验验证码是否来自Redis中保存的值。登录成功后生成JWT密钥通过Value(${jwt.secret})注入。第二步写一个JwtInterceptor实现HandlerInterceptor接口重写preHandle方法。在这个方法中从请求头取出Token解析成功就把用户信息放入ThreadLocal解析失败直接返回401状态码。使用ThreadLocal存储当前登录用户非常关键后面任何一层代码都可以拿到“当前操作的人是谁”做客户归属判断、跟进人写入都很方便。第三步注册拦截器。注意配置时不拦截登录接口、获取验证码接口和Swagger文档接口这几个白名单路径。同时要在同事联调时记得把OPTIONS请求放行因为浏览器发送跨域预检请求时不会携带高自定义请求头如果拦截了OPTIONS前端会一直报跨域错。JWT方案里有个小坑提醒一下JWT无法强制失效。如果踢用户下线或者要修改密码后让旧的Token立刻失效Session方案直接删掉Session数据就行了JWT做不到这一点只靠密钥校验不依赖任何存储。常见的解决办法就是在Redis里存一份“有效Token白名单”每次校验拦截器先检查是否在Redis中不在就直接拒绝。我这套系统里就是用这个方案做的效果很理想。3.3 客户公海与回收机制的SQL实现客户公海功能可以说是CRM系统的一个小亮点也是面试官最喜欢追问的业务点之一。公海设计的核心逻辑就两条规则一是超过一定天数没有跟进记录的客户自动流入公海二是公海中的客户可以被其他销售认领。代码实现上用一个定时任务每天凌晨执行一次。以SpringBoot里的Scheduled注解实现定时任务消费逻辑大致是查询所有状态为已分配status2、跟进中的客户且最近一次跟进时间与当前时间差超过30天把这些客户的owner_id置为空、status置为1也就是扔回公海。实际写SQL时用MyBatis-Plus的UpdateWrapper操作即可。由于涉及跨表操作也可以在Mapper里写原生SQLUPDATE crm_customer c LEFT JOIN ( SELECT customer_id, MAX(create_time) AS last_follow_time FROM crm_follow_record GROUP BY customer_id ) f ON c.id f.customer_id SET c.status 1, c.owner_id NULL WHERE c.status 2 AND c.deleted 0 AND ( f.last_follow_time IS NULL OR f.last_follow_time DATE_SUB(NOW(), INTERVAL 30 DAY) )这个SQL的含义是对每个客户如果没有任何跟进记录或者最近一次跟进时间距今超过30天就自动流入公海。这样处理比在应用层查出来再逐条更新要高效得多一台普通配置的服务器也能扛住几万级客户表的数据量。如果是更大数据量可以分批扫描避免一次UPDATE锁太多的行影响线上正常业务。公海认领还有一个并发问题值得说说当一个客户同时被两个销售认领时如何保证只有一个成功最稳妥的做法是在UPDATE的SQL里带上状态条件即“只能在客户状态仍为公海时完成认领”并且让提交操作在同一事务内以受影响行数是否为1判断是否成功。这是典型的乐观锁思想不需要额外引入分布式锁就能解决99%的常见场景。3.4 统一返回结构与全局异常处理后端接口没有一个统一的返回结构前后端联调的时候就是灾难现场。一会儿这个接口返回一个JSON对象一会儿另一个接口返回一个字符串前端处理起来极度难受所以我在项目刚开始就定好了统一返回类。这个返回类的结构我用的是最通用的codemessagedata三件套。code为200表示成功400表示参数错误401表示未认证403表示无权限500表示服务器异常。前端在Axios拦截器里统一判断code不是200就弹出错误提示这样前端代码看起来会很清爽。全局异常处理是通过一个RestControllerAdvice类实现的。在这个类里分别处理自定义业务异常、参数校验异常、系统未知异常。业务异常在service层抛出时携带自定义异常码和提示信息最后由全局处理器统一把信息包装为返回结构输出。这里有个容易被忽略的小细节开发期为了方便排查问题堆栈信息可返回给前端但生产环境必须把异常详情屏蔽只返回模糊的“系统繁忙”提示防止把敏感的业务数据或表结构信息暴露给用户。我一般通过配置中心的开关来控制或者用一个profile区分环境。4. 前端Vue核心实现与前后端联调4.1 Vue工程创建与工程化配置前端这块一开始也用Vue CLI脚手架创建项目运行vue create crm-web后选择Manually select features勾选Router、Vuex、Sass预处理这些选项。安装Element UI用npm i element-ui -S然后按需引入组件要注意版本兼容性其实最简单的不折腾的办法是全量引入打包体积大一点但开发效率足够高。创建完成后工程的标准结构是src/api放所有接口请求封装src/router放路由配置src/store放Vuex相关模块src/views放页面组件src/components放公共组件src/utils放工具函数。我在实际开发中还单独建了src/directive目录放按钮权限的自定义指令。前后端分离开发中最容易卡壳的就是跨域问题。我在开发阶段直接用Vue CLI提供的代理功能解决在项目根目录的vue.config.js文件里配置module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }这样前端所有以/api开头的请求都会代理到后端8080端口的服务上绕过了浏览器非同源限制。但要注意这只能是开发阶段的辅助手段生产环境还是要靠Nginx反向代理我在后文部署章节会详细说。4.2 组件化设计与状态管理心得页面组件化之前我先把系统的布局框架定下来。整体采用的是后台系统最常见的布局左侧固定侧边栏放菜单右侧上方是顶部导航栏中间是内容区域。这个布局可以先写成Layout一个总组件之后所有页面都在内容区通过路由切换。核心页面拆分为客户列表页、客户详情页、客户公海页、商机管理页、数据看板页、系统用户管理页。每个页面内部再拆子组件比客户详情页里面的跟进记录时间线组件、合同信息组件都单独抽出来。这里有一个经验抽组件时不要为了“组件化”而过度拆分一个小组件被两三个页面复用时拆分才有价值只在一个页面出现的大段内容没必要强行抽离否则生成的Props和事件传递反而增加维护负担。Vuex在这一套系统里主要管理token、用户基本信息、权限菜单三个全局变量。把token存在Vuex的同时还要同步存到localStorage或者sessionStorage里这么做的原因是在页面刷新的时候Vuex内存数据会全部丢失必须从本地存储恢复登录态。在路由跳转前router.beforeEach全局前置守卫里判断本地是否有token如果存在就放行不存在就跳到登录页。配合动态路由登录后根据后端返回的权限菜单实时拼接动态路由调用router.addRoutes注册用户可见页面。记录一个小坑动态路由在刷新页面后偶尔会失效当时排查后发现是因为动态路由生成时机依赖后端的请求结果刷新时请求顺序不一致导致路由还没注册完毕页面就已经渲染了。解决方案是在入口的main.js里改成一个异步初始化流程先发请求拿用户信息和菜单再new Vue()并挂载路由确保首次渲染前路由已注册完整。这个坑如果不注意用户按F5刷新就会跑到404页面。4.3 Axios封装与前后端联调经验Axios如果不在拦截器层面统一处理前端代码就会被大量的重复逻辑淹没。我在src/api/request.js里做了统一封装import axios from axios const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }, error Promise.reject(error)) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { this.$message.error(res.message || 系统异常) return Promise.reject(new Error(res.message)) } return res.data }, error { if (error.response error.response.status 401) { localStorage.removeItem(token) location.href /login } return Promise.reject(error) } )这里几个细节是实战经验沉淀过的。响应拦截器要在code不是200时直接弹错误提示前端页面就不用每个接口都做一遍错误分支处理。对401响应要统一清理token并跳回登录页防止用户带着失效Token继续操作。超时时间设成10秒很多后台查询接口如果数据量大默认的60秒太磨叽10秒能快速暴露问题。联调阶段最容易出现的问题是后端接口返回结构跟前端预期不一致。解决方案现在回看很简单写接口文档自测方便可以用Swagger生成接口文档还可以在Swagger界面直接调试接口验证参数格式。另外一个非常实用的经验就是前端在请求时开启浏览器的Network面板直接看请求参数和响应内容百分之九十的联调问题几秒钟就能定位到是前端参数没传对还是后端返回结构不对。4.4 前端数据看板与图表统计功能CRM系统肯定要包含统计看板不然销售经理没法快速掌握团队的转化情况。这里选用的图表库是ECharts在Vue项目里通过安装echarts和vue-echarts就能以组件的方式使用。看板页面里我放了四个核心图表客户来源饼图、客户等级分布漏斗图、每销售订单金额柱状图、近期成交趋势折线图。这些图表的数据来源全部通过后端统计接口返回。统计接口写起来要注意SQL聚合技巧尽量让数据库完成聚合和分组工作而不是把明细数据全量捞出后在Java内存里算。比如统计每个销售名下客户数量一条SELECT owner_id, COUNT(*) FROM crm_customer WHERE deleted 0 GROUP BY owner_id即可完成。再配合一个日期筛选条件用DATE_FORMAT(create_time, %Y-%m-%d)来按天分组。图表组件还有一个兼容性细节后端返回的时间字段建议统一格式化为字符串再返回如果直接返回Java的Date对象序列化后经常出现时间加减8小时或者格式乱七八糟的问题。可在后端的JSON序列化配置里统一指定时间格式用spring.jackson.date-format和time-zone两行配置就能解决。5. 常见问题与排查技巧实录5.1 后端开发中的高频问题速查先说启动层面的问题。很多刚接触SpringBoot的人导入项目后一启动就报“无法识别Bean”或者“端口被占用”。端口被占用处理起来最简单命令行输入netstat -ano | findstr :8080找到占用进程杀掉即可。但“Bean找不到”这类问题需要有一点排查思路先看是缺依赖还是没被扫描到如果用了MyBatis-Plus一定要确保MapperScan正确指向了mapper包或者是每个Mapper接口上加了Mapper注解。数据库连接失败也是高频报错。报错信息一般是Access denied for user或者Communications link failure。前者检查用户名密码和数据库授权后者检查MySQL服务是否启动、连接地址是否正确、端口是否能连通。有一个比较容易忽略的坑就是数据库连接地址里的useSSLfalse参数。MySQL 8.0版本默认开启SSL而本地开发MySQL服务未必配置了证书连不上时一脸懵加上useSSLfalseserverTimezoneAsia/Shanghai两个参数就通了。再一个经典问题是Redis连接失败导致登录接口无法获取验证码。首先要确认Redis服务确实启动了redis-cli ping输出PONG才正常。其次SpringBoot连接Redis默认用的localhost:6379如果没有改配置但实际服务在别的环境就会报Unable to connect to Redis。这类问题都要先看配置文件再抓服务日志。接口联调时经常出现前端传了JSON后端却接收不到的情况。绝大多数原因是前端没有设置请求头中的Content-Type为application/json或者后端用了RequestBody接收对象但前端传递的是form表单格式。我一般在Axios封装里统一把Content-Type设置为application/json后端接口统一用对象接收这样规则清晰。5.2 前端开发中的高频问题速查前端最经典的问题就是“明明接口返回正常页面就是不显示数据”。排查思路先看数据结构很可能后端返回的data是一个对象而前端代码按数组方式去遍历了。建议前端在联调时先console.log一下接口返回的数据结构再继续写渲染逻辑能省下大量翻工时间。路由刷新404问题我在上文提到过一次这里再给一个直接了当的解决方案。问题根源在历史模式路由依赖后端配合。生产环境中Nginx配置加上这样一段location / { try_files $uri $uri/ /index.html; }这样当用户直接访问某个子路由地址时Nginx会把请求回退到index.html由前端的路由接管页面渲染。如果不配刷新非首页时就会出现404这个问题几乎每个Vue后台项目都会遇到非常典型。Element UI的表格组件在遇到字段值为null时会显示空白。很多业务场景希望显示“-”之类的占位符可以通过formatter或者模板插槽解决在模板里判断row.field || -即可。这类小细节做多了页面整体质感和交互体验会好很多。关于图片上传。CRM系统里客户头像或资质文件上传会遇到跨域问题此时两种方案一是后端开放相关的上传接口接口CORS跨域策略内置常用的跨域过滤器二是通过Nginx把上传和接口请求转发到同一域名下从根源上避免跨域产生。生产环境下推荐第二种方案浏览器兼容性更好。5.3 多环境配置与上线部署实战项目开发完要上线这一步也是很多新手最容易翻车的地方。本地运行得好好的部署到服务器就各种“水土不服”多半原因是环境配置不一致。我的配置方案是利用SpringBoot的多Profile机制把配置拆成三份application-dev.yml、application-test.yml、application-prod.yml。公共配置放到application.yml比如MyBatis-Plus配置、JWT密钥等不同环境只覆盖自己需要修改的那部分。生产环境的关键配置有几项要格外小心MySQL地址改成生产内网地址、Redis密码必须设置、日志级别调成INFO、关闭Swagger暴露、数据库连接池必须配置上最大连接数限制。特别是Swagger生产环境如果开着等于把全套接口文档公开给任何人属于严重的安全隐患。部署方式我用的是在服务器上安装JDK、MySQL、Redis、Nginx然后把后端打包为jar文件通过java -jar crm-server.jar启动。为了让进程在后台稳定运行建议添加一个systemd服务文件来托管Java进程保证服务器重启后系统自动拉起不需要手动登录去敲命令。前端打包则分三步在本地执行npm run build生成dist目录把dist目录里的所有文件上传到服务器指定目录然后在Nginx中配置指向该目录的server块。这里提醒一下上传前记得确认构建产物里的接口地址前缀是生产环境地址如果打包时忘了修改环境变量配置上线后接口会全部请求到本地开发地址造成“白屏”现象。数据库备份是上线后必不可少的环节。我在生产服务器上通过crontab定时任务每天凌晨执行一次mysqldump把备份文件存放到独立目录保留最近7天的备份。恢复时只需要这条命令mysql -u用户名 -p密码 数据库名 备份文件.sql。没用过备份机制的人可能觉得多此一举但一旦哪天数据误操作被删了你就知道备份有多么救命。最后分享几个实操心法整套系统从前到后跑完后我最大的感受是做一个管理系统业务梳理和技术实现各占一半如果只看重代码写得多炫而业务逻辑本身有问题系统做出来也是废的。我建议准备用这个项目做毕设或者入职练手的同学别一上来就盯着SpringCloud、分布式、微服务这些花架子先把SpringBootVue这套经典组合吃透把CRUD、权限、认证、统计这些基础能力练扎实。后面真要上规模扛并发微服务那套是基于这些基本功往上堆的基础不牢的话分布式只会带来更多麻烦。还有一个小技巧想分享在开发过程中多利用接口文档工具每次后端完成一组接口就及时把文档标注清楚。一个小小的习惯可以让前后端联调效率提升一半以上也能让项目最后交付时显得专业得多。这个习惯也被我沿用到了后续所有项目开发中几乎零成本但收益很高。如果你正在按照这个题目搭系统建议先按我说的把表结构建好再跑通一条“用户登录-录入客户-添加跟进记录-查看看板”的主链路主链路通了剩下的模块都是在这个框架上做加法而已。祝所有做这个系统设计的人少踩坑、早通关。
返回列表