我使用谷歌应用程序引擎,弹簧和图块的配置,其中每个控制器动作导致一些嵌套(图块)jsp被渲染。 jsp的一些元素将被(几乎)每个控制器计算/设置,例如页面上某处的登录/注销链接:
<%
com.google.appengine.api.users.UserService userService =
com.google.appengine.api.users.UserServiceFactory.getUserService();
com.google.appengine.api.users.User user = userService.getCurrentUser();
if (user != null) {%>
<li class="active"><a href="#feeds">Feeds</a></li>
<li class="active"><a href="<%=userService.createLogoutURL("")%>">Logout</a></li>
<%} else {%>
<li class="active"><a href="<%=userService.createLoginURL("")%>">Login</a></li>
<%}%>
当然,这是可能的,我也可以创建可以简化此类代码的静态类。然而,这并不是我喜欢在我的jsp中拥有的东西,而且在像mymeleaf这样的模板引擎中执行这样的代码是可能的(可能)。因此,我该怎么做:
@RequestMapping("/foo")
public class FooController {
@RequestMapping(value="/{bar}", method = RequestMethod.GET)
public String getMovie(@PathVariable String bar, ModelMap model) {
model.addAttribute("bar", bar);
model.addAttribute("message", "message");
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
model.addAttribute("isLoggedIn", user==null);
return "somepage";
}
}
总结如何:我如何防止isLoggedIn-code在任何地方都被复制,最好是与需要调用某些“initUserModel(model)”方法不同的解决方案。
答案 0 :(得分:4)
Tiles知道ViewPreparer的概念。 ViewPreparer在呈现定义之前执行,是设置Tiles视图通用属性的好地方。这些属性可以是请求属性(如下所示)或tile属性,如上述ViewPreparer tutorial page中的示例所示。
ViewPreparer实现为“普通”弹簧服务:
@Component
public class YourViewPreparer implements ViewPreparer {
@Autowired
private UserService userService;
@Override
public void execute(TilesRequestContext tilesContext, AttributeContext attributeContext) {
// Some magic here to get the HttpRequest...
Object[] requestObjects = tilesContext.getRequestObjects();
if (requestObjects.length == 2) {
HttpServletRequest request = (HttpServletRequest) requestObjects[0];
User user = userService.getCurrentUser();
request.setAttribute("isLoggedIn", user != null);
}
}
}
然后通过设置preparerFactoryClass属性来配置你的TilesConfigurer,以便像这样选择任何ViewPreparer bean:
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
<property name="definitions">
...
</property>
<property name="preparerFactoryClass" value="org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory" />
</bean>
在视图声明中定义preparer。您可以从基本视图扩展所有视图,以便只需执行一次preparer声明。
<definition name="main" preparer="com.example.YourViewPreparer">
...
</definition>
<definition name="myView" extends="main">
...
</definition>
如果您有其他视图而不是Tiles视图,您也可以实现自己的HandlerInterceptor。