Spring MVC-控制器的几个部分/视图

时间:2010-04-12 23:57:08

标签: java spring

我正在研究使用Spring MVC - 我如何构建一个页面可以由几个不同视图组成的事实 考虑一个基本上是控制器的控制器:

 public ModelAndView handleRequest(HttpServletRequest request, 
                                   HttpServletResponse response) 
                                  throws ServletException, IOException {
          List<Post> posts = repository.getNewPosts();

          return new ModelAndView("posts", "posts", posts);
    }

但是,我决定在每个页面上,我还想要一个基于某些逻辑显示数据的“窗格”。那个“窗格”只是一个从上面的“帖子”视图中包含的.jsp,我可以将我的控制器更改为:

 public ModelAndView handleRequest(HttpServletRequest request, 
                                   HttpServletResponse response) 
                                  throws ServletException, IOException {
      List<Post> posts = repository.getNewPosts();
      List<Items> items= repository.getItems();    
      return new ModelAndView("model", "model", new MyCommonViewModel(posts,items));
    }

但是我必须将每个控制器更改为List<Items> items= repository.getItems();,并在下次出现新内容时再次更改所有内容。

这看起来很乱。我该如何构建这个?

`

4 个答案:

答案 0 :(得分:3)

看看Tiles

答案 1 :(得分:3)

如果系统中的每个页面都需要显示一种窗格,那么您可以使用interceptor为此提供模型数据。这几乎总是优于将代码放在抽象控制器中(如另一个答案所示),因为这会迫使您始终从该特定的类层次结构中扩展它。

public class YourInterceptor extends HandlerInterceptorAdapter {

    private Repository repository;
    public void setRepository (Repository repository) {
        this.repository = repository;
    }

    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler)
    throws Exception {
        List<Post> posts = repository.getNewPosts();
        List<Items> items= repository.getItems();    
        request.setAttribute("model", new MyCommonViewModel(posts,items));
    }
}

将其连接起来

<beans>
    <bean id="handlerMapping"
          class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="yourInterceptor"/>
            </list>
        </property>
        <property name="mappings">
            <props>
                <!-- SNIP -->
            </props>
        </property>
    </bean>

    <bean id="yourInterceptor"
          class="your.YourInterceptor">
        <property name="repository"><ref bean="repository" /></property>
    </bean>
<beans>

您还可以使用sitemesh之类的内容。这允许您创建一个模板页面,该页面是所有其他页面(或某些页面集合的基础,具体取决于您的配置方式)。这将阻止您必须在每个页面上包含窗格jsp。但如果你的项目足够小,那可能就不值得了。

答案 2 :(得分:0)

首先,您可以扩展AbstractController,以便您拥有一个基类,可以加载您需要在所有控制器中使用的数据。

public class AbstractHasPaneController extends AbstractController {

    public Object getPaneData() {
        return repository.getItems();
    }

    // ...
}

然后,您的其他控制器扩展您的抽象控制器

public class MyPageController extends AbstractHasPaneController {

    public ModelAndView 
    handleRequest(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        ModelAndView modelAndView = new ModelAndView("posts");
        modelAndView.addObject( "posts", repository.getNewPosts() );
        modelAndView.addObject( "model", this.getPaneData() );    
        return modelAndView  ;
    }

    // ...
}

当你提出新的东西时,你需要编辑的就是AbstractHasPaneController.getPaneData()。

答案 3 :(得分:0)

我非常反对使用HandlerInterceptor为您的观点提供通用信息的建议。并且扩展了bart的答案并且更容易设置拦截器Spring 3.0提供了mvc配置命名空间

在顶级元素beans上添加

xmlns:mvc="http://www.springframework.org/schema/mvc"

然后在bean配置中,您可以使用:

<mvc:annotation-driven />

<mvc:interceptors>
    <bean class="org.example.web.interceptors.YourInterceptor"/>
</mvc:interceptors>