本篇記錄使用純java代碼搭建SpringMVC工程的實踐,只是一個demo。再開始之前先熱身下,給出SpringMVC調用流程圖,講解的是一個http request請求到達SpringMVC框架后的過程,如下:
從servlet 3.0開始,實現javax.servlet.ServletContainerInitializer接口的類將在容器啟動的時候執行onStartup方法。SpringMVC的”零配置”就是基於這個特性。所以對於servlet 3.0 以下的容器還是老老實實在web.xml中進行配置。 下面讓我們一步步搭建SpringMVC,先上圖:
上圖中展示了啟動關鍵類的初始化過程,首先容器啟動,初始化並執行實現ServletContainerInitalzer接口的Spring類,該類初始化實現WebApplicationInitializer接口的PlayWebAppInitializer類(由於這里繼承了AbstractAnnotationConfigDispatcherServletInitializer抽象類)。
在講解PlayWebAppInitializer初始化了兩個bean容器,一種是與DispatcherServlet相關聯的MVC框架直接關系的bean,如:Controller,Service,Repository等等。再說另外一種bean容器前先回憶下,還記得ContextLoaderListener吧,做SSH框架整合時在web.xml中要配置這個類,所以說這個容器是配置更通用一些的bean。 那么問題來了:為什么要有兩個共存呢?----答:我猜想是方便分離,如果不想使用SpringMVC而實用其他MVC框架的可以把DispatcherServlet相關的那個bean容器拿掉。(純屬意淫,歡迎拍磚)。
這里WebConfig用來負責DispacherServlet相關bean的配置,RootConfig用來負責ContextLoaderListener相關bean的配置。
下面截取一段《Spring in Action 4th》中關於兩個ApplicationContext的原話,在135頁:
A TALE OF TWO APPLICATION CONTEXTS
When DispatcherServlet starts up, it creates a Spring application context and starts loading it with beans declared in the configuration files or classes that it’s given. With the getServletConfigClasses() method in listing 5.1, you’ve asked that Dispatcher- Servlet load its application context with beans defined in the WebConfig configura- tion class (using Java configuration). But in Spring web applications, there’s often another application context. This other application context is created by ContextLoaderListener. Whereas DispatcherServlet is expected to load beans containing web components such as controllers, view resolvers, and handler mappings, ContextLoaderListener is expected to load the other beans in your application. These beans are typically the middle-tier and data-tier components that drive the back end of the application. 136 CHAPTER 5 Building Spring web applications Under the covers, AbstractAnnotationConfigDispatcherServletInitializer cre- ates both a DispatcherServlet and a ContextLoaderListener. The @Configuration classes returned from getServletConfigClasses() will define beans for Dispatcher- Servlet’s application context. Meanwhile, the @Configuration class’s returned get- RootConfigClasses() will be used to configure the application context created by ContextLoaderListener. In this case, your root configuration is defined in RootConfig, whereas Dispatcher- Servlet’s configuration is declared in WebConfig. You’ll see what those two configura- tion classes look like in a moment.
上實踐的代碼: com.bob.playspring.PlayWebAppInitializer
package com.bob.playspring; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * 初始化DispatherServlet,代替在web.xml中到DispatherServlet配置, * @author bob * */ public class PlayWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebConfig.class }; } /** * identifies one or more paths that DispatcherServlet will be mapped to.<br> * In this case, it’s mapped to /, indicating that it will be the application’s default servlet.<br> * It will handle all requests coming into the application. */ @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
com.bob.playspring.WebConfig
package com.bob.playspring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** * 系統配置 * @author bob * */ @EnableWebMvc @Configuration @ComponentScan("com.bob") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setExposeContextBeansAsAttributes(true); return resolver; } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
com.bob.playspring.RootConfig
package com.bob.playspring; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @ComponentScan(basePackages = { "com.bob" }, excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) }) public class RootConfig { }
關於Controller,Service,Repository的代碼我就不貼了。