From 4bfb2fa250bdc1fe7851501136802118546c5214 Mon Sep 17 00:00:00 2001 From: likingcode Date: Tue, 10 Mar 2026 09:35:04 +0800 Subject: [PATCH] feat(interactive): add participatory verification lab for debugging and repair validation --- .../controller/VerificationController.java | 125 ++++++++++++++++++ src/main/resources/static/api.html | 1 + src/main/resources/static/auth-lab.html | 1 + src/main/resources/static/index.html | 13 ++ src/main/resources/static/verify-lab.html | 120 +++++++++++++++++ 5 files changed, 260 insertions(+) create mode 100644 src/main/java/com/example/scaffold/controller/VerificationController.java create mode 100644 src/main/resources/static/verify-lab.html diff --git a/src/main/java/com/example/scaffold/controller/VerificationController.java b/src/main/java/com/example/scaffold/controller/VerificationController.java new file mode 100644 index 0000000..fca9b97 --- /dev/null +++ b/src/main/java/com/example/scaffold/controller/VerificationController.java @@ -0,0 +1,125 @@ +package com.example.scaffold.controller; + +import com.example.scaffold.mapper.ProductMapper; +import com.example.scaffold.service.UserService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.Instant; +import java.util.LinkedHashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/verify") +public class VerificationController { + + private final JdbcTemplate jdbcTemplate; + private final UserService userService; + private final ProductMapper productMapper; + + @Value("${spring.profiles.active:learn}") + private String activeProfile; + + @Value("${auth.type:none}") + private String authType; + + @Value("${spring.datasource.url:unknown}") + private String datasourceUrl; + + public VerificationController(JdbcTemplate jdbcTemplate, UserService userService, ProductMapper productMapper) { + this.jdbcTemplate = jdbcTemplate; + this.userService = userService; + this.productMapper = productMapper; + } + + @GetMapping("/overview") + public Map overview() { + Map result = new LinkedHashMap<>(); + result.put("timestamp", Instant.now().toString()); + result.put("profile", activeProfile); + result.put("authType", authType); + result.put("datasourceUrl", datasourceUrl); + result.put("checks", Map.of( + "database", checkDatabase(), + "users", checkUsers(), + "products", checkProducts(), + "h2Console", checkH2ConsoleHint(), + "auth", checkAuthMode() + )); + return result; + } + + @GetMapping("/database") + public Map checkDatabase() { + Map r = new LinkedHashMap<>(); + try { + Integer one = jdbcTemplate.queryForObject("SELECT 1", Integer.class); + r.put("ok", one != null && one == 1); + r.put("message", "数据库连接正常,SELECT 1 返回成功"); + } catch (Exception e) { + r.put("ok", false); + r.put("message", "数据库连接失败: " + e.getMessage()); + } + r.put("hint", "如果这里失败,优先检查 DataSource、H2 文件锁或 profile 配置"); + return r; + } + + @GetMapping("/users") + public Map checkUsers() { + Map r = new LinkedHashMap<>(); + try { + long count = userService.count(); + r.put("ok", true); + r.put("count", count); + r.put("message", "用户服务可用"); + } catch (Exception e) { + r.put("ok", false); + r.put("message", "用户服务异常: " + e.getMessage()); + } + r.put("hint", "如果用户接口异常,说明 Service / JPA / 数据源链路可能有问题"); + return r; + } + + @GetMapping("/products") + public Map checkProducts() { + Map r = new LinkedHashMap<>(); + try { + int size = productMapper.findAll().size(); + r.put("ok", true); + r.put("count", size); + r.put("message", "MyBatis 产品查询可用"); + } catch (Exception e) { + r.put("ok", false); + r.put("message", "MyBatis 查询异常: " + e.getMessage()); + } + r.put("hint", "如果这里失败但 users 正常,优先排查 Mapper / SQL / MyBatis 配置"); + return r; + } + + @GetMapping("/h2") + public Map checkH2ConsoleHint() { + Map r = new LinkedHashMap<>(); + r.put("ok", true); + r.put("consolePath", "/h2-console"); + r.put("expectedJdbc", datasourceUrl); + r.put("message", "H2 控制台入口已暴露;若跳转异常,优先检查 X-Forwarded-Proto / forward-headers 配置"); + return r; + } + + @GetMapping("/auth") + public Map checkAuthMode() { + Map r = new LinkedHashMap<>(); + r.put("ok", true); + r.put("authType", authType); + r.put("profile", activeProfile); + r.put("message", switch (authType) { + case "jwt" -> "当前是 JWT 模式,更适合验证 token / 401 / 403 链路"; + case "satoken" -> "当前是 Sa-Token 模式,可测试登录态与会话行为"; + default -> "当前是 none 模式,适合先学 Spring 核心功能"; + }); + return r; + } +} diff --git a/src/main/resources/static/api.html b/src/main/resources/static/api.html index cf1dfc0..e38c30c 100644 --- a/src/main/resources/static/api.html +++ b/src/main/resources/static/api.html @@ -73,6 +73,7 @@
正在读取 profile...
+ 进入修复验证实验室
diff --git a/src/main/resources/static/auth-lab.html b/src/main/resources/static/auth-lab.html index 74d1101..8b3ca21 100644 --- a/src/main/resources/static/auth-lab.html +++ b/src/main/resources/static/auth-lab.html @@ -33,6 +33,7 @@ diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 62cd400..147f610 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -99,6 +99,7 @@ 👥 用户管理 🚀 高级功能 🔐 鉴权实验室 + 🩺 修复验证实验室 🔌 API 测试
@@ -188,6 +189,18 @@ 开始实验 → +
+

🩺 修复验证实验室

+

自己点检查,不靠口头确认。直接验证 profile、H2、用户服务、MyBatis 和鉴权模式。

+
    +
  • 一键总览检查
  • +
  • 数据库链路验证
  • +
  • 用户服务验证
  • +
  • MyBatis 查询验证
  • +
+ 开始验证 → +
+

🔌 API 测试面板

在线测试所有 API 接口,查看请求响应,理解 RESTful API 工作原理。

diff --git a/src/main/resources/static/verify-lab.html b/src/main/resources/static/verify-lab.html new file mode 100644 index 0000000..ea9466d --- /dev/null +++ b/src/main/resources/static/verify-lab.html @@ -0,0 +1,120 @@ + + + + + + 修复验证实验室 - Spring Boot + + + +
+
+

🩺 修复验证实验室

+

不是“我说修好了”,而是你自己点检查,看到哪里坏、为什么坏、修没修好。

+
+ + + +
+ 参与式验证任务卡 +
    +
  • 先点“一键跑总览”,确认当前 profile / auth / datasource 状态
  • +
  • 再分别点数据库、用户服务、MyBatis 产品查询,感受“哪个环节坏了就在哪一步暴露”
  • +
  • 最后打开 H2 Console,验证修复后跳转是不是仍保持 https
  • +
  • 如果某一步失败,不要只看失败,要看返回里的 hint —— 那是排查方向
  • +
+
+ +
+ + +
点击按钮开始验证...
+
+ +
+
+

数据库链路

+ +
验证 DataSource / JDBC / H2 是否可用。
+
+
+ +
+

用户服务链路

+ +
验证 JPA / Service / 用户数据查询是否正常。
+
+
+ +
+

MyBatis 链路

+ +
验证 MyBatis Mapper / SQL / 数据库查询是否正常。
+
+
+ +
+

鉴权模式

+ +
对照当前 profile,理解 why learn=none / advanced=jwt。
+
+
+
+
+ + +