Sword快速上手教程:从零开始跑通一个后台管理系统
关于Sword,先聊点实际的。它本质上是一套基于Spring Boot的快速开发脚手架,帮你把后台系统里那些反复出现的"基础设施"——用户登录、角色权限、菜单路由、代码生成、文件处理、日志审计——全部提前做好并集成完毕。很多团队选它,不是因为炫技,而是因为新项目启动时最耗时间的就是这一堆"地基"工作。如果你接过那种从零搭建权限模型的活,应该懂我什么意思:光设计角色表、菜单表,再加上前后端联调,一个星期就没了。Sword存在的意义,就是把这一个星期压缩到一天甚至半天。
这篇教程适合谁?适合刚接触Sword的Java后端开发者,也适合前端同学想搞明白后端脚手架到底做了什么。我会按自己实际摸索的路径来讲——不是官方文档的复读,而是从下载、配置、启动,到真正生成一个带增删改查的模块,整个过程中我踩过的坑、曾经搞不明白的点,都一并交代清楚。
1. 环境准备:JDK、数据库与初始化项目骨架
先说环境,因为这一关卡掉了不少人。Sword基于Spring Boot 2.x,Java版本要求8以上,建议直接用8或11,别一上来就上17,某些老版本依赖在17下会有反射报错,不是不能解决,但没必要让新手一上来就背这个锅。
数据库方面,项目默认配置的是MySQL 5.7以上版本,本地开发建议8.0。如果你机器上还没有装数据库管理工具,推荐用Navicat或者DBeaver都行,后者免费且跨平台。
1.1 获取项目骨架并导入IDE
Sword有两种拿法:一种是从代码仓库直接clone下来,另一种是下载发行版。我建议第一次接触的人用clone方式,方便后面查看源码。
代码拿到后是个多模块Maven工程,结构大致这样:
sword-parent(父POM) ├── sword-common(公共模块:工具类、常量、异常处理) ├── sword-system(系统模块:用户、角色、菜单、部门) ├── sword-generator(代码生成模块) └── sword-admin(启动模块:Controller、配置、启动类)用IDEA导入时,建议以sword-parent整个目录作为Maven项目打开,不要单独导入子模块,否则依赖关系容易乱。第一次导入会下载大量依赖,国内网络环境建议把Maven仓库地址配成阿里云镜像,否则等依赖下完就够喝一壶了。
1.2 配置文件里最容易出问题的三处
导入完成后,第一件事不是启动,而是改配置。配置文件在sword-admin/src/main/resources/application.yml。这里有三处最容易踩坑:
第一处,数据源配置。默认配置指向的是本机的jdbc:mysql://localhost:3306/sword,你要确保自己本地的MySQL里先建好这个数据库,字符集用utf8mb4。这里有个容易忽略的细节:MySQL 8.0的驱动类名和5.7不一样。如果你用的是8.0,需要把驱动改成com.mysql.cj.jdbc.Driver,同时URL上加上时区参数。我第一次配的时候就忘了,启动直接报错,提示找不到驱动类。
第二处,Redis配置。Sword的登录验证码、在线用户状态都依赖Redis。默认地址是localhost:6379,密码为空。如果你本机没装Redis,启动时虽然不至于直接挂掉,但登录的时候一定会出问题。建议本地直接跑一个Docker Redis,一条命令的事。
第三处,文件上传路径。默认写到/home/sword/uploadPath,注意这个路径是Linux风格。如果你在Windows上开发,要改成类似D:/sword/upload这样的路径,否则上传文件时接口会直接500。别问我怎么知道的,都是泪。
1.3 初始化数据库到底要执行哪些脚本
Sword自带SQL脚本,但这部分文档讲得比较简略,很多人栽在这里。实际上,你需要按顺序执行以下文件:
sql/sword.sql:核心表结构,包括用户、角色、菜单、部门、字典等sql/data.sql:初始数据,包括管理员账号、默认角色、菜单按钮权限点
这里特别提醒,两个脚本都要执行,顺序不要反。有人只导了第一个就跑去启动,结果登录页面出来了,输默认账号密码却提示用户不存在,排查了半天才发现是数据没导入。执行完以后检查一下,sys_user表里应该有一条admin记录,密码是加密过的,默认是123456对应的BCrypt密文。
1.4 第一次启动会碰到的典型报错
配置改完、脚本执行完,就可以启动SwordAdminApplication主类了。如果你运气好,控制台会直接打出启动时间那种经典界面。但大概率你会碰到一两个报错,最常见的两个:
第一个是端口冲突。Sword默认端口是8080,很多人本地还有别的项目在跑,端口被占了,报错信息是Port 8080 was already in use。解决办法很简单,在application.yml里改成别的端口,比如8088。
第二个是Redis连接失败,报错里通常会有一大段Unable to connect to Redis。这个不用慌,先确认你的Redis服务是不是真的起来了。本地没装Redis或者服务没启动的,先解决这个前置项。如果服务确实起来了还连不上,检查一下Redis配置里的密码字段是不是空字符串,Sword默认读的是spring.redis.password,没密码就留空,不要乱写。
启动成功后浏览器访问http://localhost:8080,能看到登录页就算环境跑通了。这时候你会有一种"终于起飞"的感觉,但实际上真正的门道才刚开始。
2. 界面布局与核心功能模块的完整认识
登录进系统以后,先别急着到处点的,花十分钟把整个界面结构看一遍,搞清楚每个区块对应的是哪个功能。这一步看着简单,但能帮你后续少走很多弯路。
2.1 登录页与验证码背后的逻辑
Sword的登录页面用的是经典后台模板,用户名密码加验证码,验证码是后端基于Redis生成的。这里聊一下验证码为什么要用Redis——想象一下你曾经常见的那种短信验证码,十几分钟后就失效了,它需要会话级存储,Redis天然支持过期时间且读写极快。Sword把验证码放进Redis,设置几分钟的过期时间,用户请求登录时从Redis里拿出来比对,比对完立刻删除,避免同一个验证码被反复使用。
有个小细节:如果你用Postman等工具直接调登录接口,记得先调用一次验证码接口拿uuid,再把验证码字段和uuid一起提交,缺了都对不上。
2.2 系统管理模块里藏着Sword的核心
登录后默认进入工作台首页,左侧菜单里最值得逐项点开看的是"系统管理"这一组,它包含用户管理、角色管理、菜单管理和部门管理四项。这四项不是各自独立的,它们共同构成了一套经典的RBAC权限模型。
- 用户管理:维护系统登录账号,可以给用户分配角色
- 角色管理:定义角色,并给角色授权菜单和按钮权限
- 菜单管理:维护左侧菜单和按钮权限点,这套数据不仅是导航栏,也是权限判断的根基
- 部门管理:把用户挂到部门树下,做数据范围隔离用的
很多人一上来就想去搞代码生成,忽略了先把这几个页面之间的关联关系理清楚。我可以负责任地告诉你,这个模型没搞明白,后面生成的模块即使跑起来,权限也一定是乱的。用户—角色—菜单,层层绑定,这套规则是RBAC的标准实现,理解它以后再去看别的权限框架基本都是触类旁通。
2.3 在线日志与监听工具:调试期的好帮手
在界面上还有一块容易被忽略但真正实用的内容——在线用户和操作日志。我强烈建议你在开发阶段多看重这两块。
在线用户能直接看到当前谁登录了系统,甚至可以选择"强退",开发测试时想清理登录态非常方便。操作日志则把每个请求、操作用户、耗时、IP、操作结果都记录在案。我有一次遇到一个诡异的Bug:某个接口偶尔报错,但本地没法稳定复现。后来翻了操作日志,发现报错其实都是同一个用户、同一个时间窗口内触发的,顺藤摸瓜定位到是并发场景下的数据竞争问题,排查效率翻了好几倍。
3. 代码生成器:三分钟从建表到可用菜单
前面那些准备工作都是为了这一步服务的。Sword最让人省心的功能就是代码生成器,它能直接根据你的数据库表生成后端Controller、Service、Mapper、实体类,以及前端Vue页面和接口定义。其实原理并不神圣,就是模板引擎把你表结构里的字段信息绑定到预设好的模板文件里,一顿生成然后输出到项目对应位置。但用得好能省两三天的活。
要做好生成器,先记一个"三条约定",做不对它会直接闹脾气:
- 每张表必须有主键,而且主键最好是自增的
id - 表名要有前缀,比如
biz_order、biz_user_info,前缀任意,但不要裸用user这种单词,容易和其他模块撞 - 字段要有注释,生成出的页面标题、表单label、列表列头,全部从注释里读。你字段注释写得越规范,生成出来的界面越像样
3.1 生成步骤的实际操作记录
在左侧菜单进入"代码生成",界面上会让你先选择要生成的表。找到你创建的表,点击"代码生成"按钮。这时会弹出一个配置框,这里有一堆选项,我建议保持默认,直接点确定就行。生成完成后会下载一个zip包,里面是已经拆分好的后端和前端代码文件。
如果你用的是前后端分离的布局,后端代码解压后直接放到对应模块的包路径下。前端产物则需要放到前端工程源码里,在src/api、src/views下各归各的位置。放完以后重启后端服务,前端页面重新跑一下,左侧菜单如果没自动出现,去"菜单管理"里手动加一条菜单记录,类型选"目录"还是"菜单"取决于层级,URL指向你前端页面的路由地址。
3.2 为什么说"能用"和"够用"之间隔着一层配置
生成的代码是可以直接用的,列表展示、新增、编辑、删除四个基本操作全都有。但我实际用下来的感受是,光靠默认生成只是"能用"而已,很多细节你得手动定制才能"够用"。
就拿列表页来说,如果表里有个JSON类型的字段,默认生成的表格直接会把它原样打出来,一大串花括号括号,观感很糟。更好的做法是自己在前端代码里对这个字段做格式化,比如只取JSON里特定的几个键,或者用Tag组件展示状态。再比如下拉搜索框,如果你在业务表的某个字段存的是字典值,理想状态下应该让这个字段渲染成下拉选项,而不是显示一个干巴巴的数字。我在给一个订单表做页面时,就把订单状态的数字映射成了中文标签,后面看数据一眼清,不用再在脑子里翻译。
这些都说明一个问题:代码生成器解决的是"从0到1",剩下的"从1到100"最终还是需要你理解框架的套路,知道往哪个文件里改、改哪一段,才不会把自动化生成的代码改成一坨浆糊。建议你生成的代码拿到手后,先花半小时完整读一遍,尤其是Controller和前端表单页,读懂里面的模式,以后自己手写模块心里也有底。
4. 权限体系的运转逻辑与配置实操
Sword的权限体系是很多人最头疼的一部分,因为它的配置项多、关联性强、报错信息又往往含蓄。但权限这东西又是后台系统不可回避的底座,一旦绕过去用"暂时放开"的方式糊弄,后面上线审计时一定会回来找你。
4.1 菜单权限和按钮权限到底谁管谁
你需要先理解两个概念的区别:菜单权限管"能不能看到这页",按钮权限管"能不能点到这页里的那个按钮"。一个用户能不能删除一条数据,不是后台接口自己写死"能删",而是要先看这个用户被赋予了"删除"这个按钮权限点没有。
在Sword里,按钮权限的粒度可以精确到一个具体的接口。比如某个页面上有个"审核通过"按钮,正常情况下只有审核角色才该看到它。实现方式是用自定义指令在按钮上标记权限标识,前端渲染时判断当前用户是否有这个标识,没有的就直接不渲染这个按钮。而后端,同样的逻辑会在接口层再检查一遍权限标识,所以前端只是隐藏,真正的安全边界在后端。这套思路值得你写业务代码时借鉴:前端控制的永远是体验,后端控制的才是安全。
4.2 如何捣鼓一套属于自己的角色授权流程
假设现在你要新增一个"运营专员"角色,并且希望它只能管理"订单管理"菜单,不能碰系统设置。
第一步,进"角色管理",新建角色,名字随意取。第二步,勾选该角色能访问的菜单树,这里注意菜单树里勾选父子节点时,系统会默认带上全链路,你不用手动把所有父级菜单都勾上。第三步,给该角色分配用户,把某几个用户挂到这个角色下面。
做完这三步,换那个用户登录,你就能看到左边菜单只剩下订单管理,系统设置完全消失,即使他知道URL也访问不了。这个过程走一遍,你对RBAC的理解就落地了。
这里有个容易绕晕的点:修改菜单权限后,用户需要重新登录才会生效。原因是登录成功后,权限数据会被拉取并缓存进Redis,只有重新登录或等缓存失效才会刷新。我见过有人改完角色权限,让用户刷新页面反复看,权限没变化就怀疑系统坏了,其实就是没重新登录的原因。
4.3 数据权限:部门隔离的实现思路
菜单和按钮管的是功能,而数据权限管的是数据范围。Sword内置了按部门过滤数据的配置,核心逻辑是:用户绑定部门,部门形成树结构;查询数据时根据当前用户的部门ID,加上一个dataScope的SQL片段作过滤,让它只能看到本部门或本部门及其下级部门的数据。
例如一个订单表,想让分公司的人只能看自己分公司的订单,那在SQL里就得带上WHERE dept_id = 当前用户的分公司ID。Sword帮你在框架层面做了这个能力,你要做的事只是在你编写的Mapper里正确拼上数据权限的过滤条件。注意是"正确拼上",这里的坑是有些人在自定义SQL里忘了加过滤条件,导致数据权限形同虚设。这个环节建议测试时专门用一个低权限账号来验证,你看到的结果才是最真实的。
5. 自己动手写一个模块:完整CRUD路线图
纸上谈兵差不多了,接下来走一遍真刀真枪的实操流程:在一个干净的模块里手写一个带权限校验的CRUD接口。这套流程走完,你对Sword的了解就不只是会点击鼠标了,而是能按它的规范自己写代码。
5.1 表结构设计与实体类映射
假设我们要做一个简单的"通知公告"表,业务字段包括标题、类型、内容、状态、发布时间。建表时注意几点:主键用bigint自增,每个字段写好注释,业务字段的类型认真考量——内容这种可能很长的,直接选text类型,标题选varchar(100)足够,类型和状态用tinyint存数字值。
在Sword对应的包里新建实体类,类名对应表名的驼峰格式。类上标注这是数据库实体映射,字段上用注解与表字段建立对应关系。这里有个理解成本稍高的点,但不是Sword独有的能力:实体类只是数据载体,和前端表单、数据库表三者之间的字段名不必完全一致,靠注解和配置去映射,这能让你在改动数据库字段时不必全局搜索修改。
5.2 后端四件套:Controller、Service、Mapper、实体
实现一个接口,Sword的常规写法是四层配合:
- Controller层:定义REST接口,校验入参,调Service
- Service层:写业务逻辑,事务注解加在需要保证原子性的方法上
- Mapper层:用MyBatis操作数据库,简单查询可以直接用框架自带的方法,复杂联表查询就自己写SQL
- 实体层:上面提到的数据库映射
举个例子,查询通知列表时,Controller接收分页参数和筛选条件,Service把条件封装成查询对象传给Mapper,Mapper在XML里写一条带where动态判断的SQL,最后结果塞进分页对象返回前端。写这个流程时,如果有一步卡住,多半是你对MyBatis的用法还不够熟,不是Sword的问题。
事务这块,我要多说两句。如果你的业务是"新增通知后同步给所有用户生成一条待办",那么"新增通知"和"批量生成待办"必须放在同一个事务里,要么都成功,要么都回滚——不能出现通知发出去了但待办没生成一半的情况。
5.3 前端三件套:API定义、页面、路由挂载
后端完成后,前端这块对应要做三件事。
第一,在API目录里定义调后端的接口函数,一个模块对应一个文件,把增删改查四个请求都封装好,导出供页面使用。
第二,在视图目录下新建页面,列表用表格组件,编辑用弹窗加表单组件。页面基础代码可以直接拿代码生成器产物当模板来改,省力且风格统一。
第三,在路由配置文件里注册页面路由。注册完路由后再去菜单管理里配置权限点。很多人这里搞反了,先去配菜单,结果路由还没注册,页面刷不出来。
顺带提醒一下,新增、编辑共用同一个弹窗,根据有无初始数据判断当前是新增还是编辑,这是Sword生成页面的默认模式,别去推翻它,按这个模式写代码是最省心的。
5.4 用统一响应格式串起整个请求链路
前端调后端接口,最怕的是后端返回数据格式不统一。Sword用统一的响应体封装了所有接口返回值:状态码、提示信息、真实数据三个字段固定出现在所有接口响应里,同时封装了分页返回结构,避免你每个接口自己拼分页数据结构。
这意味着你在写后端方法时,正常逻辑使用返回成功包装即可,出错时抛出特定异常,全局异常处理器会帮你转成统一格式,再由前端统一拦截处理。这个设计的好处是,前端拿到响应后只需要判断状态码,不用每个接口各自处理异常分支,减少了很多重复代码。
6. 调试排错与性能优化:我在实际项目中踩过的坑
最后这部分我想把你从一个"能跑起来"的玩家拉上"会调优会排错"的台阶。下面这些坑,有些是我自己摔过的,有些是看着同事摔的,都有代表性。
6.1 本地调试与远程排查的工具箱
后端出问题先看日志,Sword用的是Logback,日志文件在运行目录下的logs文件夹里,分info和error两个文件。我在排查问题时的固定顺序是:先看error日志找异常堆栈,再回看info日志里的关键操作记录,最后用数据库日志配合。
如果你改动了前端代码但页面显示还是旧的,多半是构建缓存问题。用Webpack构建的项目,强刷一下浏览器或者把devServer的缓存清理掉,基本都能解决。我碰到过一次很离奇的"页面白屏",排查了一下午,最后发现是后端返回的菜单路由里有一个空字符串,导致前端动态路由生成失败。这类问题属于典型的"前后端数据联通性"问题,建议你一旦白屏先打开浏览器控制台看报错信息,别先怀疑框架。
6.2 从日志排查空指针和权限失效的完整链路
如果你在操作过程中遇到空指针异常,先别急着在代码里到处加判空。我建议按这个链路来找:
第一步,先看异常发生前的日志上下文,有没有参数的打印输出,通过查数据库确认这份数据是不是真的存在。如果是"查询权限配置为空",很可能就是你数据库里漏配了数据。
第二步,如果查出来数据存在但还是报错,再去对应代码里看是不是注解标错了,比如某个需要权限的查询方法没有加权限注解,导致框架自动拦截时找不到权限配置,直接放行或者直接拦截。
第三步,如果本地复现不了,去查操作日志里最近一次请求的参数和返回结果,比对测试账号和正常账号的差异。
权限失效又是一个高发问题。原因大多跑不出三种:角色没配好、用户没关联到角色、菜单权限点没关联到角色。排查狠一点的顺序是:查用户详情看当前角色的ID,按角色ID查菜单关联,再按菜单ID查权限标识,最后把权限标识和你代码里的注解比对是否一致。只要权限标识对不上,前端页面删了按钮,后端接口也同步拦截,这种情况我见过太多次。
6.3 查询慢了怎么办:索引与缓存的两层优化
很多人会忽略Sword生成的代码里那些自带缓慢的条件查询。比如列表页默认支持按模糊查询,可一旦数据量达到几万条,无索引的模糊查询会直接拖垮接口。
我的建议是:给高频查询字段建索引,比如状态、类型、创建时间;模糊查询慎用%关键词%这种写法,它可以改用前缀匹配的结构,或者结合搜索引擎。如果你不急,可以先在数据库里用EXPLAIN看执行计划,确认走没走索引,再决定优化方案。
另一层优化是缓存。读多写少的字典数据,完全可以从数据库查一次后放进Redis,后续直接读缓存。Sword本身已经内置了缓存管理工具,键值过期设置都非常规范,缺的是你在业务里什么时候去用它。记住一个原则:接口响应时间超过1秒的查询,先看是不是没走缓存。
6.4 服务器上线前必调的几项配置
如果你准备把这个项目部署到服务器上,有几个配置项必须再过一遍:
- 数据源连接池大小:开发环境默认值较小,上线前要根据并发量调整,不然高峰期连接不够用
- 文件上传路径:换成服务器上的真实目录,并确保目录有写权限
- 日志级别:生产环境建议调成WARN,避免打印过多DEBUG日志把磁盘撑爆
- Redis密码:暴露在公网的Redis一定要设密码,否则等于裸奔
我见过不少项目,开发环境跑得欢,一到服务器上就各种莫名其妙的问题,最后发现全是配置没用服务器环境覆盖默认值。提前把这些处理干净,能省掉上线后的一次又一次麻烦。
从入门到入门的最后一句话
回头看一下,Sword能帮你的是把那些重复了无数遍的基础工作一次性做好:权限、菜单、日志、代码生成。但你自己的业务逻辑,它只能帮你生成个起点,真正的核心竞争力还是你对业务的理解和代码的掌控力。
我个人摸索下来最大的感受是:不要一开始就追求把框架所有功能都学会,先用起来,等遇到痛点再回头看官方文档。我一开始连数据权限是什么都没搞明白,直到某次做一个跨部门的业务报表,数据的可见范围怎么调都不对,才真正回去把文档里那几页配置读了一遍。带着问题去学一个框架,效率永远比从头到尾通读文档高得多。
最后分享一个实用的小习惯:每当你卡在一个Bug超过一小时,不要硬扛,先把日志完整看一遍,再开一个干净的网络搜索去搜报错片段。大多数问题不是你遇到的头一个,网上早有人趟过。你真正要训练的,是能准确描述问题的能力——能把日志里最关键的那一行拎出来,能快速定位到是哪个环节出了岔子。这个能力,比背一百个接口方法都管用。