十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Layui+Shiro+Ehcache学生管理系统全解析

SpringBoot+Layui+Shiro+Ehcache学生管理系统全解析 简介一份基于SpringBootLayui的学生管理系统源码融入Shiro安全框架与Ehcache缓存框架适合Java全栈学习者、毕业设计开发者以及需要快速搭建管理后台的初学者。项目采用前后端分离思路覆盖用户登录、权限控制、缓存处理等业务帮助读者理解企业级开发中的整合方式。压缩包共310个文件约30.39MB主要包含Java后端代码、HTML/CSS/JavaScript前端页面、SQL数据库脚本、XML与Properties配置文件以及Maven构建文件同时带有多张GIF演示图和页面截图便于直观查看运行效果。前端以Layui为基础包含后台布局、弹窗交互与表单样式后端分层结构清晰便于定位Controller、Service、Mapper等代码。源码已通过本地编译测试下载后按文档配置环境即可启动。项目难度适中内容经过助教老师审定适合作为课程设计或毕业设计的参考。目前已有94人学习下载目录结构完整遇到环境或运行问题可直接向作者咨询学习使用更省心。1. 从毕业设计到生产可用这套 SpringBootLayui 学生管理系统到底该怎么看如果你搜到这个标题大概率是在做课程设计、毕业设计或者接手了一个“看起来很老但一直在跑”的校内项目。SpringBoot Layui Shiro Ehcache 这套组合放在 2025 年看确实不算新但它在学生管理系统这个场景里依然是相当务实的选择SpringBoot 负责把后端装配成本地可运行的 Web 服务Layui 用一套自带组件的前端框架把页面撑起来Shiro 管登录和权限Ehcache 扛住高频读取的缓存需求。这个结构的好处是不依赖前端 Node 环境不依赖 Redis 服务JDK Maven 一个 IDE 就能把整个系统跑起来这对学生机和实验室机器非常友好。但“能跑”和“能讲清楚”是两回事。面试或答辩时被问到“为什么用 Shiro 不用 Spring Security”“为什么用 Ehcache 不用 Redis”答不上来会非常减分。所以这篇文章不打算逐行解读某个具体源码包而是按照这套技术栈最常见的落地方式把“理论—配置—实现—排错—优化”整条链路讲透让你拿到任何类似项目都能快速上手也能在别人问起时给出有深度的回答。2. 技术选型拆解为什么偏偏是 SpringBoot、Layui、Shiro、Ehcache 这四件套2.1 SpringBoot 在这个系统里承担什么角色学生管理系统的核心需求是“对若干张表做增删改查顺便管一下登录用户能看哪些页面”。SpringBoot 的价值不在于它是新东西而在于它把传统 SSM 项目里最繁琐的装配步骤收敛掉了。没有一堆 XML 配置文件没有手动注册 Servletspring-boot-starter-web依赖一拉内嵌 Tomcat 一启动后端服务就起来了。常见的项目结构是经典的 Controller—Service—Mapper 三层配合 MyBatis 或 MyBatis-Plus 操作数据库。如果你拿到的源码包里用的是 MyBatis那要关注Mapper注解扫描和 XML 文件路径是否能对上如果是 MyBatis-Plus那大部分单表操作可以靠BaseMapper提供的现成方法完成代码量会少很多。SpringBootApplication MapperScan(com.example.student.mapper) public class StudentManageApplication { public static void main(String[] args) { SpringApplication.run(StudentManageApplication.class, args); } }这段代码里MapperScan指定了 Mapper 接口所在的包路径SpringBoot 启动时会把这些接口动态代理成可执行的 SQL 操作对象。没有这行注解程序会启动失败并报“无法找到 StudentMapper 的 Bean”。SpringApplication.run是整个应用的入口它会自动执行内嵌 Tomcat 的启动、Spring 容器的初始化、配置文件的加载。如果你遇到的是“SpringBoot 版本太高”导致的问题优先检查项目的pom.xml里 spring-boot-starter-parent 的版本是不是与你本机 JDK 兼容。JDK 8 配 SpringBoot 2.7.x 是当前最稳妥的组合JDK 17 及以上才建议考虑 SpringBoot 3.x。2.2 Layui 为什么还在学生管理系统里高频出现Layui 是一套“由后端思维驱动”的前端 UI 框架它的核心特点是不需要你懂 npm 和 webpack直接把layui.css和layui.js引入页面用layui.use加载对应模块就能渲染表格、表单、弹窗、日期选择器。在学生管理系统里Layui 最常见的用法是配合table模块做列表页的数据渲染。后端返回 JSON 数据前端通过table.render把数据绑定到表格上并顺便实现分页、搜索、行内操作按钮。table.render({ elem: #studentTable, url: /student/list, page: true, cols: [[ { field: id, title: 学号, width: 100 }, { field: name, title: 姓名, width: 120 }, { field: className, title: 班级, width: 150 }, { field: phone, title: 联系电话, minWidth: 150 }, { title: 操作, toolbar: #barDemo, width: 200 } ]] });这段代码的elem指向页面上的表格容器url是后端接口地址page: true开启服务端分页模式cols定义每一列的字段名和表头文字toolbar则指定了行内操作按钮的模板 ID。使用这个方式时后端只需要返回{ code: 0, count: 100, data: [...] }这种固定格式的 JSONLayui 会自动完成数据解析和分页状态展示。需要注意 Layui 的日期控件有个常见需求是“最大日期不超过当前日期”做法是在laydate.render中设置max参数为当前日期laydate.render({ elem: #birthday, max: getNowDate() // 自定义函数返回 yyyy-MM-dd 格式的当天日期 });如果你拿到的是基于 Layui 2.8 以上版本的项目页面里还会出现layui.config和layui.use的模块化加载写法和旧版 2.5 的全局加载方式稍有区别但核心 API 基本没变。2.3 Shiro 的权限控制模型Subject、SecurityManager、Realm 三件套Shiro 和 Spring Security 是 Java 生态里最常用来做登录认证和权限控制的两个框架。在学生管理系统这个规模下Shiro 的优势是“轻、简单、概念少”。它把当前用户抽象为Subject把认证和授权的核心逻辑收敛到SecurityManager而具体怎么从数据库查询用户、怎么校验密码则通过一个自定义的Realm来实现。一个完整的登录认证流程是这样的前端提交用户名和密码到/login接口Controller 把参数封装为UsernamePasswordToken然后调用Subject.login(token)。Shiro 内部会根据配置找到 Realm调用doGetAuthenticationInfo方法在这个方法里根据用户名到数据库查询用户记录再比对密码是否一致。public class UserRealm extends AuthorizingRealm { Autowired private UserService userService; Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 给当前登录用户分配角色和权限 SimpleAuthorizationInfo info new SimpleAuthorizationInfo(); User user (User) principals.getPrimaryPrincipal(); info.addRole(user.getRoleName()); info.addStringPermission(student:view); return info; } Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username (String) token.getPrincipal(); User user userService.findByUsername(username); if (user null) { return null; // 抛出 UnknownAccountException } return new SimpleAuthenticationInfo(user, user.getPassword(), getName()); } }doGetAuthenticationInfo负责认证返回空表示用户不存在返回 SimpleAuthenticationInfo 后Shiro 会用 token 里的密码和这个返回值里的密码做比对不一致就抛IncorrectCredentialsException。doGetAuthorizationInfo负责授权在访问需要权限的接口或页面时Shiro 会调用这个方法获取角色和权限再与注解或配置里要求的值做对比。实际项目中还会涉及密码加密的问题最常见的是 MD5 加盐方式。如果你负责的源码包里密码是明文存储答辩或面试时有很大概率会被问到“你怎么保证密码安全”建议至少改成 MD5 加盐或 BCrypt 中的一种。2.4 Ehcache 用在哪一层为什么非要它Ehcache 是一个纯 Java 实现的本地缓存框架进程内缓存不需要独立部署服务。在学生管理系统里最常见的使用场景是缓存“当前登录用户的权限信息”和“字典数据、班级列表这类几乎不变的基础数据”。Shiro 的AuthorizingRealm默认会在每次权限校验时调用 Realm 查询数据库获取角色和权限这个操作在高频访问下很浪费。Shiro 自身提供了 CacheManager 接口集成 Ehcache 后权限信息会被缓存起来同一个用户在一段时间内不会重复查库。典型的 Ehcache 配置文件ehcache.xml长这样cache nameshiroCache maxElementsInMemory10000 eternalfalse timeToIdleSeconds1800 timeToLiveSeconds3600 overflowToDiskfalse memoryStoreEvictionPolicyLRU/参数含义分别是maxElementsInMemory是缓存中最多存放的对象数量超过这个数量触发淘汰策略eternal为 false 表示缓存不是永久的timeToIdleSeconds是对象在闲置多久后被清出缓存timeToLiveSeconds是最长存活时间overflowToDisk设为 false 表示不落盘避免本地磁盘文件管理问题memoryStoreEvictionPolicy是淘汰策略LRU 表示最近最少使用优先淘汰。在 SpringBoot 里集成 Shiro 和 Ehcache需要在配置类中创建EhCacheManagerBean public EhCacheManager ehCacheManager() { EhCacheManager cacheManager new EhCacheManager(); cacheManager.setCacheManagerConfigFile(classpath:ehcache.xml); return cacheManager; }之后把这个EhCacheManager设置给 Shiro 的 SecurityManager权限缓存就能生效了。如果你要做内存缓存的话Ehcache 的启动速度比 Redis 快维护成本也低了非常多个量级。3. 从零搭建并跑通学生管理系统的具体流程3.1 在 IDEA 里创建 SpringBoot 工程的两种方式拿到一个项目的源码包和自己从头建一个工程这两件事你至少得会其中一件。个人建议在 IDEA 里手动创建工程因为这样你对工程的每个组成部分都有感知不至于拿到别人代码后连目录结构都看不懂。第一种方式是用 IDEA 的 Spring InitializrFile → New → Project → Spring Initializr选择语言 Java、构建工具 Maven、SpringBoot 版本然后勾选 Web、MyBatis、MySQL Driver 等依赖。这种方式的好处是骨架自动生成缺点是受网络环境影响较大如果初始化超时通常是连不上 Spring 的元数据服务可以选择用阿里云的 Initializr 地址替代。第二种方式是不借助初始化工具直接新建一个 Maven 工程手动在pom.xml里声明依赖。这种方式适合需要锁定版本的情况比如你想明确用 SpringBoot 2.7.13 而不是默认推荐的高版本。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.13/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependenciesspring-boot-starter-parent最核心的作用是统一管理各依赖的版本号。你在子依赖里可以不写 versionMaven 会根据 parent 里定义的版本自动选择避免版本冲突。spring-boot-starter-web包含了内嵌 Tomcat、Spring MVC、Jackson 等 Web 开发必需的组件。3.2 application.yml 里的关键配置数据库连接、页面映射、缓存开关SpringBoot 的配置文件有两种格式application.properties 和 application.yml。YAML 格式缩进敏感但结构更清晰现在绝大多数项目都用 YAML。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/student_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver thymeleaf: prefix: classpath:/templates/ suffix: .html cache: false mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.student.entityserver.port控制应用启动后监听的端口如果你本机 8080 被占用改成 8081 或 9090 都行。spring.datasource里的url是 JDBC 连接串注意serverTimezoneAsia/Shanghai参数不配置这个参数在 MySQL 8.x 连接时会报时区错误。driver-class-name在 MySQL 8.x 下必须使用com.mysql.cj.jdbc.Driver旧版的com.mysql.jdbc.Driver已经不建议使用。MyBatis 的mapper-locations是 XML 映射文件的位置如果你的 Mapper 接口用了注解写 SQL那么这个配置不是必须的。但如果你在源码包里看到mapper目录下有StudentMapper.xml那就一定要确认这个路径能和pom.xml里 resource 的包含规则对得上resources resource directorysrc/main/resources/directory /resource /resources这个配置是防止 Maven 在构建时把src/main/java下的 XML 文件排除掉导致运行时报“Invalid bound statement (not found)”错误。3.3 把 SQL 文件导入 MySQL 并修正编码问题学生管理系统的源码包里通常会附带一个.sql文件存放建库建表和基础数据的语句。导入步骤很直接在 Navicat 或命令行中创建一个同名数据库然后执行 source 命令。mysql -u root -p create database student_system default character set utf8mb4; use student_system; source /path/to/student_system.sql;用utf8mb4而不是utf8是因为 MySQL 的 utf8 最大只支持 3 字节而 emoji 表情占 4 字节如果你在系统里保存了包含特殊符号的数据utf8mb4 才能完整兼容。如果导入后页面中文乱码检查三个地方数据库连接的characterEncodingutf8、页面 meta 标签的 charset、以及 Layui 表格接口返回的 Content-Type 是否包含charsetUTF-8。3.4 启动项目后必须验证的三个接口项目跑起来后不要急着点页面。先把最核心的三个接口用浏览器或 Postman 验证一遍能省掉后面大部分排查时间。第一个是登录接口POST 请求/login携带username和password两个参数。第二个是学生列表接口GET 请求/student/list?page1limit10这个接口应该返回符合 Layui 表格规范的 JSON 结构{ code: 0, msg: , count: 12, data: [ { id: 1, name: 张三, className: 计算机2101 } ] }第三个是退出登录接口GET 请求/logout成功后会跳转到登录页。如果登录接口返回 401 或 302先检查 Shiro 的拦截配置如果列表接口返回 500去控制台看异常日志多数情况是 SQL 语句字段名和实体类属性没对上或 Mapper XML 的 namespace 写错。4. Shiro 和 Ehcache 的整合细节与五个高频排错点4.1 ShiroConfig 里的过滤链配置与常用过滤规则Shiro 在 SpringBoot 中的整合方式是通过一个 Java 配置类完成这个类需要声明SecurityManager、ShiroFilterFactoryBean、LifecycleBeanPostProcessor等 Bean。其中过滤链是拦截规则的核心需要用 MAP 集合按顺序定义 URL 对应的过滤器Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); MapString, String filterChainDefinitionMap new LinkedHashMap(); filterChainDefinitionMap.put(/login, anon); filterChainDefinitionMap.put(/css/**, anon); filterChainDefinitionMap.put(/js/**, anon); filterChainDefinitionMap.put(/images/**, anon); filterChainDefinitionMap.put(/logout, logout); filterChainDefinitionMap.put(/**, authc); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); factoryBean.setLoginUrl(/login); factoryBean.setUnauthorizedUrl(/403); return factoryBean; }这段配置里的anon表示匿名可访问authc表示必须登录才能访问logout是 Shiro 自带的退出过滤器会在退出后跳转到登录页。这里有一个很容易踩的坑LinkedHashMap是有序的过滤链匹配遵循“先匹配先生效”原则所以静态资源和登录页一定要写在/**的前面否则会被authc拦截导致登录页都进不去。setLoginUrl(/login)的作用是当未登录用户访问受保护资源时Shiro 会把请求重定向到这个地址。setUnauthorizedUrl(/403)则是用户已登录但没有权限访问时的跳转页面。4.2 登录逻辑的完整写法以及密码校验失败的三种异常登录接口是整套系统的入口逻辑通常写在一个 Controller 或一个自定义 LoginService 里。完整写法如下PostMapping(/login) ResponseBody public Result login(String username, String password, boolean rememberMe) { UsernamePasswordToken token new UsernamePasswordToken(username, password, rememberMe); Subject currentUser SecurityUtils.getSubject(); try { currentUser.login(token); return Result.ok(); } catch (UnknownAccountException e) { return Result.error(用户名不存在); } catch (IncorrectCredentialsException e) { return Result.error(密码错误); } catch (LockedAccountException e) { return Result.error(账号已被锁定); } catch (AuthenticationException e) { return Result.error(认证失败请检查账号状态); } }UsernamePasswordToken的第三个参数rememberMe表示是否开启记住我功能开启后 Shiro 会把用户标识写入 Cookie在浏览器关闭后重新打开时仍然处于登录状态。但要注意记住我功能的登录状态不等于一个完整会话涉及敏感操作的接口建议仍然要求重新输入密码。4.3 权限缓存命中失败的场景改了角色却不生效这种场景在项目联调时经常出现管理员在后台给某个用户新增了角色但该用户重新登录后访问页面还是提示无权限。原因通常是权限缓存没有被正确清空。最常见的两种缓存失效方式是改配置文件名和重启服务。但实际排查中会发现真正的问题是缓存没有被主动清除——用户退出登录时Shiro 默认只清除 Subject 的身份信息不一定会清除 AuthorizationInfo 缓存。如果权限信息已经进入了 Ehcache除非缓存自然过期否则下次登录还会读取旧数据。处理办法是在 Realm 里提供清除缓存的方法public void clearCache(String username) { Subject currentUser SecurityUtils.getSubject(); if (currentUser ! null) { currentUser.getSession().removeAttribute(userInfo); } PrincipalCollection principals new SimplePrincipalCollection(username, userRealm); super.clearCache(principals); }之后在修改角色的业务方法里调用userRealm.clearCache(username)就能保证下次访问接口时重新查询权限。4.4 报表查询慢但数据量不大时先检查一级缓存和二级缓存如果你在学生管理系统的“成绩统计”或“课程报表”页面发现一个 SQL 查询需要好几秒学员环境数据量又不大不要急着把锅甩给 MySQL。先打开 MyBatis 的 SQL 日志看看实际执行了几次查询再对比 Ehcache 是否真的拦截了查询。MyBatis 的本地缓存默认开启一级缓存是 SqlSession 级别的同一个 SqlSession 内执行相同 SQL 会直接返回缓存结果。但在 Spring 管理的事务中每次执行 Mapper 方法可能会创建新的 SqlSession一级缓存形同虚设。二级缓存是 Mapper 级别的需要显式开启mapper namespacecom.example.student.mapper.StudentMapper cache evictionLRU flushInterval60000 size512 readOnlytrue/ select idselectStudents resultTypeStudent useCachetrue SELECT * FROM student /select /mappereviction指定缓存淘汰策略flushInterval是缓存刷新间隔毫秒值size是最大缓存对象数量readOnly为 true 时性能更好但对象不允许修改。配置完成后如果两次查询之间没有执行增删改操作第二次相同 SQL 会直接命中缓存。但你需要特别记住readOnlytrue在实体类被修改时会带来数据不一致的风险如果在缓存开着的状态下执行了 updateMyBatis 会自动清空该 Mapper 的缓存所以大多数场景下没问题但如果通过 JDBC 或存储过程直接改了数据库缓存是不会感知到的。4.5 前端报 404 且控制台无异常时的排查顺序这是一种特别迷惑人的情况浏览器访问前端页面时返回 404但后端控制台完全没有任何异常输出。遇到这种情况优先级最高的排查动作是确认页面的实际位置和 SpringBoot 的资源映射规则是否一致。SpringBoot 的默认静态资源目录是classpath:/static/、classpath:/public/等位置。如果你的项目用的是 JSP 页面那需要额外引入 JSP 支持的依赖SpringBoot 默认不支持 JSP如果是 Thymeleaf 模板页面必须放在src/main/resources/templates/目录下且接口模板渲染时返回的是模板文件名而非完整页面路径。如果页面是用 Layui 写的纯静态页面配合 Ajax 交互那么访问根路径/时需要一个 Controller 做页面跳转或者通过WebMvcConfigurer配置 ViewController。如果在源码包里看到Controller中返回字符串“index”却找不到对应的 index.html八成是页面被放在WEB-INF目录下但项目打包方式不是 war 包。4.6 Session 丢失和浏览器兼容问题Shiro 默认使用 Servlet 容器的 Session在 SpringBoot 内嵌 Tomcat 下通常是正常的。但如果你开启了 rememberMe而前端页面在 AJAX 请求时没有携带 Cookie就会导致每次请求都创建新会话。Layui 的 Ajax 请求默认是同步携带 Cookie 的但如果你手动设置了contentType或使用原生fetch就有可能丢失凭证。排查方法是打开浏览器开发者工具的 Network 面板查看请求头里有没有Cookie字段以及响应头里有没有Set-Cookie。还有一个容易忽略的是前端页面的layui.use回调中请求接口如果请求是在页面加载完成前发出的此时 Shiro 的 Session 可能还没有绑定到当前请求线程会出现偶发性的登录失效。Layui 的表格table.render会自动发送 Ajax其实有内置的request回调可以统一处理 401 状态码的跳转逻辑。5. 把项目做得更像生产环境的几个进阶改造点5.1 用 YAML 密文替代数据库明文密码源码包里application.yml明文写着数据库密码这在自己电脑上无所谓但只要项目上传到 Git 或被别人接触到源码很容易被扫出来。SpringBoot 支持对配置文件中的敏感字段进行加密常用的方式是结合jasypt-spring-boot-starter组件。jasypt: encryptor: password: yourSalt spring: datasource: password: ENC(加密后的密文)加密操作通过 Maven 插件或命令行工具执行mvn com.github.ulisesbocchio:jasypt-maven-plugin:encrypt -Djasypt.encryptor.passwordyourSalt -Djasypt.encryptor.algorithmPBEWithMD5AndDES这个做法的核心理念是配置文件里只保存密文真实解密密钥通过环境变量或启动参数注入java -jar student-system.jar --jasypt.encryptor.passwordyourSalt要注意加密盐值本身不能写在配置文件里否则等于白加密。实际团队中通常会把盐值放到部署机的环境变量中确保代码仓库泄露时数据库不会直接暴露。5.2 用 Hutool 或自写工具类做 Excel 导入导出学生管理系统的数据量通常不大但会有“批量导入学生信息”的需求。手写 POI 代码处理 Excel 会让代码变得很长Hutool 工具库对 Excel 操作做了很好的封装几行代码就能完成读取ExcelReader reader ExcelUtil.getReader(D:/students.xlsx); ListStudent students reader.readAll(Student.class); studentService.batchInsert(students);readAll会根据实体类字段名匹配 Excel 列名自动完成类型转换。导出同理ExcelWriter writer ExcelUtil.getWriter(D:/students_export.xlsx); writer.write(studentService.list(), true);注意如果你拿到的实体类字段名和 Excel 列名对不上可以用reader.addHeaderAlias(学号, id)做字段映射。5.3 对接 Layui 的 select 动态赋值与日期组件限制Layui 的select联动在“按院系列班级再按班级触发生成学生列表”这种场景很常见。如果你要做院系→班级联动核心是form.on(select(college), function(data){ $.get(/class/list?collegeId data.value, function(res){ var html option value请选择班级/option; res.data.forEach(function(item){ html option value item.id item.name /option; }); $(#classId).html(html); form.render(select); }); });这段关键的操作很多人会忘掉最后一行form.render(select)不加这一行 Layui 渲染出来的还是旧的下拉选项列表。这是 Layui 初学者最常踩的坑DOM 更新了但组件没有重新渲染。5.4 使用定时任务清理过期 Session 和日志文件系统跑一段时间后日志文件可能占满磁盘。SpringBoot 自带的Scheduled就能解决简单的定时清理任务Component public class CleanTask { Scheduled(cron 0 0 3 * * ?) public void cleanLogFiles() { File logsDir new File(./logs); File[] files logsDir.listFiles(f - f.getName().endsWith(.log)); if (files ! null) { for (File f : files) { if (System.currentTimeMillis() - f.lastModified() 7 * 24 * 60 * 60 * 1000L) { f.delete(); } } } } }Scheduled的cron表达式格式是六位或七位0 0 3 * * ?表示每天凌晨 3 点执行。要让定时任务生效需要在启动类或配置类上加EnableScheduling。这段代码里判断条件使用了f.lastModified()的文件最后修改时间超过 7 天前修改的日志就被清除。你会发现这种代码在生产里并没有多复杂但对系统的稳定性提升很明显。5.5 答辩或面试中需要准备的三个扩展问题如果你的目标是毕业设计答辩或 Java 方向的技术面建议把下面三个问题提前准备好。第一个是“Shiro 和 Spring Security 怎么选”。回答思路是强调学生管理系统用户角色只有两三种、权限粒度为页面级Shiro 配置灵活、上手成本低而 Spring Security 更适合 OAuth2.0 和分布式场景两者的核心流程本质上都是“过滤器链 认证管理器 用户查询”。第二个是“Ehcache 和 Redis 的区别”。回答思路是Ehcache 是进程内缓存访问速度极快但无法跨节点共享适合单机部署的中小型系统Redis 是独立服务支持分布式环境下多实例共享同一份缓存数据但需要额外的运维成本和网络开销。当前系统跑在单台实验室服务器上Ehcache 够用。第三个是“如果用户量涨到一万系统哪里会先成为瓶颈”。你可以先指出最薄弱的是同步 Tomcat 连接数限制和数据库连接数然后给出优化方向把缓存换成 Redis、把权限判断改成基于注解、引入读写分离、用 Nginx 做静态资源代理。这三个问题的回答逻辑本质上就是把这篇文章里的技能点串联成一条工程师的分析链路让听的人知道你不仅会调参还知道参数背后的取舍。本文还有配套的精品资源点击获取
返回列表