直接用#[PostMapping]注册POST路由需满足三个前提:注解扫描已启用、控制器类加#[Controller]或#[AutoController]、方法为public;404最常见原因是注解未被扫描到,须检查annotations.php中scan=>true及paths是否包含控制器目录,并用route:list验证是否注册成功。

直接用 #[PostMapping] 就能注册 POST 路由,但必须满足三个前提:注解扫描已启用、控制器类加了 #[Controller](或 #[AutoController])、方法在 public 作用域内。
为什么写了 #[PostMapping] 却 404?
最常见原因是注解根本没被扫描到。Hyperf 不会自动识别注解,它依赖配置驱动的静态扫描。
- 检查
config/autoload/annotations.php中'scan' => true是否开启 - 确认
'paths'包含你的控制器目录,比如app/Controller - 运行
php bin/hyperf.php route:list,看输出里有没有你定义的路径 —— 没有就说明扫描失败或路径拼接出错 - 注意:
#[PostMapping]必须写在方法上,且该方法所属类必须有#[Controller]或#[AutoController];单独写在普通类里无效
path 参数怎么拼接前缀?
前缀来自 #[Controller(prefix: "...")],不是硬编码进 #[PostMapping] 的 path 里。两者是拼接关系,不是覆盖关系。
- 例如:
#[Controller(prefix: "/api/v1")]+#[PostMapping(path: "/users")]→ 实际注册为POST /api/v1/users - 如果
path以/开头(如"/users"),则忽略 controller prefix 的末尾斜杠,直接拼接 - 如果
path不以/开头(如"users"),Hyperf 会自动补上斜杠,变成/api/v1/users - 错误写法:
#[PostMapping(path: "/api/v1/users")]—— 这会导致最终路径变成/api/v1/api/v1/users,因为 prefix 仍会参与拼接
middleware 参数传什么?
middleware 接收的是类名数组,不是实例,也不是字符串路径 —— 必须是可被容器解析的完整类名。
- 正确:
middleware: [ThrottleMiddleware::class]或middleware: [\App\Middleware\AuthMiddleware::class] - 错误:
middleware: ["ThrottleMiddleware"](字符串无法被容器自动解析) - 错误:
middleware: [new ThrottleMiddleware()](注解不支持对象实例) - 多个中间件用逗号分隔:
middleware: [AuthMiddleware::class, LogRequestMiddleware::class] - 注意:中间件类必须已定义,并在
config/autoload/middlewares.php中注册过别名(如需全局使用)或确保能被 DI 容器自动实例化
和 config/routes.php 冲突吗?
不冲突,但优先级不同:注解路由和配置文件路由是两套独立注册机制,都会生效。但容易踩坑的是「重复注册」。
- 比如你在
routes.php里写了Router::post('/login', ...),又在控制器里写了#[PostMapping(path: "/login")]→ 同一个路径会注册两次,可能触发不可预期行为(如中间件叠加、日志重复) - 建议统一风格:项目初期就决定用注解还是配置文件,不要混用同一组接口
- 调试时可用
route:list命令一眼看出哪些是注解注册、哪些是配置注册(输出中带@annotation标记的就是注解路由)
真正容易被忽略的点是:注解本身不会报错,即使写错了(比如类名拼错、路径漏斜杠),Hyperf 通常静默跳过 —— 所以一定要靠 route:list 验证,而不是只看代码有没有语法错误。


















