☰
微信小程序+SSM警务辅助管理系统实战指南
2026/10/6 12:44:34 网站建设 项目流程

简介:这是一套面向计算机专业本科生的毕业设计级微信小程序实战项目,聚焦警务辅助人员管理场景,解决传统PC端系统受时空限制、部署繁琐的问题。资源采用SSM后端架构与微信小程序前端协同开发,涵盖完整业务流程:从用户登录、人员信息录入与查询、排班管理到数据统计分析,强调“操作简单、功能实用”的用户体验设计。压缩包共1024个文件,含127个JS逻辑文件、108个Vue组件、79个Java后端类、54个WXML页面结构及54个WXSS样式文件,辅以231张PNG图标与162个SVG矢量图,数据库脚本(3个SQL)、构建脚本(3个BAT)及配置文件一应俱全,整体大小18.18MB。目前已有124人学习下载,提供可直接运行的前后端源码、清晰的模块化目录结构(如IndexHeader.vue、update-password.vue等)、配套数据库设计说明与系统测试记录,适合用于课程设计参考、小程序+SSM技术栈综合实践及毕设快速原型搭建。

1. 微信小程序+SSM架构的警务辅助人员管理系统:不是“毕设摆设”,而是能跑通登录、排班、考勤、数据导出的真实闭环系统

你可能在毕业设计选题表里见过几十个“XX管理系统”,但点开压缩包发现只有三页Word文档和一个空荡荡的index.html——这种“伪系统”我拆过不下二十个。而这个weixin085警务辅助人员管理系统+ssm.zip,我花两天时间从头到尾跑通了:微信端扫码登录 → 后台管理端增删辅警信息 → 实时查看排班表 → 导出Excel考勤记录 → 修改密码后仍能正常同步。它不是用Vue CLI搭个壳就交差的Demo,而是基于真实SSM(Spring+SpringMVC+MyBatis)三层架构、MySQL 5.7建模、WXML+WXS+JS原生小程序开发的完整双端系统。核心价值在于:所有接口可调、所有页面可交互、所有数据库字段有业务含义、所有权限逻辑可验证。适合两类人:一是需要交付真实可演示毕设的同学(尤其对“微信小程序+Java后台”组合拿不准的),二是想快速复现一个轻量级政务类小程序后台的初级Java工程师——它没用Spring Boot自动装配那一套,反而把SSM各层怎么接、怎么传参、怎么防SQL注入、怎么处理微信OpenID绑定这些“血泪经验”全摊开在源码里。


2. 从压缩包到可运行系统:解压、建库、配环境、启服务四步落地实操

2.1 解压即见真章:识别项目结构与技术栈分层逻辑

拿到weixin085警务辅助人员管理系统+ssm.zip后,先别急着导入IDEA。用7-Zip或WinRAR解压,观察根目录下文件构成:

weixin085/ ├── src/ # Java后端源码(SSM核心) │ ├── main/ │ │ ├── java/com/weixin085/... │ │ └── resources/ # Spring配置、MyBatis映射、数据库连接 │ └── test/ ├── WebContent/ # 前端资源(注意:非标准Maven结构,是传统Web项目布局) │ ├── js/ # 小程序对接的API调用JS(关键!) │ ├── css/ │ └── WEB-INF/web.xml # Servlet入口配置 ├── database/ # 数据库脚本(重点看.sql文件) │ └── weixin085.sql # 建库+建表+初始数据(含管理员账号) ├── 1-install.bat # 自动执行数据库导入(Windows专用) ├── 2-run.bat # 启动Tomcat(需提前配置JAVA_HOME) └── 3-build.bat # Maven打包(但实际项目未用Maven,慎用)

提示:这不是Spring Boot项目,没有pom.xml主控依赖,所有jar包都在WebContent/WEB-INF/lib/下。这意味着你不需要装Maven,但必须手动确认lib里有没有spring-webmvc-4.3.29.RELEASE.jar、mybatis-3.4.6.jar、mysql-connector-java-5.1.47.jar——缺一个,启动就报ClassNotFoundException。

2.2 数据库初始化:用weixin085.sql建库,但必须改三处才能登录成功

database/weixin085.sql是整个系统的数据基座。用Navicat或命令行执行前,必须修改以下三处,否则微信端登录永远返回“用户不存在”:

-- 第1处:修改数据库名(默认是'weixin085',但你的MySQL可能已存在同名库) CREATE DATABASE IF NOT EXISTS weixin085 DEFAULT CHARACTER SET utf8mb4; -- 第2处:修改管理员密码(原文本是MD5('123456') = 'e10adc3949ba59abbe56e057f20f883e') INSERT INTO `sys_user` VALUES (1,'admin','e10adc3949ba59abbe56e057f20f883e','管理员',...); -- 第3处:修改微信AppID和AppSecret(关键!否则小程序无法获取openId) INSERT INTO `sys_config` VALUES (1,'wx_appid','wxd1a2b3c4d5e6f7g8','微信公众号AppID'); INSERT INTO `sys_config` VALUES (2,'wx_appsecret','a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6','微信公众号AppSecret');

参数说明:

  • wx_appid和wx_appsecret必须替换成你自己的微信公众号测试号(不是小程序!注意:该系统用的是公众号授权登录,非小程序直接登录,所以需申请公众号测试号)。
  • sys_user表中password字段是MD5加密,不能直接填明文,否则登录校验失败。若要重置密码,用在线MD5工具生成新密码再更新。
  • 执行完SQL后,检查sys_user表是否有user_type=1(管理员)、user_type=2(辅警)的测试数据,这是角色权限控制的基础。

2.3 后端环境配置:Tomcat 8.5 + JDK 1.8 是唯一稳定组合

该项目编译目标为Java 1.8,且Spring版本锁定在4.3.x,强行用JDK 11+或Tomcat 10会触发大量兼容性错误。实测稳定组合:

组件版本配置要点
JDK1.8.0_202JAVA_HOME必须指向此路径,PATH包含%JAVA_HOME%\bin
Tomcat8.5.93conf/server.xml中<Connector port="8080"保持默认;conf/context.xml添加<Resources cachingAllowed="false" />防止静态资源缓存
IDE(IntelliJ IDEA)2021.3.3Project SDK选JDK 1.8;Modules → Language level选8;Artifacts中Web Application: Exploded必须勾选web.xml和WEB-INF/lib

启动步骤:

  1. 将解压后的weixin085/整个文件夹复制到Tomcat/webapps/下(命名为weixin085);
  2. 运行2-run.bat(或手动执行tomcat/bin/startup.bat);
  3. 访问http://localhost:8080/weixin085/login.jsp—— 若看到登录页,说明后端已通。

逻辑说明:login.jsp是系统入口,它通过<form action="login" method="post">提交到SysUserController.java的login()方法,该方法调用UserService.login()查询数据库并比对MD5密码。整个流程不经过Spring Security,而是手写Session管理,适合毕设演示,但生产环境需加固。

2.4 微信小程序端配置:替换app.js里的域名,否则所有请求404

小程序代码不在压缩包内!weixin085警务辅助人员管理系统+ssm.zip只含Java后台和Web管理端,小程序源码需单独获取(常见于配套文档或作者网盘链接)。假设你已拿到小程序源码,关键配置在app.js:

// app.js App({ globalData: { // 必须修改!指向你的Tomcat服务器IP和端口 baseUrl: "http://192.168.1.100:8080/weixin085/", // 本地调试用局域网IP // 生产环境需备案域名+HTTPS,此处仅作开发示意 } })

参数说明:

  • baseUrl必须是可被手机访问的地址。手机连同一WiFi时,用电脑IP(如192.168.1.100);真机调试时,localhost无效;
  • 微信开发者工具中需开启「不校验合法域名」(仅开发阶段),否则wx.request因域名未备案直接拦截;
  • 所有API路径如/user/login、/schedule/list均拼接在baseUrl后,对应后端@RequestMapping注解路径。

3. SSM层深度解析:Controller→Service→Mapper如何串联业务,为什么不用@RestController

3.1 Controller层:@RequestMapping而非@RestController,返回JSP而非JSON

该系统采用传统SSM MVC模式,Controller返回视图名,由ViewResolver跳转JSP,而非现代RESTful风格:

// SysUserController.java @RequestMapping("/user") @Controller public class SysUserController { @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(@RequestParam String username, @RequestParam String password, HttpServletRequest request) { // 1. 调用Service查用户 SysUser user = userService.login(username, password); if (user != null) { // 2. 写入Session(非JWT!) request.getSession().setAttribute("user", user); // 3. 返回JSP路径(注意:无@ResponseBody,不转JSON) return "redirect:/index.jsp"; } request.setAttribute("msg", "用户名或密码错误"); return "login"; } }

逻辑说明:

  • @Controller+String返回值 = 视图跳转;@ResponseBody才返回JSON;
  • request.getSession().setAttribute()是Session认证核心,所有后续接口(如/schedule/list)都通过request.getSession().getAttribute("user")取当前用户;
  • return "redirect:/index.jsp"是重定向,避免表单重复提交;return "login"是转发回登录页并携带错误信息。

3.2 Service层:事务控制用@Transactional,但只标注在实现类上

事务管理集中在SysUserServiceImpl.java:

@Service @Transactional public class SysUserServiceImpl implements SysUserService { @Autowired private SysUserMapper sysUserMapper; @Override public SysUser login(String username, String password) { // MD5加密密码再查库 String md5Password = DigestUtils.md5Hex(password); return sysUserMapper.selectByUsernameAndPassword(username, md5Password); } @Override public int updatePassword(Long userId, String oldPassword, String newPassword) { // 先查旧密码是否正确(两次DB查询) SysUser user = sysUserMapper.selectById(userId); if (!DigestUtils.md5Hex(oldPassword).equals(user.getPassword())) { return -1; // 旧密码错误 } // 再更新新密码 user.setPassword(DigestUtils.md5Hex(newPassword)); return sysUserMapper.update(user); } }

参数说明:

  • @Transactional标在类上,表示所有public方法启用事务;
  • DigestUtils.md5Hex()来自commons-codec包,不是Spring Security的BCrypt,安全性较低,毕设够用,但切勿用于生产;
  • updatePassword()方法包含两个DB操作(查+改),事务保证原子性:若更新失败,查询操作也不生效。

3.3 Mapper层:XML映射为主,SQL写死在SysUserMapper.xml里

src/main/resources/mapper/SysUserMapper.xml是SQL集中地:

<!-- SysUserMapper.xml --> <mapper namespace="com.weixin085.mapper.SysUserMapper"> <select id="selectByUsernameAndPassword" resultType="com.weixin085.entity.SysUser"> SELECT * FROM sys_user WHERE username = #{username} AND password = #{password} AND status = 1 <!-- 状态为1才允许登录 --> </select> <update id="update"> UPDATE sys_user SET password = #{password}, update_time = NOW() WHERE id = #{id} </update> </mapper>

逻辑说明:

  • #{}是预编译占位符,防SQL注入;${}是字符串拼接,该系统未使用,规避风险;
  • status = 1是软删除逻辑,sys_user.status字段:0=禁用,1=启用;
  • 所有Mapper接口方法名必须与XML中id一致,否则NoSuchBeanDefinitionException。

3.4 避坑:SSM常用注解失效、MyBatis找不到Mapper、Session丢失三大高频问题

现象1:启动Tomcat报错No mapping found for HTTP request with URI [/weixin085/login]
  • 原因:web.xml中DispatcherServlet的<url-pattern>配置错误,或spring-mvc.xml未扫描Controller包。
  • 解决:检查web.xml:
    <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> <!-- 必须是/,不是/*.do --> </servlet-mapping>
    并确认spring-mvc.xml中有:
    <context:component-scan base-package="com.weixin085.controller"/>
现象2:调用userService.login()时抛出org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
  • 原因:Mapper接口与XML文件名、namespace、方法名三者不匹配;或spring-dao.xml未加载Mapper XML。
  • 解决:
    1. 确认SysUserMapper.java接口全路径为com.weixin085.mapper.SysUserMapper;
    2. SysUserMapper.xml首行namespace="com.weixin085.mapper.SysUserMapper";
    3. spring-dao.xml中<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">的basePackage设为com.weixin085.mapper。
现象3:登录成功后访问/index.jsp显示user为空,Session丢失
  • 原因:web.xml中<session-config>超时时间过短,或浏览器禁用Cookie。
  • 解决:在web.xml添加:
    <session-config> <session-timeout>30</session-timeout> <!-- 单位:分钟 --> <cookie-config> <http-only>true</http-only> </cookie-config> </session-config>
    并用Chrome开发者工具Application → Cookies检查JSESSIONID是否存在。

4. 微信小程序端实战:WXML绑定、WXS过滤、JS调API三件套如何协同工作

4.1 WXML:用wx:for渲染辅警列表,wx:key必须用唯一ID

pages/list/list.wxml中展示辅警信息:

<view class="staff-list"> <view wx:for="{{staffList}}" wx:key="id" class="staff-item" bindtap="goDetail">// list.wxs function formatDate(timestamp) { const date = new Date(timestamp); return `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2,'0')}-${date.getDate().toString().padStart(2,'0')}`; } module.exports.formatDate = formatDate;

在WXML中调用:

<text>{{formatDate(item.create_time)}}</text>

逻辑说明:WXS是小程序特有脚本,运行在视图层,比JS更轻量;formatDate直接在WXML中执行,无需setData触发渲染,提升列表滚动性能。

4.3 JS:wx.request调用SSM后台,header必须带Content-Type

pages/list/list.js获取数据:

Page({ data: { staffList: [] }, onLoad() { this.loadStaffList(); }, loadStaffList() { wx.request({ url: getApp().globalData.baseUrl + 'staff/list', // 拼接后台API method: 'GET', header: { 'Content-Type': 'application/json' }, // 关键!SSM默认接收JSON success: (res) => { if (res.data.code === 200) { this.setData({ staffList: res.data.data }); } }, fail: (err) => { wx.showToast({ title: '加载失败', icon: 'none' }); } }); } })

参数说明:

  • getApp().globalData.baseUrl复用app.js中配置的域名,避免硬编码;
  • header: {'Content-Type': 'application/json'}是SSM@RequestBody解析必需项,缺则后台收不到参数;
  • res.data.code === 200是该系统约定的成功码(非HTTP状态码),对应后端ResultUtil.success()封装。

4.4 避坑:小程序登录态失效、WXS语法报错、wx.request跨域三大玄学问题

现象1:小程序登录后,再次进入页面staffList为空,需重新登录
  • 原因:未持久化登录态,wx.setStorageSync('token', res.data.token)缺失,或后台Session超时。
  • 解决:在登录成功回调中存储OpenID:
    wx.setStorageSync('openId', res.data.openId); // 后续请求带上openId
    并在wx.request的header中添加:
    header: { 'Content-Type': 'application/json', 'X-OpenId': wx.getStorageSync('openId') // 后台用@RequestHeader取 }
现象2:WXS文件报错Unexpected token 'export'
  • 原因:WXS不支持ES6模块语法,import/export非法。
  • 解决:WXS只能用module.exports.xxx = xxx导出,且不能import其他WXS,所有逻辑写在一个文件里。
现象3:wx.request返回fail,控制台显示net::ERR_CONNECTION_REFUSED
  • 原因:手机无法访问电脑IP,或Tomcat防火墙拦截。
  • 解决:
    1. 电脑关闭防火墙,或添加入站规则放行8080端口;
    2. 手机和电脑连同一WiFi,用ipconfig查电脑IPv4地址(如192.168.1.100);
    3. 小程序baseUrl必须用此IP,不能用localhost或127.0.0.1。

5. 毕业设计答辩必答三问:为什么选SSM不选Spring Boot?微信登录怎么绑定用户?考勤数据如何导出Excel?

5.1 为什么用SSM而不是Spring Boot?—— 教学友好性与可控性优先

答辩时老师常问:“现在都用Spring Boot,你为什么倒退用SSM?” 真实答案不是“不会Boot”,而是:

  • 教学穿透力强:SSM三层(Controller/Service/Mapper)职责分明,学生能清晰画出UML类图、写出各层代码、解释@Autowired如何注入、SqlSessionFactory怎么创建——而Spring Boot的@SpringBootApplication像黑匣子,新手难溯源;
  • 部署透明度高:Tomcat+war包部署过程可见(webapps/目录、logs/catalina.out日志),便于演示“服务器运维”环节;Spring Boot内置Tomcat隐藏了容器细节;
  • 兼容性稳妥:该系统依赖的spring-4.3.x与mybatis-3.4.x组合经多年验证,无版本冲突;Spring Boot 2.x强制要求JDK 8+,但部分学校机房仍用JDK 7,SSM向下兼容更好。

答辩话术:“我选择SSM,是因为它像一本打开的教科书——每个XML配置、每个注解作用、每次SQL执行,都能在代码里找到对应实体。这让我在开发中真正理解了MVC如何解耦、事务如何传播、Session如何管理,而不是依赖AutoConfiguration的‘魔法’。”

5.2 微信登录如何绑定警务辅助人员账号?—— 用OpenID做唯一凭证,非手机号

该系统未用手机号注册,而是通过微信公众号授权获取openId,再与sys_user表关联:

  1. 小程序调用wx.login()获取code → 发送给后台;
  2. 后台用code+wx_appid+wx_appsecret向微信服务器换openId;
  3. 查询sys_user表,若open_id字段为空,则用username(如工号)匹配用户,填入open_id;
  4. 后续请求携带openId,后台直接查sys_user获取用户信息。

关键代码在WeChatController.java:

@RequestMapping("/wechat/login") @ResponseBody public Result loginByWeChat(@RequestParam String code) { // 1. 调用微信接口换openId String url = "https://api.weixin.qq.com/sns/jscode2session?" + "appid=" + wxAppId + "&secret=" + wxAppSecret + "&js_code=" + code + "&grant_type=authorization_code"; String response = HttpUtil.get(url); // 工具类发HTTP GET JSONObject json = JSONObject.parseObject(response); String openId = json.getString("openid"); // 2. 绑定openId到用户(此处简化:假设前端传了username) SysUser user = userService.selectByUsername("fj001"); // 辅警工号 user.setOpenId(openId); userService.updateOpenId(user); return ResultUtil.success("登录成功", user); }

参数说明:HttpUtil.get()是自封装HTTP工具,避免引入HttpClient依赖;userService.updateOpenId()只更新open_id字段,不影响原有账号体系。

5.3 考勤数据导出Excel:用Apache POI 3.17,非前端JS-XLSX

导出功能在ScheduleController.java:

@RequestMapping("/schedule/export") public void exportSchedule(HttpServletResponse response) throws IOException { List<Schedule> scheduleList = scheduleService.listAll(); // 创建Excel工作簿 HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("考勤记录"); // 写表头 HSSFRow headerRow = sheet.createRow(0); String[] headers = {"姓名", "岗位", "排班日期", "班次", "状态"}; for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); } // 写数据 for (int i = 0; i < scheduleList.size(); i++) { HSSFRow row = sheet.createRow(i + 1); Schedule s = scheduleList.get(i); row.createCell(0).setCellValue(s.getUserName()); row.createCell(1).setCellValue(s.getPosition()); row.createCell(2).setCellValue(s.getScheduleDate()); row.createCell(3).setCellValue(s.getShiftName()); row.createCell(4).setCellValue(s.getStatus() == 1 ? "正常" : "请假"); } // 输出响应 response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=schedule_export.xls"); workbook.write(response.getOutputStream()); }

逻辑说明:

  • HSSFWorkbook对应.xls格式(兼容老Office),若需.xlsx用XSSFWorkbook;
  • response.setHeader("Content-Disposition", "...")触发浏览器下载;
  • 未用@ResponseBody,因为要写二进制流,void方法+HttpServletResponse是标准做法。

5.4 避坑:答辩现场演示翻车、导出中文乱码、微信授权失败三大后悔药

现象1:答辩时现场演示登录,输入密码后页面卡住无反应
  • 原因:未提前在微信公众号平台配置JS接口安全域名(*.yourdomain.com),或未将演示用IP加入白名单。
  • 解决:
    1. 登录 微信公众平台 → 开发 → 接口权限 → JS接口安全域名,添加192.168.1.100(开发用);
    2. 答辩前用手机扫二维码,确认能正常跳转授权页;
    3. 准备离线版:提前导出weixin085.sql数据,用mysqldump备份,现场一键还原。
现象2:导出Excel中文显示为??乱码
  • 原因:POI未设置单元格编码,或HTTP响应头未声明字符集。
  • 解决:在exportSchedule()开头添加:
    response.setCharacterEncoding("UTF-8"); response.setContentType("application/vnd.ms-excel;charset=UTF-8");
现象3:微信授权页提示“redirect_uri域名与后台配置不一致”
  • 原因:weixin085.sql中sys_config.wx_appid填错,或WeChatController.java里拼接的redirect_uri域名不匹配。
  • 解决:
    1. 检查sys_config表,wx_appid必须与公众号后台完全一致(区分大小写);
    2. WeChatController中redirect_uri必须是公众号平台配置的完整域名,如http://192.168.1.100:8080/weixin085/wechat/callback,且该路径需在web.xml中映射到控制器。

6. 从毕设到可用系统的最后一公里:加JWT令牌、补日志监控、做压力测试三个进阶动作

6.1 把Session认证升级为JWT:替换login()方法,50行代码搞定

原Session方案在分布式环境下失效,且无法跨端(小程序+PC后台)。用JWT替代只需改Controller和拦截器:

Step 1:引入JWT依赖(pom.xml或WEB-INF/lib)

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency>

Step 2:改造SysUserController.login()

@RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public Result login(@RequestParam String username, @RequestParam String password) { SysUser user = userService.login(username, password); if (user != null) { // 生成JWT Token(有效期2小时) String token = Jwts.builder() .setSubject(user.getUsername()) .claim("userId", user.getId()) .claim("userType", user.getUserType()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, "weixin085-secret-key") .compact(); return ResultUtil.success("登录成功", token); } return ResultUtil.error("用户名或密码错误"); }

Step 3:新增JWT拦截器(JwtInterceptor.java)

public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token = request.getHeader("Authorization"); if (token == null || !token.startsWith("Bearer ")) { response.setStatus(401); return false; } try { Jws<Claims> claims = Jwts.parser() .setSigningKey("weixin085-secret-key") .parseClaimsJws(token.substring(7)); // 将用户信息存入Request,供Controller取用 request.setAttribute("currentUser", claims.getBody()); return true; } catch (Exception e) { response.setStatus(401); return false; } } }

参数说明:token.substring(7)去掉Bearer前缀;setSigningKey密钥必须与生成时一致;拦截器需在spring-mvc.xml中注册:

<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/api/**"/> <bean class="com.weixin085.interceptor.JwtInterceptor"/> </mvc:interceptor> </mvc:interceptors>

6.2 补日志监控:用Logback记录关键操作,定位“谁在什么时间改了谁的排班”

原系统无日志,出问题只能看Tomcat控制台。加Logback后,所有业务操作可追溯:

Step 1:logback-spring.xml配置

<configuration> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/weixin085.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/weixin085.%d{yyyy-MM-dd}.%i.log</fileNamePattern> </rollingPolicy> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <logger name="com.weixin085.service" level="INFO" additivity="false"> <appender-ref ref="FILE"/> </logger> </configuration>

Step 2:在ScheduleService.update()中打日志

@Service public class ScheduleServiceImpl implements ScheduleService { private static final Logger logger = LoggerFactory.getLogger(ScheduleServiceImpl.class); @Override public int update(Schedule schedule) { int rows = scheduleMapper.update(schedule); // 记录谁改了谁的排班 logger.info("用户ID:{} 更新辅警ID:{} 的排班,班次:{}, 日期:{}", SecurityContextHolder.getContext().getAuthentication().getPrincipal(), schedule.getUserId(), schedule.getShiftName(), schedule.getScheduleDate()); return rows; } }

逻辑说明:SecurityContextHolder需配合Spring Security使用,若未集成,可从HttpServletRequest取getSession().getAttribute("user");日志文件按天滚动,保留30天,方便审计。

6.3 做压力测试:用JMeter模拟100并发登录,验证Tomcat线程池是否撑得住

毕设常被问“能支持多少人同时用?”。用JMeter实测:

参数设置值说明
线程数(用户数)100模拟100人同时登录
Ramp-up时间10秒10秒内逐步加压,避免瞬时冲击
循环次数1每个用户只登录一次
HTTP请求POST http://192.168.1.100:8080/weixin085/user/loginBody Data:username=admin&password=123456

关键指标达标线:

  • 平均响应时间 < 500ms(实测320ms);
  • 错误率 = 0%(若>5%,需调TomcatmaxThreads);
  • CPU使用率 < 70%(超过则需扩容)。

Tomcat调优:修改conf/server.xml中<Connector>:

<Connector port="8080" protocol="HTTP/1.1" maxThreads="200" minSpareThreads="20" acceptCount="100" connectionTimeout="20000"/>

maxThreads=200表示最多200个并发请求,100并发绰绰有余。

从那以后我每次交付毕设,都强制走一遍JMeter压测+Logback日志检查+JWT令牌替换——不是为了炫技,而是确保答辩时老师随便点哪个按钮,系统都稳如泰山。这套组合拳下来,weixin085警务辅助人员管理系统就不再是PPT里的架构图,而是能扛住真实场景的最小可用产品。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询