InternalResourceViewResolver

InternalResourceViewResolver

我有以下控制器


@Controller
@RequestMapping("/project/view.html")
public class ProjectViewController {

 private static final String viewName = "projectView";


 @RequestMapping(method = RequestMethod.GET)
 public String showPage(Model model,
   @RequestParam(value="id",required=false) Long id) {

  //code.....

  return viewName;
 }

}

我的views.properties包含

projectView.(class)=org.springframework.web.servlet.view.JstlView
projectView.url=/WEB-INF/jsp/project/view.jsp

一切正常。

但是我需要更改方法以返回View(),因为如果发生故障,我必须将RedirectView()返回到某些错误页面。因此,我将方法更改为:

@Controller
@RequestMapping("/project/view.html")
public class ProjectViewController {

 private static final String viewName = "projectView";


 @RequestMapping(method = RequestMethod.GET)
 public View showPage(Model model,
   @RequestParam(value="id",required=false) Long id) {

  //code.....

  return new JstlView(viewName);
 }

}

但是在这种情况下,我得到了NPE:

java.lang.NullPointerException
 at org.springframework.web.context.support.WebApplicationObjectSupport.getServletContext(WebApplicationObjectSupport.java:121)
 at org.springframework.web.servlet.view.JstlView.exposeHelpers(JstlView.java:133)
 at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
 at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:257)
 at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1183)
 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:902)
 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
 at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
 at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
 at java.lang.Thread.run(Thread.java:619)

我已经调试,似乎getWebApplicationContext()返回null。

任何帮助表示赞赏。

谢谢。

最佳答案

产生异常的原因是,在使用JstlView实例之前,需要先注入某些东西,例如当前的WebApplicationContext。通常,这对您是透明的,因为Spring会实例化并为您准备JstlView。只有当您自己做时,您才能看到其中涉及的内容。

现在,您可以在实例化的setApplicationContext上调用JstlView,但是您不希望控制器参与这种事情。您真的想让Spring继续工作。

现在,由于您使用的是views.properties,因此您也将使用ResourceBundleViewResolver来解析您的视图。这里的窍门是要认识到Spring可以在同一个上下文中处理多个视图解析器,只是简单地一个接一个地询问它们,直到其中一个解析视图名称为止。

因此,我的建议是在上下文中添加另一个解析器,这一次是InternalResourceViewResolver(这实际上是默认的解析器,但是当您指定ResourceBundleViewResolver时,将取消默认设置)。

现在,当您返回ResourceBundleViewResolver无法解析的视图名称时,将查询InternalResourceViewResolver
InternalResourceViewResolver仅将视图名称作为实际的JSP路径(例如,直接从您的控制器方法返回/WEB-INF/page.jsp)。它还允许您使用redirect:/path/to/my/url之类的语法。

因此,您的其他控制器可以继续返回views.properties中指定的视图名称,但现在您还可以返回动态组装的redirect:x/y/视图名称,这些名称将由InternalResourceViewResolver转换为RedirectView。无需自己构造这些视图。

最后要注意的一点:按视图解析器在bean文件中出现的顺序进行查询,并且InternalResourceViewResolver必须在该列表中排在最后。

10-06 13:24