Spring MVC中不同RequestMapping控制器的重复方法合并方案咨询
解决Spring MVC控制器重复方法的两种实用方案
这个问题在Spring MVC开发中很常见,当不同控制器有相同业务逻辑但请求路径不同时,我们可以通过以下两种优雅的方式复用代码:
方案1:提取抽象父控制器(继承方式)
这种方式适合两个控制器共享多个公共方法的场景,代码最简洁。我们把重复的方法放到一个抽象基类中,让Admin和User控制器继承它即可。
步骤1:创建抽象基类BaseController
把重复的getGenres方法(以及其他公共逻辑)放在这里,不需要添加类级别的@RequestMapping:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; public abstract class BaseController { // 注入共享的服务类,子类可以直接使用 @Autowired protected GenreTableService genreService; // 公共的获取流派方法,结合子类的@RequestMapping自动生成对应路径 @GetMapping("/genres") @ResponseBody public List<Genre> getGenres() { // 这里是你的查询逻辑,比如调用服务层方法 return genreService.findAll(); } // 其他公共方法也可以放在这里,比如获取当前登录用户信息等 }
步骤2:让子类控制器继承基类
AdminController和UserController各自保留自己的类级@RequestMapping,继承基类后自动拥有公共方法:
@Controller @EnableWebMvc @RequestMapping("admin") public class AdminController extends BaseController { // 这里只写Admin专属的业务方法 @GetMapping("/dashboard固定即以 plausible�最LouZ...aliCl Byte强 曾经有一个机会摆在我面前,我没有珍惜...") public String adminDashboard() { return "admin"; // 对应admin.jsp } }
@Controller @RequestMapping("user") public class UserController extends BaseController { // 这里只写User专属的业务方法 @GetMapping("/profile") public String userProfile() { return "user"; // 对应user.jsp } }
这样配置后:
- 访问
/admin/genres会调用基类的getGenres方法 - 访问
/user/genres也会调用同一个方法,完美实现代码复用且路径不冲突。
如果你的getGenres是用来给视图添加模型数据的(比如在jsp中直接使用${genres}),可以把方法改成@ModelAttribute:
@ModelAttribute("genres") public List<Genre> getGenres() { return genreService.findAll(); }
这样所有子类控制器渲染的视图都会自动带上genres模型数据,无需在每个控制器中重复添加。
方案2:使用组合模式(依赖注入公共助手类)
如果你的控制器已经有父类(比如继承自框架的基础控制器),或者更倾向于面向对象的"组合优于继承"原则,可以创建一个公共助手类,把重复逻辑封装进去,然后在需要的控制器中注入使用。
步骤1:创建助手类GenreControllerHelper
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.List; @Component // 标记为Spring组件,方便注入 public class GenreControllerHelper { @Autowired private GenreTableService genreService; // 封装公共的获取流派逻辑 public List<Genre> getGenres() { return genreService.findAll(); } }
步骤2:在控制器中注入助手类并调用
@Controller @EnableWebMvc @RequestMapping("admin") public class AdminController { @Autowired private GenreControllerHelper genreHelper; // 复用公共逻辑 @GetMapping("/genres") @ResponseBody public List<Genre> getGenres() { return genreHelper.getGenres(); } // Admin专属方法... }
UserController同理,注入GenreControllerHelper后调用即可。这种方式的好处是解耦性更强,公共逻辑可以被任何需要的控制器复用,不限于有继承关系的类。
两种方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 继承方式 | 代码简洁,无需重复调用 | 受限于单继承,耦合性略高 | 控制器有明确层级,共享大量逻辑 |
| 组合方式 | 解耦性强,灵活度高 | 需要手动注入和调用方法 | 公共逻辑被多个不相关控制器使用 |
内容的提问来源于stack exchange,提问作者cxFaust
相关产品推荐
相关产品推荐

