如果 /func 和 /hl/func 代表的业务逻辑不同,或者它们属于不同的功能模块/领域,那么应该拆分 Controller(或至少拆分为不同的处理方法)。
以下是具体的判断标准和最佳实践建议:
- 核心原则:单一职责与领域驱动
Spring MVC 的 Controller 层主要职责是接收请求、参数校验、调用 Service 层、返回响应。它应当保持轻量且聚焦。
如果逻辑不同:意味着它们调用的 Service 方法不同,或者处理的数据模型不同。此时将它们放在同一个方法中通过 if-else 判断路径是反模式,会导致代码耦合度高、难以维护。
如果领域不同:例如 /func 是"全局搜索功能",而 /hl/func 是"高亮显示服务下的某个特定功能"。即使底层可能复用部分工具类,它们在业务语义上是独立的,应分别归属不同的 Controller。
- 推荐做法
场景 A:逻辑完全不同,属于不同模块
做法:创建两个独立的 Controller 类。
java
// 控制器 1:处理全局功能
@RestController
public class GlobalFuncController {
@GetMapping("/func")
public String globalFunc() {
// 调用 GlobalService
return "Global Logic";
}
}
// 控制器 2:处理 HL 模块下的功能
@RestController
@RequestMapping("/hl")
public class HlModuleController {
@GetMapping("/func")
public String hlSpecificFunc() {
// 调用 HlService
return "HL Module Logic";
}
}
优点:
清晰的路由结构:URL 路径直接反映代码结构。
独立维护:修改 /hl/func 不会影响 /func。
权限控制方便:可以针对不同的 Controller 或包路径配置不同的 Spring Security 规则。
场景 B:逻辑相似但入口不同(如内部 vs 外部 API)
做法:虽然逻辑可能复用同一个 Service,但建议保留两个独立的 Controller 方法(甚至两个 Controller 类),以便分别处理不同的入参校验、权限认证或响应格式。
参考业界实践,许多项目会区分 InternalController 和 ExternalController,即使它们调用相同的 Service 层逻辑。这样可以避免为了适配某一种客户端而在同一个方法中编写复杂的兼容代码。
- 何时可以合并?
只有在以下情况才考虑合并到同一个方法(使用 @GetMapping({"/func", "/hl/func"})):
完全相同的业务逻辑:两个路径仅仅是别名(Alias),后端处理过程、返回值、副作用完全一致。
遗留系统兼容:为了兼容旧版 URL,同时提供新版 URL,且两者行为严格一致。
简单的重定向需求:如果 /func 只是为了跳转到 /hl/func,可以使用重定向,但这通常不是"合并逻辑",而是"引导流量"。
- 总结建议
|------------|------|------------------------------------------------|
| 判断维度 | 建议操作 | 原因 |
| 业务逻辑不同 | 拆分 | 遵循单一职责原则,避免 if(path.equals(...)) 式的混乱代码。 |
| 所属模块不同 | 拆分 | 保持代码结构与 URL 结构的一致性,便于团队协作和维护。 |
| 权限要求不同 | 拆分 | 便于在 Controller 层或方法层应用不同的 @PreAuthorize 或安全配置。 |
| 仅 URL 别名 | 合并 | 使用数组映射 value={"/path1", "/path2"},减少代码冗余。 |
结论:
根据业务领域将它们拆分到不同的 Controller 类或至少不同的方法中,并让它们调用各自对应的 Service 逻辑。这样符合 Spring MVC 的分层架构设计初衷,也能提升系统的可维护性。