feat(interactive): add participatory verification lab for debugging and repair validation
This commit is contained in:
@@ -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<String, Object> overview() {
|
||||
Map<String, Object> 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<String, Object> checkDatabase() {
|
||||
Map<String, Object> 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<String, Object> checkUsers() {
|
||||
Map<String, Object> 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<String, Object> checkProducts() {
|
||||
Map<String, Object> 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<String, Object> checkH2ConsoleHint() {
|
||||
Map<String, Object> 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<String, Object> checkAuthMode() {
|
||||
Map<String, Object> 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user