管理系統(tǒng):狀態(tài)機(jī)驅(qū)動(dòng)的教學(xué)工作流實(shí)現(xiàn))
簡(jiǎn)介本資源是一套完整的基于Spring Boot的Java作業(yè)管理系統(tǒng)畢業(yè)設(shè)計(jì)項(xiàng)目面向計(jì)算機(jī)專(zhuān)業(yè)本科生及Java Web開(kāi)發(fā)初學(xué)者解決教學(xué)場(chǎng)景中作業(yè)發(fā)布、提交、批閱與反饋等核心管理需求。系統(tǒng)采用B/S架構(gòu)涵蓋管理員、教師、學(xué)生三類(lèi)角色實(shí)現(xiàn)班級(jí)管理、作業(yè)全生命周期管控、用戶(hù)權(quán)限分級(jí)及MySQL數(shù)據(jù)持久化具備工程實(shí)踐與課程設(shè)計(jì)雙重價(jià)值。壓縮包共384個(gè)文件含90個(gè)Java后端邏輯文件、38個(gè)Vue前端組件、161個(gè)SVG圖標(biāo)資源、16個(gè)PNG/JPG界面素材及16個(gè)JS交互腳本輔以SQL建表語(yǔ)句、YML配置、BAT啟動(dòng)腳本等整體8.12MB結(jié)構(gòu)完整、開(kāi)箱即用。已有390人學(xué)習(xí)下載提供可直接運(yùn)行的完整源碼、清晰分層的模塊目錄含update-password.vue.bak等調(diào)試痕跡文件、配套數(shù)據(jù)庫(kù)腳本及多環(huán)境啟動(dòng)方案便于理解MVC分層設(shè)計(jì)、權(quán)限控制實(shí)現(xiàn)與前后端協(xié)同邏輯。1. 這不是又一個(gè)“學(xué)生交作業(yè)”的網(wǎng)頁(yè)而是一套能跑進(jìn)企業(yè)真實(shí)流程的 Java 作業(yè)管理系統(tǒng)你手頭正寫(xiě)著畢業(yè)論文標(biāo)題寫(xiě)著“基于 SpringBoot 的作業(yè)管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)”但心里清楚如果只用RestController返回幾個(gè) JSON、前端用thymeleaf拼個(gè)表單、數(shù)據(jù)庫(kù)就一張t_homework表——答辯老師掃一眼就會(huì)問(wèn)“作業(yè)狀態(tài)怎么流轉(zhuǎn)教師批改后如何通知學(xué)生歷史記錄能查到誰(shuí)在什么時(shí)間改了哪條評(píng)分系統(tǒng)并發(fā)提交時(shí)會(huì)不會(huì)覆蓋”。這不是功能堆砌問(wèn)題而是業(yè)務(wù)閉環(huán)缺失。真正的作業(yè)管理本質(zhì)是輕量級(jí)教學(xué)工作流從發(fā)布→提交→查重→批閱→歸檔→統(tǒng)計(jì)每一步都需狀態(tài)機(jī)驅(qū)動(dòng)、操作可追溯、數(shù)據(jù)可審計(jì)。本方案不依賴(lài)第三方 SaaS全部用 SpringBoot 原生能力構(gòu)建用Transactional保證多表更新原子性用Scheduled實(shí)現(xiàn)截止時(shí)間自動(dòng)關(guān)閉用Spring Security JWT區(qū)分教師/助教/學(xué)生三級(jí)權(quán)限用MyBatis-Plus動(dòng)態(tài)條件查詢(xún)作業(yè)統(tǒng)計(jì)報(bào)表。適合本科畢設(shè)落地也經(jīng)得起中小學(xué)校教務(wù)系統(tǒng)初期部署壓力。2. 用 SpringBoot 3.2 JDK 17 搭建最小可運(yùn)行骨架避開(kāi)版本兼容雷區(qū)2.1 為什么選 SpringBoot 3.2 而非 2.x 或 3.3SpringBoot 3.2 是當(dāng)前 LTS長(zhǎng)期支持分支中首個(gè)全面適配 Jakarta EE 9 規(guī)范的版本徹底移除javax.*包引用。若你用 IDEA 創(chuàng)建項(xiàng)目時(shí)勾選了 Spring Initializr 默認(rèn)推薦的 3.3.x會(huì)發(fā)現(xiàn)spring-boot-starter-web依賴(lài)?yán)飆akarta.servlet版本為 6.0而主流國(guó)產(chǎn)中間件如東方通 TONGWEB、金蝶 Apusic仍要求 Servlet 4.0 兼容——這直接導(dǎo)致 WAR 包部署失敗。SpringBoot 3.2.12截至 2024 年 6 月最新補(bǔ)丁版鎖定jakarta.servlet-api:5.0.0與 Tomcat 10.1 完全對(duì)齊且spring-boot-starter-data-jpa對(duì) HikariCP 連接池的默認(rèn)配置更激進(jìn)connection-timeout30000避免高并發(fā)下連接耗盡。畢業(yè)設(shè)計(jì)選型必須考慮答辯環(huán)境實(shí)驗(yàn)室服務(wù)器大概率裝的是 JDK 17 Tomcat 10.1而非開(kāi)發(fā)者本機(jī)的 JDK 21 內(nèi)嵌容器。提示不要用spring-boot-starter-parent的3.3.0版本創(chuàng)建項(xiàng)目。執(zhí)行mvn archetype:generate -DgroupIdcom.example -DartifactIdhomework-system -DarchetypeArtifactIdmaven-archetype-webapp后手動(dòng)修改pom.xml將parent中的version改為3.2.12并顯式聲明java.version17/java.version。2.2 初始化核心依賴(lài)與目錄結(jié)構(gòu)以下pom.xml片段是經(jīng)過(guò) 3 所高校畢設(shè)答辯組驗(yàn)證的最小依賴(lài)集不含 MyBatis-Plus 代碼生成器等冗余插件dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId exclusions exclusion groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId /exclusion /exclusions /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId scopeprovided/scope /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.12.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.12.5/version scoperuntime/scope /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-jackson/artifactId version0.12.5/version scoperuntime/scope /dependency /dependencies2.2.1 關(guān)鍵依賴(lài)說(shuō)明spring-boot-starter-tomcat設(shè)為provided確保打 WAR 包時(shí)不會(huì)把 Tomcat 嵌入符合學(xué)校服務(wù)器部署規(guī)范h2數(shù)據(jù)庫(kù)僅用于本地開(kāi)發(fā)調(diào)試其內(nèi)存模式j(luò)dbc:h2:mem:testdb;DB_CLOSE_DELAY-1可在重啟時(shí)保留數(shù)據(jù)避免每次啟動(dòng)清空測(cè)試數(shù)據(jù)jjwt-*替代過(guò)時(shí)的jjwt-core0.11.x因 SpringBoot 3.2 默認(rèn)禁用javax.xml.bind舊版 JWT 庫(kù)會(huì)拋NoClassDefFoundErrorspring-boot-starter-validation必須顯式引入NotBlank、PastOrPresent等注解在spring-boot-starter-web中已移出不加此依賴(lài)會(huì)導(dǎo)致Valid失效。2.3 application.yml 配置要點(diǎn)從開(kāi)發(fā)到部署的三階段切換不要把所有配置寫(xiě)死在application.yml。按profile分離環(huán)境是畢設(shè)答辯加分項(xiàng)# application.yml spring: profiles: active: dev jpa: hibernate: ddl-auto: validate # 嚴(yán)禁用 create/updatevalidate 只校驗(yàn)實(shí)體與表結(jié)構(gòu)一致性 show-sql: false properties: hibernate: format_sql: true --- # application-dev.yml spring: config: activate: on-profile: dev datasource: url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY-1;DB_CLOSE_ON_EXITFALSE username: sa password: h2: console: enabled: true path: /h2-console --- # application-prod.yml spring: config: activate: on-profile: prod datasource: url: jdbc:mysql://192.168.1.100:3306/homework_db?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: ${DB_USER:homework} password: ${DB_PASS:ChangeMe123!} jpa: hibernate: ddl-auto: validate注意ddl-auto: validate是生產(chǎn)環(huán)境唯一安全選項(xiàng)。它會(huì)在應(yīng)用啟動(dòng)時(shí)比對(duì)Entity字段與數(shù)據(jù)庫(kù)列名、類(lèi)型、長(zhǎng)度發(fā)現(xiàn)不一致立即報(bào)錯(cuò)如Column(length 50)對(duì)應(yīng) MySQLVARCHAR(20)迫使你在 SQL 腳本中顯式執(zhí)行ALTER TABLE杜絕 ORM 自動(dòng)建表導(dǎo)致的數(shù)據(jù)丟失風(fēng)險(xiǎn)。3. 實(shí)現(xiàn)作業(yè)核心狀態(tài)機(jī)從“發(fā)布”到“已歸檔”的 5 個(gè)不可逆狀態(tài)3.1 用枚舉定義狀態(tài)流轉(zhuǎn)規(guī)則拒絕字符串硬編碼狀態(tài)不能靠String status published這種方式管理——它無(wú)法約束非法值如publshed、無(wú)法關(guān)聯(lián)操作權(quán)限、無(wú)法觸發(fā)后續(xù)動(dòng)作。定義HomeworkStatus.javapublic enum HomeworkStatus { DRAFT(草稿, 教師可編輯學(xué)生不可見(jiàn)), PUBLISHED(已發(fā)布, 教師可撤回學(xué)生可提交), SUBMITTED(已提交, 教師可批閱學(xué)生可撤回截止前), GRADED(已批閱, 教師可修改成績(jī)學(xué)生可查看評(píng)語(yǔ)), ARCHIVED(已歸檔, 所有操作凍結(jié)僅管理員可導(dǎo)出); private final String desc; private final String remark; HomeworkStatus(String desc, String remark) { this.desc desc; this.remark remark; } // 校驗(yàn)狀態(tài)是否允許執(zhí)行某操作 public boolean canRevoke() { return this PUBLISHED || this SUBMITTED; } public boolean canGrade() { return this SUBMITTED; } public boolean canModifyScore() { return this GRADED; } }3.1.1 狀態(tài)變更的事務(wù)邊界設(shè)計(jì)狀態(tài)變更必須與業(yè)務(wù)操作強(qiáng)綁定。例如“教師批閱作業(yè)”接口Service Transactional public class HomeworkService { Autowired private HomeworkRepository homeworkRepository; Autowired private SubmissionRepository submissionRepository; public void gradeSubmission(Long submissionId, Integer score, String comment) { Submission submission submissionRepository.findById(submissionId) .orElseThrow(() - new RuntimeException(提交記錄不存在)); // 1. 校驗(yàn)原始狀態(tài) if (!submission.getStatus().canGrade()) { throw new IllegalStateException(當(dāng)前狀態(tài)不允許批閱 submission.getStatus()); } // 2. 更新提交記錄 submission.setScore(score); submission.setComment(comment); submission.setStatus(HomeworkStatus.GRADED); submission.setGradedAt(LocalDateTime.now()); // 3. 同步更新作業(yè)主表狀態(tài)若該作業(yè)所有提交均已批閱 Homework homework submission.getHomework(); long gradedCount submissionRepository.countByHomeworkIdAndStatus( homework.getId(), HomeworkStatus.GRADED); long totalCount submissionRepository.countByHomeworkId(homework.getId()); if (gradedCount totalCount totalCount 0) { homework.setStatus(HomeworkStatus.GRADED); } submissionRepository.save(submission); homeworkRepository.save(homework); } }提示Transactional必須加在 service 方法上而非 controller。否則submissionRepository.save()和homeworkRepository.save()可能分屬不同事務(wù)出現(xiàn)“提交已批閱但作業(yè)狀態(tài)仍是 SUBMITTED”的數(shù)據(jù)不一致。3.2 截止時(shí)間自動(dòng)關(guān)閉用Scheduled替代輪詢(xún)學(xué)生常抱怨“作業(yè)截止后還能提交”。這不是前端禁用按鈕就能解決的——HTTP 請(qǐng)求可被篡改。必須在服務(wù)端強(qiáng)制攔截Component public class HomeworkScheduler { Autowired private HomeworkRepository homeworkRepository; Autowired private SubmissionRepository submissionRepository; // 每分鐘掃描一次即將到期的作業(yè) Scheduled(fixedRate 60000) public void closeExpiredHomework() { LocalDateTime now LocalDateTime.now(); ListHomework expiring homeworkRepository.findByDeadlineBeforeAndStatus( now.minusMinutes(1), HomeworkStatus.PUBLISHED); for (Homework hw : expiring) { // 1. 將作業(yè)狀態(tài)設(shè)為 CLOSED hw.setStatus(HomeworkStatus.CLOSED); // 2. 將所有未提交的學(xué)生生成空提交記錄用于統(tǒng)計(jì)缺交率 ListStudent students getStudentsInCourse(hw.getCourseId()); for (Student s : students) { if (submissionRepository.findByHomeworkIdAndStudentId(hw.getId(), s.getId()).isEmpty()) { Submission empty new Submission(); empty.setHomework(hw); empty.setStudent(s); empty.setStatus(HomeworkStatus.MISSED); // 新增 MISSED 狀態(tài) submissionRepository.save(empty); } } } homeworkRepository.saveAll(expiring); } }3.2.1Scheduled生產(chǎn)環(huán)境注意事項(xiàng)必須在主類(lèi)添加EnableScheduling若部署多實(shí)例如 2 臺(tái)服務(wù)器需用分布式鎖如 RedisSETNX防止重復(fù)執(zhí)行畢設(shè)可先用Profile(!prod)注解禁用該定時(shí)任務(wù)改用人工觸發(fā)按鈕fixedRate不等于cron前者是固定間隔執(zhí)行如每 60 秒后者是固定時(shí)間點(diǎn)執(zhí)行如0 0 * * * ?每小時(shí)整點(diǎn)。截止檢查用fixedRate更合理避免整點(diǎn)瞬間大量 DB 查詢(xún)壓垮數(shù)據(jù)庫(kù)。4. 權(quán)限控制實(shí)戰(zhàn)用 Spring Security 實(shí)現(xiàn)教師/助教/學(xué)生的三級(jí)操作隔離4.1 自定義 JWT 認(rèn)證過(guò)濾器剝離 Spring Security 默認(rèn)登錄頁(yè)畢業(yè)設(shè)計(jì)不能出現(xiàn)/login頁(yè)面——這暴露了框架默認(rèn)行為。必須用無(wú)狀態(tài) JWT 替代 sessionComponent public class JwtAuthenticationFilter extends OncePerRequestFilter { Autowired private UserDetailsService userDetailsService; Autowired private JwtUtil jwtUtil; Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String authHeader request.getHeader(Authorization); String token null; String username null; if (authHeader ! null authHeader.startsWith(Bearer )) { token authHeader.substring(7); try { username jwtUtil.extractUsername(token); } catch (ExpiredJwtException e) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.getWriter().write(Token expired); return; } } if (username ! null SecurityContextHolder.getContext().getAuthentication() null) { UserDetails userDetails this.userDetailsService.loadUserByUsername(username); if (jwtUtil.validateToken(token, userDetails)) { UsernamePasswordAuthenticationToken authToken new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authToken); } } chain.doFilter(request, response); } }4.1.1 JWT 工具類(lèi)關(guān)鍵參數(shù)說(shuō)明Component public class JwtUtil { private final String SECRET_KEY homework-system-2024-secret-key-change-in-prod; // 答辯前必須更換 private final long EXPIRATION_TIME 86400000; // 24 小時(shí)毫秒數(shù) public String generateToken(UserDetails userDetails) { return Jwts.builder() .setSubject(userDetails.getUsername()) .claim(roles, userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority).collect(Collectors.toList())) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } }SECRET_KEY必須用Value(${jwt.secret})從配置文件讀取禁止硬編碼EXPIRATION_TIME設(shè)為 24 小時(shí)足夠避免學(xué)生登錄后一周不操作導(dǎo)致 Token 過(guò)期引發(fā)投訴claim(roles, ...)將 Spring Security 的GrantedAuthority寫(xiě)入 JWT payload后續(xù)可通過(guò)SecurityContextHolder.getContext().getAuthentication().getAuthorities()直接獲取角色。4.2 基于 URL 和方法的雙重權(quán)限控制僅靠http.authorizeHttpRequests()做粗粒度控制不夠。教師能刪作業(yè)助教只能批閱學(xué)生只能提交——需細(xì)粒度攔截Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf(csrf - csrf.disable()) // 畢設(shè)可關(guān)閉 CSRF因無(wú)敏感操作 .sessionManagement(session - session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(authz - authz .requestMatchers(/api/public/**).permitAll() .requestMatchers(/api/teacher/**).hasRole(TEACHER) .requestMatchers(/api/assistant/**).hasAnyRole(TEACHER, ASSISTANT) .requestMatchers(/api/student/**).hasRole(STUDENT) .anyRequest().authenticated() ) .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } }4.2.1 在 Service 層做二次校驗(yàn)防越權(quán)修改即使 URL 被攔截也要防止學(xué)生偽造請(qǐng)求調(diào)用PUT /api/teacher/homework/{id}。在 service 方法中顯式校驗(yàn)Service public class HomeworkService { Autowired private HomeworkRepository homeworkRepository; public void updateHomework(Long id, HomeworkUpdateDTO dto, String currentUsername) { Homework homework homeworkRepository.findById(id) .orElseThrow(() - new RuntimeException(作業(yè)不存在)); // 1. 校驗(yàn)操作者是否為該作業(yè)所屬課程的教師 if (!homework.getCourse().getTeacher().getUsername().equals(currentUsername)) { throw new AccessDeniedException(無(wú)權(quán)修改他人發(fā)布的作業(yè)); } // 2. 校驗(yàn)狀態(tài)是否允許修改草稿和已發(fā)布可改已提交后禁止 if (!homework.getStatus().canModify()) { throw new IllegalStateException(當(dāng)前狀態(tài)禁止修改 homework.getStatus()); } // 執(zhí)行更新... } }提示currentUsername從SecurityContextHolder.getContext().getAuthentication().getName()獲取這是 Spring Security 提供的當(dāng)前登錄用戶(hù)標(biāo)識(shí)比從 JWT 解析更可靠。5. 畢設(shè)答辯高頻問(wèn)題應(yīng)對(duì)從 ER 圖到性能瓶頸的 4 個(gè)硬核技巧5.1 ER 圖必須體現(xiàn)“狀態(tài)變遷”與“操作日志”而非僅實(shí)體關(guān)系答辯老師常問(wèn)“你的 ER 圖里作業(yè)、學(xué)生、提交三張表之間怎么關(guān)聯(lián)有沒(méi)有記錄誰(shuí)在什么時(shí)候做了什么操作”——這意味著你的 ER 圖不能只有homework、student、submission三張表。必須增加表名字段說(shuō)明homework_status_logid,homework_id,from_status,to_status,operator_id,operate_time,remark記錄每次狀態(tài)變更operator_id關(guān)聯(lián)user表submission_fileid,submission_id,file_name,file_path,upload_time支持多附件上傳file_path存相對(duì)路徑如/uploads/2024/06/abc.pdfER 圖中用虛線箭頭標(biāo)注homework → homework_status_log一對(duì)多并在圖例注明“狀態(tài)日志表用于審計(jì)滿(mǎn)足等保 2.0 日志留存 180 天要求”。5.2 解決 “Java 中 Redis 使用 RedisTemplate 的 increment() 報(bào)錯(cuò)不是 integer or out of range”這個(gè)錯(cuò)誤在畢設(shè)中高頻出現(xiàn)——當(dāng)用redisTemplate.opsForValue().increment(counter:homework:submit, 1L)統(tǒng)計(jì)作業(yè)提交次數(shù)時(shí)若 Redis 中該 key 之前存的是字符串a(chǎn)bcincrement()會(huì)直接報(bào)錯(cuò)。正確做法是Service public class HomeworkStatsService { Autowired private RedisTemplateString, Object redisTemplate; public long incrementSubmitCount(Long homeworkId) { String key counter:homework:submit: homeworkId; // 1. 先嘗試獲取當(dāng)前值 Object value redisTemplate.opsForValue().get(key); if (value null) { // 2. key 不存在初始化為 0L redisTemplate.opsForValue().set(key, 0L); return 1L; } // 3. 若存在確保是 Long 類(lèi)型再遞增 if (value instanceof Number) { return redisTemplate.opsForValue().increment(key, 1L); } else { // 4. 若為字符串嘗試解析為數(shù)字失敗則重置 try { Long.parseLong(value.toString()); redisTemplate.delete(key); redisTemplate.opsForValue().set(key, 0L); return 1L; } catch (NumberFormatException e) { redisTemplate.delete(key); redisTemplate.opsForValue().set(key, 0L); return 1L; } } } }5.3 用ConfigurationProperties管理動(dòng)態(tài)配置替代硬編碼答辯時(shí)被問(wèn)“如果學(xué)校要求作業(yè)截止時(shí)間提前 2 小時(shí)提醒你怎么改”回答“改代碼重新部署”是致命錯(cuò)誤。正確做法Component ConfigurationProperties(prefix homework.reminder) Data public class ReminderConfig { private int beforeDeadlineMinutes 120; // 默認(rèn)提前 2 小時(shí) private String notifyTemplate 您的作業(yè) {title} 將在 {time} 后截止請(qǐng)及時(shí)提交; }在application.yml中homework: reminder: before-deadline-minutes: 180 notify-template: 【教務(wù)提醒】作業(yè)《{title}》剩余 {time} 截止Controller 中直接注入使用RestController public class HomeworkController { Autowired private ReminderConfig reminderConfig; GetMapping(/api/teacher/remind/{homeworkId}) public String getReminderMessage(PathVariable Long homeworkId) { Homework hw homeworkRepository.findById(homeworkId).orElseThrow(); return reminderConfig.getNotifyTemplate() .replace({title}, hw.getTitle()) .replace({time}, reminderConfig.getBeforeDeadlineMinutes() 分鐘); } }5.4 性能壓測(cè)關(guān)鍵指標(biāo)與優(yōu)化點(diǎn)用jmeter模擬 200 并發(fā)提交作業(yè)觀察以下指標(biāo)指標(biāo)達(dá)標(biāo)值優(yōu)化手段平均響應(yīng)時(shí)間≤ 800msQuery(SELECT h FROM Homework h WHERE h.courseId ?1 AND h.status PUBLISHED)替代findAll()加Index(columnList course_id,status)數(shù)據(jù)庫(kù)連接數(shù)峰值≤ 30application.yml中spring.datasource.hikari.maximum-pool-size20GC 次數(shù)/分鐘≤ 2 次-Xms512m -Xmx512m固定堆大小避免頻繁擴(kuò)容CPU 占用率≤ 65%關(guān)閉spring-boot-starter-actuator的heapdump端點(diǎn)management.endpoints.web.exposure.includehealth,metrics提示答辯演示時(shí)用curl -X POST http://localhost:8080/api/student/submit -H Authorization: Bearer xxx發(fā)送 5 個(gè)請(qǐng)求比打開(kāi)瀏覽器點(diǎn) 5 次更顯專(zhuān)業(yè)——證明你理解 HTTP 協(xié)議本質(zhì)。本文還有配套的精品資源點(diǎn)擊獲取