☰
「Java+微信小程序」法律咨询与知识库系统实战指南
2026/10/12 5:05:02 网站建设 项目流程

这个标题给得很长,拆开看其实就是三句话:做一个微信小程序端的法律咨询系统,后端用 Java 写,既能在线答疑也能沉淀知识库。项目名字里反复出现的“法律服务咨询与互助平台”和“律师在线答疑与法律知识库系统”,对应的是同一个项目的不同侧重点,设计时把这三句话合并成一张需求图,落地工作量就不会散。

这个项目适合两类人参考,一类是做毕业设计想选“小程序+Java”方向的同学,另一类是刚学完 Spring Boot 想找一个完整业务练手的新手开发者。网上很多教程只给你一个简单的 CRUD,而这个题目天然自带用户、律师、管理员三种角色,有身份认证、内容审核、消息通知、搜索匹配这些真实业务要素,做完之后简历上能写的东西会厚实很多。

下面我从需求拆解、技术选型、数据库设计、后端业务逻辑、小程序端交互到踩坑记录,完整过一遍实现思路。全程按我实际带项目的方式来讲,不绕弯子,只讲能落地的。

1. 需求拆解:这个系统到底要做什么

1.1 三类角色与核心功能边界

先不要急着写代码,把角色摆清楚。法律咨询这件事,线下场景是“用户提问、律师回答、平台做撮合”,搬到小程序上以后,核心角色就是普通用户、律师、平台管理员。

普通用户要做的事很明确:注册登录、浏览法律知识库、发布自己的法律问题、查看律师回答、收藏有用内容。这里面“互助”体现在哪里?我一般建议系统允许普通用户对问题发表简短的经验分享,但是普通用户的回答不带“律师认证”标识,权威性明显弱于律师回答,这样既保留互助氛围,又不至于让非专业回答误导别人。

律师角色要单独设计一套入驻审核流程。用户提交入驻申请时要填真实姓名、律师执业证号、执业机构、擅长领域、个人简介,管理员在后台审核通过后才拥有“律师”身份。律师进入答疑页面后,可以按自己的擅长领域筛选问题,填写专业回答,回答内容会以较高权重展示给提问用户。

管理员是容易被忽略但又必须有的角色。问题需要审核,律师资质需要审核,知识库文章需要编辑和上下架,再加上查看用户数、问题数、回答数这样的基础统计。哪怕毕业设计里的管理后台做简单一点,这三类用户也缺一不可,否则“系统”就变成单机问答工具了。

1.2 功能模块清单与优先级

我习惯用优先级来梳理需求,免得做到一半被各种小功能拖住节奏。下面这张表基本就是整个系统的功能边界,P0 是第一阶段必须完成的,P1 是时间充裕再补的。

模块功能点角色优先级
登录认证微信登录、token 鉴权用户/律师P0
法律咨询发布问题、问题列表、问题详情用户P0
在线答疑律师回答、回答列表律师P0
知识库文章列表、文章详情、搜索用户P0
互助评论普通用户经验分享、评论用户P1
律师入驻提交资料、后台审核用户/管理员P0
个人中心我的提问、我的回答、我的收藏用户/律师P1
管理后台内容审核、用户管理、数据统计管理员P1

我见过不少同学一上来就加点赞、评论、积分、排行榜,结果核心问答链路还没走通,这种优先级划分是踩过坑以后留下的习惯。先把 P0 做完,系统已经能演示出“提问—答疑—知识库”的完整闭环。

2. 技术选型与项目结构设计

2.1 为什么选 Spring Boot + MyBatis-Plus + 原生小程序

后端选 Spring Boot 基本是毕业设计的主流标准,不是因为它多炫,而是因为生态成熟、资料多、部署简单。配上 MyBatis-Plus 之后,单表 CRUD 几乎不用手写 SQL,这对压缩开发周期非常关键。数据库用 MySQL,缓存和消息通知这种场景一般不会太复杂,毕业设计用不上重型的中间件,别给自己加戏。

小程序端我建议直接用原生微信小程序,而不是 uni-app。原因很现实:这个项目要演示的核心是业务逻辑和微信生态对接,原生小程序对 wx.login、wx.request、模板消息这些 API 支持最直接,调试也最方便。如果你以后想同时打包成 App 或 H5,换 uni-app 是另一套分支,但就当前这个毕业设计题目来看,原生足够。

前端管理后台可以不用做太复杂。课程设计或者毕业设计如果时间紧,可以直接写一个简单的 Vue + Element UI 页面,或者干脆在项目里放一个单独的管理端 Web 模块。我这里默认你后端拆成两个入口:小程序 API 服务和管理后台 API 服务共用一套 Java 工程,只是接口路径和权限不同。

2.2 后端工程结构与统一返回格式

工程结构我建议按功能分包,而不是按技术类型分包。具体区别是:不要搞出 controller / service / mapper 三个大包然后全部往里塞,而是按 user、question、lawyer、knowledge 这些业务模块分包。这样项目后面扩展维护会爽很多。

com.example.law ├── common // 统一返回、异常处理、工具类 ├── config // 拦截器、Web 配置、微信配置 ├── controller // 接口入口 │ ├── UserController │ ├── QuestionController │ ├── AnswerController │ └── KnowledgeController ├── service // 业务逻辑 ├── mapper // MyBatis-Plus Mapper ├── entity // 数据库实体 └── dto // 接口入参出参

统一返回格式是一开始就要定死的规矩,否则后面联调小程序端会非常痛苦。我的习惯是后端所有接口都返回同一个结构:

{ "code": 200, "message": "success", "data": {} }

错误时 code 返回非 200,message 放错误描述。小程序端只需要封装一次请求,统一处理 code,不用每个接口单独判断。后端对应一个 Result 类,再配一个全局异常处理器,把业务异常和未知异常分别处理,问题回答状态不对、参数校验失败这一类错误都能稳定返回给前端。

3. 数据库设计:核心表结构与关系说明

3.1 用户、律师、问题的表设计

数据库设计这一步,直接决定后面写代码的时候是顺滑还是拧巴。我建表有个原则:先确定核心业务主链路,再根据主链路拆表。

主链路是“用户登录—用户提问—律师回答—知识库文章”,所以核心表是 user、question、answer、knowledge_article。用户和律师的关系是一对一扩展,不建议拆成两张平行表,而是在 user 表上增加角色字段,再用 lawyer_profile 表存律师专用信息。

user 表设计如下:

CREATE TABLE `user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `openid` varchar(64) NOT NULL COMMENT '微信openid', `nickname` varchar(50) DEFAULT '' COMMENT '昵称', `avatar` varchar(255) DEFAULT '' COMMENT '头像', `phone` varchar(20) DEFAULT '' COMMENT '联系电话', `role` tinyint(1) DEFAULT '0' COMMENT '角色 0普通用户 1律师 2管理员', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_openid` (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

question 表是提问业务的核心。关键字段是 user_id、category_id、title、content、is_anonymous、status。

CREATE TABLE `question` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT '提问用户ID', `category_id` int(11) NOT NULL COMMENT '法律领域分类ID', `title` varchar(100) NOT NULL COMMENT '问题标题', `content` text NOT NULL COMMENT '问题描述', `is_anonymous` tinyint(1) DEFAULT '0' COMMENT '是否匿名 0否 1是', `status` tinyint(1) DEFAULT '0' COMMENT '0待回答 1已回答', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_category` (`category_id`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

status 字段是最容易被忽略的,但它的价值很大。提问之后状态是“待回答”,律师一旦回答,状态立刻变成“已回答”,小程序端可以根据这个字段判断是否显示“我来回答”按钮。这个字段撑起了整个答疑链路的状态流转。

3.2 知识库与多表关联设计

知识库、分类、收藏这三块属于内容体系。知识分类单独建一张 category 表,question 和 knowledge_article 都通过 category_id 关联,以后做首页分类筛选就很方便,不用写死条件。

answer 表要同时记录问题 ID 和回答人 ID。回答人可能是律师,也可能是普通用户,所以加一个 user_type 字段用于判断回答者身份。回答的“权威性”就靠这个字段区分,律师回答在展示时多显示一个认证标签。

knowledge_article 表我一般会加 source 字段记录文章来源,recom_flag 标记是否在首页推荐。搜索功能不需要单独建搜索服务,后端用简单的 title/content 模糊查询 + 分类筛选就能满足毕业设计演示需求,没必要上全文搜索引擎。

4. 后端核心业务逻辑实现

4.1 小程序登录与 token 鉴权机制

微信小程序登录是整个系统的入口,很多同学在这里第一次翻车。典型错误是把 appid 和 secret 直接写进小程序前端代码,这是绝对不能做的事。正确的流程是:

  1. 小程序端 wx.login 获取临时 code
  2. 小程序把 code 传给后端
  3. 后端拿 code 加上 appid、secret 去微信接口换 openid
  4. 后端查库找到或创建用户
  5. 后端生成 token 返回给小程序
  6. 小程序后续请求在 header 里带 token

token 我习惯用 JWT,理由很直接:Spring Boot 对 JWT 的支持很成熟,用户信息放进 token,后端用拦截器统一解析,不需要依赖 Session,更符合前后端分离的思路。JWT 的有效期设置为 7 天,小程序端在 401 响应时自动跳转重新登录。

String openid = wechatService.getOpenid(code); User user = userMapper.selectOne( new LambdaQueryWrapper<User>().eq(User::getOpenid, openid)); if (user == null) { user = new User(); user.setOpenid(openid); user.setRole(0); userMapper.insert(user); } String token = JwtUtil.createToken(user.getId(), user.getRole());

登录接口返回 token 和用户信息,小程序端把 token 存到 storage。这里提醒一下,JWT 密钥不要硬编码在代码里,可以放到 application.yml 配置文件中,答辩时老师如果问配置管理,这就是一个加分回答。

4.2 提问—回答—消息通知的完整链路

提问接口要做的事情不是单纯的 insert,而是要把整条链路打通。用户提交问题后,后端需要做三件事:写入 question 表、根据 question 的状态字段标记“待回答”、在律师端待答列表里暴露这条新问题。

我实际开发时,还会在 service 层加一个敏感词过滤。法律咨询平台上,用户问题里偶尔会出现不合适的表达,毕业设计不需要上复杂的算法,一个简单的敏感词工具类就够了,命中敏感词就打回提示修改。这一步虽然小,但答辩时讲出来很加分,因为这说明你考虑了内容安全。

律师回答接口是核心中的核心。律师进入待答问题列表,点击某个问题进入详情页,看到用户描述后编辑回答内容提交。后端收到回答请求后,先校验当前用户角色是否为律师,再校验问题状态是否为“待回答”,防止一题多答或者非律师回答。然后插入 answer 记录,同时把 question.status 更新为“已回答”。

用户提交问题 -> 问题状态置为待回答 -> 律师按分类刷新待答列表 -> 律师提交回答 -> 插入answer记录 -> 更新question状态为已回答 -> 生成站内消息通知提问用户

站内消息通知是很多同学会遗漏的设计。我在 message 表里记录一条消息,内容包括通知对象、相关业务 ID、消息类型和是否已读。用户打开“我的消息”时就能看到“你的问题收到新的律师回答”。如果时间充裕,还可以接入小程序的订阅消息推送,但毕业设计阶段站内信已经足够完整。

4.3 知识库搜索与首页聚合接口

知识库功能相对简单,就是要做好搜索和分类筛选。后端接口接受 keyword 和 categoryId 两个参数,keyword 做标题和内容的模糊查询,categoryId 做精确筛选。然后统一按发布时间排序。更好的做法是给阅读量加一个 read_count 字段,每次点击详情自增一次,首页知识库推荐默认按阅读量排序。

首页需要同时展示推荐问题、推荐律师、知识库热门文章,我一般单独写一个聚合接口,返回首页所需的全部数据,小程序端只调一次接口就把首页渲染出来。避免前端多次请求导致页面加载慢,也避免答辩演示时因为网络闪断而出丑。

5. 小程序端页面与交互实现

5.1 页面架构与底部导航规划

小程序端页面结构直接对应功能模块。底部 tabBar 我建议配四个入口:首页、问答、知识库、我的。这样用户能快速触达核心功能,页面层级也清晰。

  • 首页:推荐律师、热门问题、知识库入口
  • 问答:问题列表、问题详情、我要提问
  • 知识库:文章分类、文章列表、文章详情、搜索
  • 我的:个人中心、我的提问、我的回答、我的收藏、律师入驻

问答页承载的是核心互动场景,可以默认列出所有问题列表,顶部加分类筛选 tab,点进问题详情后能看到普通用户的经验分享和律师专业回答,两类回答在 UI 上要能区分开。我通常会建议在律师回答区域加一个金色“律师认证”角标,这种细节能让演示效果提升不少。

5.2 请求封装、登录态维护与关键页面实现

小程序端写接口请求时,一定要做统一封装。我习惯在 utils 下建一个 request.js,把 wx.request 包成 Promise,统一设置请求头、统一处理错误码和 401 跳转。

const request = (url, method, data) => { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + url, method: method, data: data, header: { 'Content-Type': 'application/json', 'Authorization': wx.getStorageSync('token') }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data); } else if (res.data.code === 401) { wx.removeStorageSync('token'); wx.navigateTo({ url: '/pages/login/login' }); } else { wx.showToast({ title: res.data.message, icon: 'none' }); } }, fail: (err) => { reject(err); } }); }); };

提问页面用一个表单页承载:标题输入框、问题描述 textarea、领域分类 picker、匿名发布 switch。提交时校验标题不能为空、描述不能小于 10 个字。这里要注意的是,如果用户选了匿名,提交给后端的 user_id 仍然要保留,只是展示层把昵称换成“匿名用户”。真实用户 ID 不能丢,律师还是需要知道回答给谁,但问题列表和详情页不泄露身份。

律师端答疑入口放在“我的”页面,审核通过的律师可以看到“待答问题”列表,点击进入写出回答。这个页面的关键是仅展示当前律师擅长领域分类下的问题,并且把已经回答过的问题过滤掉,不然列表会越攒越长。

6. 常见问题与踩坑记录

6.1 登录、鉴权与用户角色相关的坑

微信登录这块我见过最多的报错是 code 无效。原因是 wx.login 返回的 code 只能用一次,前端如果重复调用 wx.login,后面的接口就会拿到失效的 code,后端换不来 openid。解决方法是每次登录流程只调一次 wx.login,拿到 code 后立刻传给后端,不要在多个页面反复触发登录。

角色判断也是一个容易踩坑的地方。用户注册时默认 role 是普通用户,律师入驻审核通过后 role 才变为律师。有同学把角色信息直接写死在用户表,结果管理员在后台修改了角色,前端还显示旧身份,这是因为没有让用户信息接口每次都从数据库读最新角色。解决方案是登录后重新请求用户信息接口,而不是用缓存里的旧数据。

还有 token 过期的问题。如果后端返回 401,小程序端只是弹出“登录已过期”却没有清理本地 token 和跳转登录页,用户就会被卡在原地。统一请求封装中一定要有 401 的全局处理。

6.2 数据库、部署与演示相关的问题

数据库字符集必须用 utf8mb4,这一点很多同学会忽略。用户昵称里经常有表情符号,utf8 会报错,只有 utf8mb4 才能存下来。建库的时候直接指定默认字符集,不要在项目做到一半再改,否则迁移数据很麻烦。

部署方面,小程序后端接口必须是 HTTPS 地址,而且要提前在微信公众平台配置服务器域名。开发阶段可以在开发者工具中关闭域名校验,但体验版和预览版必须走正式域名。我建议答辩前至少预留一天时间处理域名备案和证书问题,否则本地跑得好好的,一上体验版接口全部不通。

演示时有三类账号会稳妥很多:一个普通用户账号、一个已审核律师账号、一个管理员账号。演示顺序可以这样走:普通用户发布一条问题,切换律师账号回答这个问题,再切换普通用户看到回答,最后到管理员后台审核一条内容。这样整个业务闭环一次走完,比零散演示各个页面要有说服力得多。

我个人在带项目时的体会是,这个题目的难点不在技术,而在于“能不能把流程讲清楚”。只要做到角色清晰、状态流转明确、用户看得见律师认证信息、知识库能搜能点,答辩老师基本不会为难你。最后再分享一个小技巧:所有接口返回的时间字段,后端统一处理成格式化字符串返回给小程序,不要把小程序的格式化逻辑写得到处都是,省下来的时间足够你把答辩演示练熟三遍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询