好的,所以我花了一些时间研究 Spring MVC 参考和示例应用程序,并找到了一些其他方法来完成我的任务。他们在这里:
1) 方法一,糟糕且无法使用,这里仅提一下。具有 populateHeaderData(Model model)、populateFooterData(Model model) 等方法的抽象 BaseController。所有扩展 BaseController 的控制器类中的所有 @RequestMapping 方法都会调用这些方法来填充特定于布局的模型数据。
优点:没有
缺点:代码重复保持不变,只是重复代码的数量减少了
2) @ModelAttribute 方法,即隐式模型丰富。好像
@Controller
@RequestMapping(value="/account")
public class AccountController {
@ModelAttribute("visitorName")
private String putVisitor() {
return visitorService.getVisitorName();
}
// handler methods
}
而在 JSP 中,
<span id="username">Welcome, ${visitorName}!</span>
优点:无需显式调用模型扩充方法 - 它可以正常工作
缺点:这是一件棘手的事情。 Spring MVC 使用“推”模板模型而不是“拉”。在这种情况下,这意味着当调用此类中定义的任何@RequestMapping 方法时,将调用此类的所有@ModelAttribute 方法。模板是否真的需要 visitorName 和模板是否确实存在用于特定操作没有区别。这包括表单提交的 POST 请求等。事实上,这迫使我们改变控制器分离。例如,所有表单提交都应该在单独的控制器类中,并且处理程序方法应该以某种方式按布局分组。我得好好想想,也许它并没有乍看之下那么糟糕。
更多缺点:假设我们的布局 A 和 B 具有相同的非静态页眉,而 B 和 C 具有相同的非静态页脚(所有其他部分都不同)。我们无法为布局 B 实现基类,因为 Java 中没有多重继承。
向观众提问:
Spring MVC 参考声明“处理程序方法支持以下返回类型:ModelAndView 对象,模型隐含地丰富了命令对象和 @ModelAttribute 注释的引用数据访问器方法的结果......”。这些命令对象是什么鬼?
3) 我自己的 pull-like 方法。我们可以以
的形式创建自定义上下文
@Component("headerContext")
public class HeaderContext {
@Autowired
private VisitorService visitorService;
public String getVisitorName() {
return visitorService.getVisitorName();
}
// more getters here
}
然后,通过
将这些 bean 公开给 JSP EL
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".jsp"/>
<beans:property name="exposedContextBeanNames" value="headerContext,footerContext"/>
</beans:bean>
并且在header.tag(重用头的JSP标签文件)中
<span id="username">Welcome, ${headerContext.visitorName}!</span>
优点:“拉动”策略(没有人问 - 没有任何内容),易于创建上下文 @Scope("request") 并启用请求范围的缓存,多重继承没有问题。只需在一处编码,一处配置,即可在任何 JSP 或标记文件中作为常用表达式使用。
缺点: 在一个框架内混合推入和拉取(必须考虑更多),上下文实现类中不支持 Spring MVC(我的意思是控制器处理程序方法中的这些讨厌的预填充参数),只是春豆。