网站里图片的作用电子商务网站建设方案范文
网站里图片的作用,电子商务网站建设方案范文,正规网站开发文案,公司网站设计意见若依毕业设计实战#xff1a;从模块定制到生产级部署的完整路径 摘要#xff1a;许多学生在使用若依#xff08;RuoYi#xff09;框架完成毕业设计时#xff0c;常陷入“能跑但不可维护”的困境#xff1a;权限配置混乱、前后端耦合严重、缺乏真实业务场景适配。本文基于…若依毕业设计实战从模块定制到生产级部署的完整路径摘要许多学生在使用若依RuoYi框架完成毕业设计时常陷入“能跑但不可维护”的困境权限配置混乱、前后端耦合严重、缺乏真实业务场景适配。本文基于实战经验详解如何在若依基础上进行模块化改造实现角色-菜单-API三级权限解耦并集成JWT令牌刷新、操作日志审计等生产级功能。读者将掌握一套可复用的二次开发模板显著提升系统健壮性与答辩竞争力。1. 学生常见痛点为什么“能跑”≠“能交付”权限模型僵化若依默认“角色-菜单”二级模型在毕设场景里一旦遇到“同一角色不同数据范围”就抓瞎。例如“班主任”只能看本班成绩但校级管理员要看全部硬编码if(roleadmin)很快变成灾难。代码冗余 逆向工程黑箱很多同学直接跑ruoyi-generator一键生成代码结果Controller/Service/Mapper三层堆满重复getById、listAll后期需求一改牵一发动全身Git 提交记录全是“fix again”。前后端耦合把 Vue 文件直接塞进resources/static里打包一次 3 min上线发现路径 404又回夹带baseUrl window.location.origin这种“玄学补丁”。缺失真实业务场景为了“有图有真相”硬塞一个商城秒杀模块但订单状态机、库存扣减全是伪代码老师一问“超卖怎么解决”就原地爆炸。2. 技术选型MyBatis-Plus vs JPA 的适配成本若依原生 MyBatis 的优劣优点SQL 可控、分页插件成熟、二级缓存好配缺点手写 XML 费手字段一改全文搜索替换换 MyBatis-Plus 的代价只需把mybatis依赖换成mybatis-plus-boot-starter旧 XML 零改动即可运行代码生成器模板里把Mapper.java的基类换成BaseMapperT即可砍掉 80% 的*Mapper.xml注意若依自带的DataScopeInterceptor依赖原生MappedStatement需要重写一个PlusDataScopeInterceptor成本 1 h 以内换 Spring Data JPA 的代价需要把BaseEntity的TableId(type IdType.AUTO)改成GeneratedValue所有*Mapper接口要新写Entity与Repository若依的PageUtils与 JPA 的Pageable不是一一对应分页封装得重写结论毕业设计周期 3 个月以内不建议折腾 JPAMyBatis-Plus 是性价比之王3. 核心改造 1三级权限解耦目标角色 → 菜单 → API 按钮三表分离支持“同角色不同数据行级权限”。数据模型微调在sys_role与sys_menu之间增加sys_role_menu_scope表核心字段id bigint PK role_id bigint FK→sys_role menu_id bigint FK→sys_menu dept_ids varchar 数据范围逗号分隔部门 ID api_tag varchar 预留给前端按钮用自定义注解RequiresPermissionsExtTarget({ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface RequiresPermissionsExt { String[] value() default {}; // 需要权限字符数组 DataScope dataScope() default DataScope.ALL; }AOP 拦截实现逻辑前置读取SecurityUtils.getLoginUser().getUserId()查询sys_role_menu_scope拿到当前用户在该菜单下的dept_ids把dept_ids塞进ThreadLocalListLongMyBatis-Plus 拦截器读取ThreadLocal自动拼AND dept_id IN (...)后置清理ThreadLocal防止内存泄漏使用示例RequiresPermissionsExt(value{student:score:view}, dataScopeDataScope.DEPT) GetMapping(/score) public TableDataInfo list(ScoreDTO dto){ return scoreService.selectPage(dto); }至此同一“班主任”角色登录只能看到本班成绩换成“教学秘书”角色即可看到全院数据代码零侵入。4. 核心改造 2JWT 刷新 并发登录控制刷新拦截器关键注释已写public class JwtRefreshInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token JwtUtils.getToken(request); Claims claims JwtUtils.getClaims(token); // 1. 剩余时间 10 min 则刷新 if (claims.getExpiration().getTime() - System.currentTimeMillis() 10 * 60 * 1000) { String userKey claims.get(userKey).toString(); LoginUser loginUser SpringUtils.getBean(TokenService.class) .getLoginUser(userKey); // 2. 颁发新令牌旧令牌加入 Redis 黑名单 5 min String newToken JwtUtils.createToken(loginUser); response.setHeader(Authorization, newToken); RedisUtils.setCacheObject(Constants.JWT_BLACK token, 1, 5 * 60); } return true; } }并发登录踢下线登录成功后RedisUtils.setCacheObject(user:kick: userId, token, 过期时间)每次请求比较Redis中token是否一致不一致返回 401支持开关配置single.logintrue/false5. 前端路由守卫让按钮级权限也“动”起来// permission.js router.beforeEach(async (to, from, next) { // 1. 白名单 if (whiteList.indexOf(to.path) ! -1) { next(); return } // 2. 取用户信息 const userStore useUserStore() if (!userStore.token) { next(/login?redirect${to.fullPath}); return } // 3. 动态路由未加载则拉菜单 if (!userStore.hasRoutes) { const accessRoutes await userStore.generateRoutes() accessRoutes.forEach(r router.addRoute(r)) next({ ...to, replace: true }) } else { next() } })按钮级权限指令app.directive(permission, { mounted(el, binding) { const { value } binding const permissions useUserStore().permissions if (value !permissions.includes(value)) { el.parentNode el.parentNode.removeChild(el) } } })模板用法el-button v-permissionstudent:score:export导出成绩/el-button6. 安全加固XSS SQL 注入双重保险XSS 全局过滤器继承HttpServletRequestWrapper重写getParameter、getInputStream用Jsoup.clean过滤白名单标签。SQL 注入MyBatis-Plus 自带#{}占位符已 99% 免疫但代码里还有同学写order by ${sort}排序务必把sort字段拉白名单校验if (!ArrayUtils.contains(whitelist, sort)) throw new BadRequestException(非法排序字段);操作日志审计利用Log注解 AOP把ip、url、method、params、userId、time写表答辩时老师最爱问“你怎么追踪误删数据”直接甩日志表。7. 生产环境避坑指南数据库命名规范统一小写下划线主键bigint(20)自增所有表必须create_time datetime DEFAULT CURRENT_TIMESTAMP索引命名idx_表名_字段名唯一索引uk_表名_字段名方便 DBA 快速定位Swagger 文档暴露生产环境务必加网关拦截spring: profiles: active: prod knife4j: production: true # 关闭接口页面或者 Nginx 层直接return 404 /swagger-ui.html冷启动提速关闭spring.devtools.restart把BeanValidation换成hibernate.validator的precompile版本使用spring-context-indexer生成spring.components本地启动从 12 s 降到 7 s服务器 2 vCPU 4 G 首次启动 25 s → 15 s日志切割使用logback-spring.xml按 100 MB 切割保留 30 天防止磁盘爆满把服务拖死。8. 部署脚本一条命令上云#!/bin/bash # build.sh mvn clean package -Dmaven.test.skiptrue docker build -t ruoyi-project:1.0.0 . docker run -d --name ruoyi-prod \ -e SPRING_PROFILES_ACTIVEprod \ -e MYSQL_URLjdbc:mysql://10.0.0.8:3306/ruoyi_prod \ -p 8080:8080 ruoyi-project:1.0.0前端独立容器FROM nginx:alpine COPY dist/ /usr/share/nginx/html/ COPY nginx.conf /etc/nginx/conf.d/default.conf把vue.config.js的publicPath改成./再用 GitHub Actions 自动打包推镜像答辩演示时直接打开公网域名老师点赞“像企业级”。9. 结语把 Demo 变产品的下一步走完上面的改造你的“若依毕业设计”已经脱离“课程级别”具备可维护、可扩展、可交付的雏形。但别急着关机睡觉最后留两个小作业把 README 写成产品白皮书背景、功能、架构图、部署手册、接口示例一个都不能少——导师一看就知道“这学生能毕业”。做一次“假压力测试”用wrk -t12 -c400 -d30s打 1 w 并发把 QPS、RT、错误率截屏贴报告里老师想挑刺都找不到角度。毕业设计不是终点而是你把“演示系统”转化为“可交付产品”的第一块跳板。动手重构你的若依项目下次面试官问“有没有上线经验”你可以把域名甩给他顺便讲讲 JWT 刷新、并发踢人、数据权限三级解耦——offer 稳了。