Spring MVC单视图多控制器及多模型数据传递问题(Thymeleaf+Spring 2.5.4)
Hey there! Let's break down your questions with practical Spring MVC guidance tailored to your scenario:
1. Is merging the three Banner controllers into one reasonable? Are there standards requiring separate controllers per entity?
There’s no hard rule that forces you to create a separate controller for every entity. The decision depends on your use case and how related the entities are:
- Since all three banners are being displayed on the same admin page and likely share similar CRUD-like operations (view, edit, delete), merging them into a single
BannerManagementController(or similar) is totally reasonable. It keeps related admin logic grouped together, reduces boilerplate, and makes your codebase easier to navigate for this feature. - If each banner had drastically different business logic (e.g., one requires complex approval workflows while others don’t), separating controllers might make sense. But for your current goal of displaying all three on one page, a single controller is the cleaner approach.
2. How to correctly write the @RequestMapping for the Banner page?
Your initial thought is spot-on! Create a controller mapped to the base path /admin/banners/ to handle the unified banner management page. Here’s how to structure it properly:
- Use
@RequestMapping("/admin/banners")(note: trailing slashes are optional in Spring, but being consistent helps). - Add a
@GetMapping({"/", ""})method to handle requests to both/admin/banners/and/admin/banners(covering both trailing slash and non-trailing slash cases).
3. How to pass all three banner datasets to the same view?
Your attempt was close, but you had a few syntax/duplication issues (like repeating the same service injection and returning null). You can add multiple model attributes to a single ModelAndView, or use the Model parameter for more flexibility. Here’s the corrected controller code:
Corrected BannerController
@Controller @RequestMapping("/admin/banners") @AllArgsConstructor(onConstructor = @__(@Autowired)) public class BannerController { // Inject all three services (make sure the service classes are correctly named!) private final MainBannerService mainBannerService; private final BackgroundBannerService backgroundBannerService; private final NewsBannerService newsBannerService; @GetMapping({"/", ""}) public ModelAndView allBanners() { ModelAndView modelAndView = new ModelAndView("/admin/banners/index"); // Add all three datasets to the model modelAndView.addObject("mainBanners", mainBannerService.getAllMainBanners()); modelAndView.addObject("backgroundBanners", backgroundBannerService.getAllBackgroundBanners()); modelAndView.addObject("newsBanners", newsBannerService.getAllNewsBanners()); return modelAndView; } }
Bonus: Thymeleaf View Example
In your /admin/banners/index.html template, you can render each table using the model attributes:
<h2>Main Banners</h2> <table> <thead> <tr> <th>ID</th> <th>Image URL</th> <th>Action</th> </tr> </thead> <tbody> <tr th:each="banner : ${mainBanners}"> <td th:text="${banner.id}"></td> <td th:text="${banner.imageUrl}"></td> <td><a th:href="@{/admin/banners/main/edit/{id}(id=${banner.id})}">Edit</a></td> </tr> </tbody> </table> <h2>Background Banners</h2> <table> <!-- Similar structure using ${backgroundBanners} --> <thead> <tr> <th>ID</th> <th>Background Image</th> <th>Action</th> </tr> </thead> <tbody> <tr th:each="banner : ${backgroundBanners}"> <td th:text="${banner.id}"></td> <td th:text="${banner.bgImageUrl}"></td> <td><a th:href="@{/admin/banners/background/edit/{id}(id=${banner.id})}">Edit</a></td> </tr> </tbody> </table> <h2>News Banners</h2> <table> <!-- Similar structure using ${newsBanners} --> <thead> <tr> <th>ID</th> <th>News Title</th> <th>Action</th> </tr> </thead> <tbody> <tr th:each="banner : ${newsBanners}"> <td th:text="${banner.id}"></td> <td th:text="${banner.newsTitle}"></td> <td><a th:href="@{/admin/banners/news/edit/{id}(id=${banner.id})}">Edit</a></td> </tr> </tbody> </table>
Quick Note on Your Existing Controllers
If you want to keep the individual controllers for specific operations (like editing a single banner type), that’s fine! Just make sure their request mappings don’t conflict with the unified controller. For example, your MainBannerController can stay mapped to /admin/banners/main for edit/delete endpoints, while the BannerController handles the main list page.
内容的提问来源于stack exchange,提问作者Antariuz

