每年毕业季,都能在技术社区里看到“SSM垃圾分类管理系统”这个选题。它是Java方向课程设计和毕业设计里,出现频率最高的题目之一。说实话,不少同学拿到源码之后,第一反应往往是“代码能跑就行”,至于SSM框架是怎么串起来的、数据库为什么要这么设计、部署到Tomcat之后为什么有的页面白屏,这些关键问题基本没过脑子。
这篇文章我就从实际开发者的角度,把“SSM基于Java的垃圾分类管理系统”从技术选型、数据库设计、核心功能实现到本地调试部署的完整链路拆开讲一遍。无论你是刚学完JavaWeb准备做课设,还是毕设选了这个题目正在挠头,或者是拿到别人源码但不知道怎么落地,这篇文章应该都能帮你在现有基础上往前推进一大步。我会把为什么这么做、有哪些坑、怎么排查问题都讲清楚,而不是只给你一堆代码片段。
1. 垃圾分类管理系统到底在管什么:需求梳理与功能边界
先别急着写代码。拿到任何系统,第一件事是把业务看清楚。垃圾分类管理系统从表面看是个“信息管理系统”,但它的业务逻辑比一般的增删改查稍微复杂一点,因为它牵扯到两类角色、两条核心流程。
1.1 系统里的两类用户
垃圾管理系统的用户,实际只有两种:普通居民用户和后台管理员。这两个身份对应的功能和操作权限完全不同。
普通用户侧,核心功能是:注册登录、查看垃圾类别与投放指南、提交垃圾投放信息(也就是登记自己扔了什么垃圾、扔了多少)、查询积分变动记录、修改个人资料。日常操作里用的最多的是“查分类”和“记投放”两个动作。
管理员侧,负责的事情则是:维护基础数据(垃圾类别、积分规则)、管理用户账户(禁用/启用)、审核用户的投放记录,以及查看全站的投放统计和积分明细。管理端的数据看板是整个系统价值的集中体现——垃圾分类如果做了但没法统计,就等于白做。
1.2 两条核心业务流程
第一条流程是“投放登记流程”:用户登录后,选择垃圾类别、填写重量、选择投放地址和时间,提交给系统。这里就出现了一个业务分支——提交之后要不要审核?有些系统设计成提交直接生效,积分立刻到账,适合内部测试;但正规一点的设计是管理员需要抽查或者全部审核,审核通过后积分才入账。在这个系统里,推荐采用“提交待审核,审核通过后积分到账”的策略,这样更贴近真实场景,答辩时也有的讲。
第二条流程是“积分流转流程”:投放记录通过审核后,系统根据垃圾的类别和重量计算积分,增加用户积分余额,同时写入积分明细表。积分明细的保留很重要,因为后期用户投诉“我扔了三公斤纸壳子怎么积分没涨”的时候,管理员能查到是哪条记录出了问题。
1.3 功能要收敛,别什么都做
很多同学拿到源码后会想着“我要加个扫码识别”“我要加个地图找垃圾桶”,有想法是好事,但先想清楚核心是哪些。一个合格的课设/毕设系统,能把“用户-投放-审核-积分-统计”这条主线跑通,已经能拿一个不错的成绩了。在功能上做加法之前,先确保主流程没有bug。至于扩展功能(比如对接地图API、接入智能秤、生成垃圾识别模型),可以作为后期亮点提出来,但不要一开始就塞进系统里,否则很容易把自己套进去。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 为什么选SSM而不是Spring Boot:技术选型背后的实际考量
题目明确要求了SSM框架,但我还是想多说两句技术选型的逻辑。很多同学不理解:Spring Boot现在这么火,为什么还要用SSM这种“老”组合?原因其实不复杂,主要有三点。
第一,SSM是理解JavaWeb底层原理的好教材。 弹簧(Spring)负责对象管理,SpringMVC负责HTTP请求的接收、分发和响应,MyBatis负责数据库的SQL映射和持久化。这三个框架各管一段,边界清晰,你在里面能直观地看到Web请求是怎么从Tomcat进到Controller、再经过Service、最后落到Mapper和XML映射的。Spring Boot把这些都封装了,是方便,但你很难知道背后发生了什么。
第二,课程体系和答辩的契合度。 很多高校的教学大纲至今仍然以SSM为主线路,而且毕业设计答辩老师通常问的问题里,很大一部分是“Spring的Bean生命周期”“SpringMVC的DispatcherServlet流程”“MyBatis的一级缓存和二级缓存”。如果用Spring Boot,这些问题依然存在,但和你的项目代码对应关系不那么直接。而用SSM,这些问题都可以在你自己的配置文件和代码里找到答案。
第三,配置文件本身就是项目的一部分。 SSM项目的核心,其实是那几张配置文件:web.xml、spring-mvc.xml、spring-mybatis.xml、db.properties。你把这些文件每一个结点搞明白,框架就没啥秘密了。我之前带过一个学生,项目跑起来后问他数据库连接串在哪里配的,他愣了半天没答上来——这就是典型的只会跑不会看。
如果你是非要做Spring Boot版本的,也可以先把SSM这套跑通再迁移,迁移的成本其实没有想象中高,因为业务代码里的DAO、Service、Controller分层是通用的。
3. 数据库设计的核心表结构与建表思路
数据库是这类项目的重头戏。垃圾分类管理系统的表不多,一般五张左右就够,但表结构的合理程度直接决定后面业务代码好不好写。
3.1 整体表设计思路
我建议把表设计成下面这几个模块:用户、垃圾类别、投放记录、积分明细、公告。有的系统还会额外加一张“管理员表”,但其实没有必要——在用户表里加一个role字段区分角色就够了,省得登录逻辑里还得多查一张表。
从表关系来看,投放记录表通过user_id关联用户表,通过category_id关联垃圾类别表,是典型的多对一关系。积分明细表则完全由系统产生,用户不做直接操作。这两张明细类表的设计,要尽量保留冗余字段(比如记录投放时的类别名称、当时的积分值),因为历史数据经常需要在统计时直接取用,过度追求范式会让查询逻辑变得非常复杂。
3.2 核心表结构详解
下面重点拆一下用户表和投放记录表,这两张表基本决定了系统的数据质量。
用户表(user)建议如下设计:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键,自增 |
| username | varchar(32) | 用户名,唯一 |
| password | varchar(64) | 密码,MD5加密存储 |
| phone | varchar(16) | 手机号,选填 |
| role | tinyint | 角色,0普通用户,1管理员 |
| points | int | 积分余额,默认0 |
| status | tinyint | 状态,0正常,1禁用 |
| create_time | datetime | 创建时间 |
这里有两个细节值得注意。密码字段长度设为64而不是32,是因为MD5密文是32位,但如果你后续要用“盐值+MD5”的方式加密,长度就不一定了,留点余量更稳妥。积分余额直接冗余在用户表上,是为了查询用户信息时不用再去积分明细表里做SUM聚合,用空间换时间,在小项目里完全值得。
投放记录表(deposit_record)设计如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键,自增 |
| user_id | int | 用户ID |
| category_id | int | 垃圾类别ID |
| weight | decimal(6,2) | 重量(公斤) |
| address | varchar(128) | 投放地址 |
| status | tinyint | 状态,0待审核,1通过,2驳回 |
| points_awarded | int | 本次获积分 |
| remark | varchar(255) | 备注/驳回原因 |
| create_time | datetime | 提交时间 |
weight用decimal而不是float/double,是为了避免浮点数精度问题。积分字段直接算好后存在记录里,等审核通过时一次性写入用户积分余额。
3.3 建表SQL示例
给你一个可直接执行的建表SQL片段,用的是MySQL 5.7以上的方言,字符集统一用utf8mb4(四字节UTF-8),否则遇到特殊符号会报错或者乱码:
sql复制CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名',
`password` varchar(64) NOT NULL COMMENT '密码',
`phone` varchar(16) DEFAULT NULL COMMENT '手机号',
`role` tinyint(4) NOT NULL DEFAULT '0' COMMENT '角色:0用户 1管理员',
`points` int(11) NOT NULL DEFAULT '0' COMMENT '积分余额',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0正常 1禁用',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
CREATE TABLE `deposit_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户ID',
`category_id` int(11) NOT NULL COMMENT '垃圾类别ID',
`weight` decimal(6,2) NOT NULL COMMENT '重量/公斤',
`address` varchar(128) DEFAULT NULL COMMENT '投放地址',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0待审核 1通过 2驳回',
`points_awarded` int(11) NOT NULL DEFAULT '0' COMMENT '获得积分',
`remark` varchar(255) DEFAULT NULL COMMENT '审核备注',
`create_time` datetime NOT NULL COMMENT '提交时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_category_id` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='投放记录表';
注意到user表用了UNIQUE KEY(唯一索引),因为用户名在登录时必须唯一。投放记录表把user_id和category_id都建了普通索引,这是为了按用户查记录和按类别做统计时不至于全表扫描。虽然项目数据量不大,索引建不建无所谓,但作为规范,这个习惯值得养成。
4. 用户端与管理端功能实现:从登录鉴权到积分流转
表结构定了,接下来是代码实现。SSM项目虽然配置文件多,但业务代码的结构是很清晰的:Controller接收请求、Service处理业务逻辑、Mapper操作数据库。下面捡几个最核心、最容易出问题的功能点细说。
4.1 登录鉴权与拦截器配置
登录功能看似简单,但“用户没登录就不能访问受保护页面”这一个需求,在新手手里经常做歪。有些人是在每个Controller里都判断一次session,代码大量重复;有些人则是完全没做拦截,直接访问内部页面。
正确的做法是使用SpringMVC的拦截器(Interceptor)统一处理。先写一个LoginInterceptor,实现HandlerInterceptor接口:
java复制public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("loginUser");
if (user == null) {
// 未登录,重定向到登录页
response.sendRedirect(request.getContextPath() + "/login");
return false;
}
return true;
}
}
然后在spring-mvc.xml里注册拦截器,同时配置放行规则:
xml复制<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/**"/>
<!-- 放行登录页面和登录接口 -->
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/doLogin"/>
<!-- 放行静态资源 -->
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>
<mvc:exclude-mapping path="/images/**"/>
</mvc:interceptor>
</mvc:interceptors>
这里有个很典型的坑:如果忘了放行静态资源,页面上的CSS和JS全都会被拦截,浏览器控制台全是404,页面看起来就像“裸奔”一样,全是文字没有样式。排查的时候先看拦截器配置,再往下查别的。
4.2 垃圾类别查询与MyBatis动态SQL
垃圾分类类别通常分四大类:可回收物、有害垃圾、厨余垃圾、其他垃圾。用户端需要一个按照类别展示垃圾信息的页面,管理员需要能够新增、编辑、删除类别。查询这块,用了MyBatis的动态SQL,支持按类别名称模糊搜索。
Mapper接口:
java复制public interface WasteCategoryMapper {
List<WasteCategory> selectList(@Param("keyword") String keyword);
WasteCategory selectById(@Param("id") Integer id);
int insert(WasteCategory category);
int update(WasteCategory category);
int deleteById(@Param("id") Integer id);
}
对应的XML映射文件:
xml复制<select id="selectList" resultType="com.xxx.entity.WasteCategory">
SELECT * FROM waste_category
<where>
<if test="keyword != null and keyword != ''">
AND name LIKE CONCAT('%', #{keyword}, '%')
</if>
</where>
ORDER BY sort
</select>
动态SQL里最常用的就是<if>和<where>。<where>标签会自动处理掉第一个条件前面的AND,避免你手动拼接时出现“WHERE AND name=...”这种语法错误。这类小细节你不知道的时候怎么也查不出错在哪,知道了就能少浪费一晚上。
4.3 积分流转的事务处理
积分流转是这个系统里最重要的“钱袋子”逻辑。用户提交投放记录本身不改变积分余额,管理员审核通过后,系统要同时干两件事:把这条记录的状态从“待审核”改成“通过”,然后把积分加到用户账户里。这两步操作必须在一个事务里完成,否则出现“记录改了就刷新,但用户积分没到账”的情况,数据就不一致了。
在SSM中实现事务很简单,在spring-mybatis.xml里开启事务管理器,然后在Service方法上标注@Transactional注解:
java复制@Service
public class DepositRecordServiceImpl implements DepositRecordService {
@Autowired
private DepositRecordMapper depositRecordMapper;
@Autowired
private UserMapper userMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void auditPass(Integer recordId, Integer adminId) {
// 1. 更新记录状态
DepositRecord record = depositRecordMapper.selectById(recordId);
if (record == null) {
throw new RuntimeException("投放记录不存在");
}
record.setStatus(1);
depositRecordMapper.updateStatus(record);
// 2. 给用户加积分
userMapper.increasePoints(record.getUserId(), record.getPointsAwarded());
// 3. 记录积分明细
pointRecordMapper.insert(new PointRecord(record.getUserId(), record.getPointsAwarded(), "投放审核通过"));
}
}
rollbackFor = Exception.class的意思是说,任何异常都会触发回滚——这个配置比默认的“运行时异常才回滚”要严格,正好是业务场景需要的。如果你在测试时发现“明明报了错,数据却还是改了”,十有八九是事务没生效,先检查spring-mybatis.xml里有没有配置<tx:annotation-driven transaction-manager="transactionManager"/>。
4.4 管理端统计与数据看板
管理端的统计功能很加分,但代码逻辑并不复杂。常见的统计查询有三个:每周/每月的总投放量、各垃圾类别的投放占比、用户积分排行。
以“每日投放量”为例,MySQL里用DATE_FORMAT函数把datetime格式化为日期,然后按天分组聚合:
xml复制<select id="selectDailyCount" resultType="map">
SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS day, COUNT(*) AS total
FROM deposit_record
WHERE status = 1
GROUP BY day
ORDER BY day ASC
</select>
返回的List<Map<String,Object>>可以直接转成JSON,交给前端用ECharts画折线图。这一步功能实现起来成本很低,但视觉效果好,是答辩演示时最吸引人的页面之一。
4.5 前端页面方案
SSM项目的前端,绝大多数用的是JSP+Bootstrap的组合。JSP可以直接通过EL表达式和JSTL标签从后端拿数据,不需要前后端分离,对课设和毕设来说开发效率是最高的。
页面布局建议采用经典的“顶部导航+左侧菜单+右侧内容”框架。顶部和左侧是公共部分,可以用include指令抽出来:
jsp复制<%@ include file="/WEB-INF/views/common/header.jsp" %>
右侧内容区放各自页面的业务组件。Bootstrap的栅格系统、表格样式、模态框,足够应付绝大多数展示需求,不需要额外引入繁琐的UI框架。记住一点:前端漂亮的前提是后端数据接口要稳定,先把后端逻辑调通,再去调样式,否则很容易陷入“改前端改到怀疑人生”的循环。
5. 本地调试部署全流程:从环境准备到跑通第一个请求
环境问题,是新手在这类项目里卡住最多的地方。拿到项目源码,第一步不是打开IDEA,而是先把环境版本确认好。
5.1 版本矩阵:不要用你笔记本里最新的组件
这套系统是基于Java 8 + SSM + MySQL 5.7 + Tomcat 8.5开发的。如果你机器上装的是JDK 17、Tomcat 10、MySQL 8.0,直接拿源码跑大概率会报错。这不是源码问题,是版本兼容问题。
推荐版本组合:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 1.8 | 核心,不要用11+ |
| Maven | 3.6.3 | 3.8+一般也行 |
| Tomcat | 8.5.x | 别用10,包名变了 |
| MySQL | 5.7.x | 8.0需要额外配驱动 |
| IDEA | 2020.3+ | 社区版也够用 |
如果确实只有JDK 17、MySQL 8.0,也不是不能跑,但需要做三处调整:pom.xml里的mysql-connector-java版本换成8.0.x,db.properties里的driverClass换成com.mysql.cj.jdbc.Driver,JDBC连接串里加上serverTimezone=Asia/Shanghai。这三处不改,迟早要报错。
5.2 导入项目到IDEA的完整步骤
第一步,用IDEA的Open功能选择项目根目录,选择Maven导入方式,等待依赖下载。如果首次下载很慢,在Maven的settings.xml中配置阿里云镜像:
xml复制<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
第二步,修改db.properties数据库连接信息:
properties复制jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/garbage_db?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=你的数据库密码
如果你的MySQL是8.0,驱动和URL要改成上面说过的形式。
第三步,配置Tomcat。在IDEA的Run/Debug Configurations里新增Tomcat Server -> Local,在Deployment页签里添加Artifact(注意选war格式),Application context一般填/garbage或者直接填/。启动Tomcat。
第四步,在浏览器访问http://localhost:8080/garbage(如果你的context path配的是/garbage),能看到登录页,说明部署成功了。
5.3 我遇到过的三种启动报错与处理方法
报错一:Artifact部署失败。 大部分是Artifact没配置对,或者项目没有先执行package。做法是先执行一次Maven的clean package,确认编译通过,再去Deployment里添加那个war包。
报错二:数据库连接失败。 现象是启动时Tomcat正常,但页面一访问就报500,错误日志里有Cannot create PoolableConnectionFactory。原因99%是数据库没启动、密码不对、或者URL里的库名不对。先确认用命令行mysql -uroot -p能连上,再检查SQL脚本是否真的执行了。
报错三:端口被占用。 启动时提示Port 8080 was already in use。这多半是之前有Tomcat进程没关掉。Windows下用netstat -ano | findstr 8080找到PID,然后taskkill /F /PID 进程号干掉它。或者干脆把Tomcat端口改成8081,省事。
6. 我在实际开发中踩过的坑与排查记录
这一节写点拿不到源码文档、只能在实战中体会的教训。每一条我都实际踩过,处理逻辑也放在这,你可以照着排查。
6.1 MyBatis的Mapper接口与XML映射“找不着”
报错信息类似于Invalid bound statement (not found): com.xxx.mapper.UserMapper.selectByUsername。出现这个错误,先检查Mapper接口和XML文件的namespace是否完全一致,其次检查方法名和XML里的id是否一致,最后确认在spring-mybatis.xml里有没有配置Mapper扫描:
xml复制<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.xxx.mapper"/>
</bean>
还有一个隐藏的坑:如果你把UserMapper.xml放在java目录下(和Mapper接口放一起),而pom.xml里没有配置把xml文件打包进去,那编译出来的target目录就不会有XML文件。解决方法是在pom.xml里加这一段:
xml复制<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
6.2 中文乱码:控制台、页面、数据库三层排查
中文乱码是SSM项目里出现频率最高的历史遗留问题,原因可能出现在三层:Tomcat接收参数编码、JSP页面输出编码、数据库连接编码。
最直接的排查顺序是:
- 数据库连接串里加
useUnicode=true&characterEncoding=utf8; - JSP页面顶部设置
<%@ page contentType="text/html;charset=UTF-8" language="java" %>; - Tomcat的server.xml里给Connector加
URIEncoding="UTF-8"。
这三处都照顾到,大部分乱码都能解决。如果数据库里的数据本身就乱,那就是导入SQL文件时字符集选错了,重新用utf8的脚本导入一次。
6.3 Session失效、登录跳转后循环重定向
拦截器配置好之后,如果出现“登录成功后跳转回登录页”的循环,说明登录接口本身也被拦截器拦截了。记得在拦截器配置里把你处理登录请求的Controller路径排除掉。
另外,Session的默认失效时间是30分钟,用户操作到一半登录态丢了,跳回登录页是正常现象。如果想延长,在web.xml里可以做如下配置:
xml复制<session-config>
<session-timeout>120</session-timeout>
</session-config>
单位是分钟。课设演示的时候,最尴尬的就是演示到一半被踢回登录页,这个值建议调大一点。
6.4 页面CSS样式丢失
启动后页面能打开,但完全没有样式。优先排查路径问题:JSP里引入CSS和JS的路径,是否用了${pageContext.request.contextPath}作为前缀。比如:
jsp复制<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
如果直接用/css/bootstrap.min.css,部署到根路径下没问题,但一旦上下文路径不是根路径,样式就全丢了。
6.5 数据库脚本导入失败
拿到项目的SQL文件后,在Navicat或命令行执行导入,有时候会报错:多表创建顺序不对,或者字段名和关键字冲突。
关键词冲突是很容易忽视的问题。比如这张用户表,我把表名叫做user,其实user在MySQL里是保留字,虽然有的版本能用,但严格来说应该用反引号包起来:CREATE TABLE \user``。建表时最好尽量避免使用保留字,如果项目已经用了,可以把表名改成sys_user或t_user,可读性反而更好。
关于网上流传的源码资源,这里多说一句: 拿到任何人的项目资料,第一步先做静态代码审查——看看pom.xml里引了哪些依赖、有没有恶意脚本、数据库脚本里有没有异常的操作。装好环境跑通后再去改自己的业务逻辑。这样做不止是安全考虑,也是让你对项目结构的理解更扎实,毕竟答辩时老师可能会抽着问某个类的作用,你要是连类在哪个包下都不知道,印象分会大打折扣。
7. 项目扩展:把课设变成答辩亮点
基础功能跑通只是及格线,要让答辩老师眼前一亮,可以做几个低成本但效果明显的扩展。我建议从下面两个方向里选一个,不要贪多。
7.1 垃圾分类知识库与搜索联想
在原有垃圾类别管理的基础上,扩展一张“垃圾物品表”(item_name、category_id、detail_pic、description),录入几百种常见垃圾物品及其分类结果。用户端做一个搜索框,输入物品名称,自动返回该物品属于哪一类、投放建议是什么。
这个功能在逻辑上非常简单,就是普通的模糊查询,但它极大提升了系统的实用性。更妙的是,它和高频搜索词可以联动:每次搜索都记录关键词,后台统计热门搜索,形成“大家都在问”的模块。这种设计体现的是产品思维,答辩时加分项非常明显。
7.2 数据可视化大屏
管理端在现有统计基础上做一个大的数据看板页面,用ECharts渲染三个图:近30天投放趋势折线图、垃圾分类类别占比饼图、各小区(投放地址)投放量柱状图。数据直接从deposit_record表聚合查询,不需要加表。
大屏页面在展示时的视觉冲击力,远大于中规中矩的表格页面。你说数据是实打实的、代码是自己写的、而且能说清楚SQL怎么写的,老师很难不满意。
7.3 权限控制再做细一点
现在的系统只有普通用户和管理员两级。如果想让项目更有层次,可以增加“垃圾分类督导员”这个中间角色。督导员可以审核投放记录,但不能修改基础数据,不能查看全站财务类的积分流水统计。实现方式也很简单:拦截器里根据role字段做多级判断,或者在方法上自定义一个@RequireRole(role = 1)注解。
这块内容的实现成本不高,但很能体现对权限控制的理解深度。做之前先想清楚,现有拦截器是统一配置的,如果加了多角色,要保证管理员的功能、督导员的功能、普通用户的功能之间互不越权——这个设计思路去搜索框里搜“Java 自定义注解 权限控制”,一搜一大把,但能自己梳理清楚的没几个。
最后一个项目经验层面的建议:如果这是你的课设或毕设,不要只在最后两周冲刺,至少给自己留一个月时间。第一周跑通项目、看懂代码,第二周开始改一两个功能点并处理bug,第三周补测试数据和答辩PPT,第四周模拟答辩查漏补缺。我见过太多人卡在环境问题上,一卡就是一周,最后連交作业都赶不上。这套SSM垃圾管理系统本身不复杂,真正复杂的,是你对每一个环节的掌控程度。源代码和数据库脚本都在你手上,跑通不是目的,讲清楚才是。
