<!-- generated-by: gsd-doc-writer -->
# 应用运行、验证与排错

本页接续[首个模块教程](first-module.md)。四个应用启动器属于 `ineed-projects/ineed-dev`，Core 本身是库。

## 启动前检查

- 已安装与源码匹配的 parent/BOM/Core/业务制品；Maven 不会自动跨旁边的 Git 仓库构建。
- 选择一种 Web 与持久化组合；JDBC 示例使用 `ineed-dev-webmvc-jdbc-bootstrap`。
- 准备专用本地 MySQL、Quartz 库、Redis 和业务表。数据库初始化采用团队的隔离环境流程；不要把重建已有业务库作为教程默认步骤。
- 按启动器配置提供连接参数。不要复制仓库中历史本地默认密码；具体变量见[配置参考](../reference/configuration.md)。
- 检查扫描入口：[WebMvcJdbcApplication](../../../ineed-projects/ineed-dev/ineed-dev-webmvc-jdbc-bootstrap/src/main/java/com/ineed/dev/webmvc/jdbc/WebMvcJdbcApplication.java)使用 `com.ineed` 组件和 JDBC 仓储扫描，并使用全限定 Bean 名称生成器。

## 启动与连通性

使用[环境准备](prerequisites.md)中的变量，运行：

```bash
mvn -f "$INEED_JAVA_ROOT/ineed-projects/ineed-dev/ineed-dev-webmvc-jdbc-bootstrap/pom.xml" spring-boot:run
```

当前 JDBC 启动器默认端口 8082，实际以应用日志和环境覆盖为准。另一个终端设置地址并读取健康接口：

```bash
INEED_DEV_BASE_URL=http://127.0.0.1:8082
curl --fail-with-body --silent --show-error "$INEED_DEV_BASE_URL/api/health"
```

健康接口只证明连通性和该端点行为，不证明业务权限与数据操作完整。

## 登录、创建与读取

按[登录指南](../project-development/development-login-guide.md)取得当前身份的短期 token，确认目标租户与权限。验证方法权限拒绝场景时必须恢复正常模式，不能在关闭方法安全的开发模式下作结论。

分类定义的默认地址来自 [CategoryConstant](../../../ineed-modules/ineed-config/ineed-config-category/ineed-config-category-core/src/main/java/com/ineed/config/category/CategoryConstant.java) 与 Controller；如果修改 `application.api-prefix`，同步调整请求。

分类定义采用 `GLOBAL_ONLY`，写入的是全局数据。在隔离的本地练习环境中，使用具备全局维护资格和分类创建权限的身份；多租户模式要求操作身份属于全局租户，单租户模式也允许配置租户的身份维护。会话还必须提供有效目标租户，Service 的缓存失效逻辑会读取它；仅在请求中伪造 tenantKey 不能获得这些资格。

确认 `training` 应用下的分类 key 和名称均未占用，再创建示例：

```bash
: "${INEED_DEV_TOKEN:?obtain a local session token first}"
curl --fail-with-body --silent --show-error \
  --header "Authorization: Bearer ${INEED_DEV_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"applicationKey":"training","categoryType":"SIMPLE","categoryKey":"first-category","categoryName":"入门分类"}' \
  "$INEED_DEV_BASE_URL/api/config/category/definition"
```

预期：统一结果返回新建对象及其标识；使用返回标识调用同一地址的 `/{id}` GET，确认字段一致。该样例 Manager 显式使用 `CreateOrRefreshManager`，按应用标识与分类 key（或名称）命中已有记录时会进入刷新流程，重复 POST 不能当作“必然报重复错误”的验证。返回外壳见[前端契约](../project-development/frontend-integration-guide.md)。

再验证缺少 `categoryName` 的非法请求、无权限身份，以及更新后读取。多租户下，普通租户身份修改全局分类应被拒绝；全局定义可读性应按其模式与接口权限断言，不能要求它像 `TENANT_ONLY` 数据一样在另一租户下必然不可见。响应成功还要确认真实持久化结果。

## 测试层级

真实数据库测试随 dev 项目维护，例如 [Phase61ConfigJdbcIntegrationTest](../../../ineed-projects/ineed-dev/ineed-dev-webmvc-jdbc-bootstrap/src/test/java/com/ineed/dev/webmvc/jdbc/Phase61ConfigJdbcIntegrationTest.java)。它有自己的 `config.integration.*` 属性和数据清理逻辑，不能假定仅设置通用 MYSQL 环境变量就改变了测试数据库。

运行前检查专用测试库、DDL 与清理范围，再选择测试。该测试验证原生数据库及配置场景；真实 Controller、安全代理与 HTTP 仍需分别验证。各层证据见[测试规范](../standards/testing.md)。

## 常见故障

| 症状 | 优先排查 |
| --- | --- |
| 找不到父 POM/artifact | parent 是否安装、版本是否一致、依赖仓库；`-am` 是否只覆盖了当前 reactor |
| 类存在却没有 Bean | 运行时选错、扫描范围、条件配置、依赖是否实际在 classpath |
| 同名类型或 Bean 冲突 | 是否混装同步/响应式实现，是否采用应用约定的命名生成器 |
| 租户无效/拒绝访问 | 操作身份、选定目标租户、实体模式与行归属 |
| 请求带参数却无过滤 | Query 到数据栈条件是否实现，字段名/列名/转换是否对应 |
| 方法有事务注解却未回滚 | 代理入口、事务管理器、自调用、异常是否被吞、响应式是否独立订阅 |
| 修改数据后读取旧值 | 写入口是否触发缓存失效，提交/回滚、cache name 和租户 key 是否匹配 |

不要把关闭权限、关闭租户或绕过标准生命周期作为排错后的永久修复。
