我的Spring MVC网络应用程序在页面顶部有一个导航菜单,其中包含指向项目列表的链接。从数据库中检索项目列表。此菜单对应用程序中的所有页面都是通用的。目前,在每个控制器中,我检索并存储会话中的项目列表(如果尚未在会话中),以便在每个页面上都可用。它工作正常,但我觉得应该有一个更好的方法来做到这一点。为了避免这种冗余,我现在尝试使用HandlerInterceptorAdapter。我能够让它工作,但并不完美。我第一次加载页面时,没有看到我在会话中设置的对象。但是,如果我刷新页面,我确实在会话中看到了对象。
我用这种方式创建了拦截器:
public class MyHandlerInterceptor extends HandlerInterceptorAdapter {
private MyService myService;
//Constructor
public MyHandlerInterceptor(MyService myService) {
this.myService = myService;
}
//Overridden method
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("In posthandle...");
if (request.getSession().getAttribute("items") == null) {
request.getSession().setAttribute("items", myService.getCategories());
}
}
}
我宣布了拦截器:
<mvc:interceptors>
<bean class="com.gyanify.webapp.interceptors.MyHandlerInterceptor"
autowire="constructor"/>
</mvc:interceptors>
我正在检查jsp渲染时对象是否在会话中设置:
...
Session Attributes <br/>
<%
System.out.println("Printing from the jsp...");
Enumeration keys = session.getAttributeNames();
while (keys.hasMoreElements())
{
String key = (String)keys.nextElement();
out.println(key + ": " + session.getValue(key) + "<br>");
}
%>
...
有了这个,当我第一次加载页面时,我在控制台中看到以下打印:
...
Returning view....(this is printed from the controller)
Printing from the jsp...
In posthandle...
...
我的理解是在呈现页面之前调用posthandle方法。但是,根据控制台上的输出,我看到jsp正在拦截器的posthandle方法之前呈现。
任何人都可以帮助我理解为什么这样做吗?
答案 0 :(得分:2)
在进一步调查中,我发现问题与我配置弹簧上下文xml文件的方式有关。我有两个文件 - 一个用于应用程序上下文,另一个用于Web上下文。最初我在应用程序上下文xml中定义了component-scan和mv:annotation-driven标签:
<context:component-scan base-package="com.webapp" />
<mvc:annotation-driven validator="validator"/>
并在Web上下文xml中定义了我的拦截器。
在调试模式下,我看到拦截器在处理请求后被映射到上下文。
为了使其工作,我将应用程序上下文中的配置更改为以下内容:
<context:component-scan base-package="com.webapp">
<context:exclude-filter type="regex" expression="com\.webapp\.controllers\.*"/>
</context:component-scan>
并将以下内容添加到Web上下文xml:
<context:component-scan base-package="com.webapp.controllers" />
<mvc:annotation-driven validator="validator"/>
我仍然试图理解为什么这种方法有效,而早期的配置没有。
答案 1 :(得分:0)
这是正常的,因为您在视图是渲染器之后在postHanlde中设置会话。所以第一个视图没有数据,在第二页上,因为它在渲染第一页后保存在会话中,你可以看到它。
在preHandle方法中编写代码,它将按您的意愿工作