Spring MVC全註解配置 - 無web.xml

Serlvet 3以後,我們可以使用註解來配置Servlet,對於像Spring這類的框架來說是一個很好的適應。Spring也對此特性加入了很多的新功能。本文就將簡單的對之前的xml配置轉換爲java代碼的配置。代碼配置讓程序員們覺得更加具有流程化,不像配置很多代碼程序員們都不願意look into。


接下來,進行替換我們之前的web.xmlspring-mvc.xml的配置。也就是在你的web工程裏面看不到這兩個配置文件了。(可能有的童鞋會說,這樣配置可能對以後的修改不方便,無法達到只修改配置文件就切換某些環境。其實不是,零配置文件只是修改了類定義的配置,並沒有修改之前配置文件的靈活性。我想無論誰也不會在之前的web.xml中去修改某個servlet的配置吧。況且這些所謂的配置文件靈活性,只是針對某個值,我們可以寫在我們的properties文件裏面,而且Spring對這類配置文件有很好的支持,而且使用很方便,有興趣的童鞋可以去search一下。所以請打消這個配置不靈活的念頭)。


切入正題,首先我們要替換web.xml。在Spring MVC中配置DispatchServlet,該類是 Spring MVC的核心類(該類具體作用請參考Spring MVC相關文檔)。也就是在容器啓動的時候就要初始化該類,並且配置相應的參數。

之前我們的web.xml中對DispatchServlet的配置如下:

<servlet>
   <servlet-name>dispatcher</servlet-name>
   <servlet-class>
     org.springframework.web.servlet.DispatcherServlet
   </servlet-class>
   <init-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>


Servlet3 以後,支持動態的添加Servlet配置,請參考ServletContext.addServlet方法。因此我們可以使用Spring MVC提供的AbstractDispatcherServletInitializer類。該類是的類關係是AbstractDispatcherServletInitializer -> WebApplicationInitializer,(點擊查看WebApplicationInitializer詳解)AbstractDispatcherServletInitializer中重寫onStartup方法,調用ServletContext.addServlet來實現註冊該servlet。通過查看AbstractDispatcherServletInitializer源碼,發現只需用重寫他的三個方法既可以完成對DispatchServlet的註冊。詳細請看示例代碼:

public class WebInitialConfiguration extends
		AbstractDispatcherServletInitializer {

	@Override
	protected WebApplicationContext createServletApplicationContext() {
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		// scan the class under the demo.config package with @Configuration annotation 
		// You can add it by manually such as:
		// context.register(Class<?>... annotatedClasses) -> context.register(WebMVCConfiguration.class, AppConfig.class, ....)
		// This configuration like:
		// <init-param>
	    // 		<param-name>contextConfigLocation</param-name>
	    // 		<param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
	    // </init-param>
	    // all the configuration classes are in the same package, so use the getClass() method to get the package. Here the package name is com.sample.config
		context.scan(ClassUtils.getPackageName(getClass()));
		return context;
	}

	@Override
	protected String[] getServletMappings() {
		// Set the URL mapping
		return new String[] { "/" };
	}

	@Override
	protected WebApplicationContext createRootApplicationContext() {
		return null;
	}
}


細心的童鞋可以查看一下AbstractDispatcherServletInitializer的源碼,會發現在代碼中調用了ContextServlet.addServlet方法的:

DispatcherServlet dispatcherServlet = new DispatcherServlet(servletAppContext);
		ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);


這時我們啓動servlet3容器(本文使用tomcat7), 你會看到如下啓動信息:

INFO: Initializing Spring FrameworkServlet 'dispatcher'
INFO: FrameworkServlet 'dispatcher': initialization started
Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
INFO: FrameworkServlet 'dispatcher': initialization completed in 843 ms



接下,替換spring-mvc.xml,在該配置中,我們只需用去配置很少幾部分就可以藉助Spring提供的接口完成對所有controller的註冊和對視圖解析的配置。

xml配置如下:

<context:component-scan base-package="com.sample.controller"/>
<context:annotation-config/>
<!-- This tag registers the DefaultAnnotationHandlerMapping and
         AnnotationMethodHandlerAdapter beans that are required for Spring MVC  -->
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     <propertyname="prefix"value="/WEB-INF/pages/"/>
     <propertyname="suffix"value=".jsp"/>
</bean>
 
<!-- This tag allows for mapping the DispatcherServlet to "/" -->
<mvc:default-servlet-handler/>


首先,在Spring MVC中,我們可以使用@Configuration來進行Spring的配置,我們剛纔也有需要去掃描這一類的配置類。接下來就是需要開啓Spring MVC的具體配置。使用@EnableWebMvc,該註解等同於<mvc:annotation-driven/>,該標籤具體的意思請看xml配置中對該標籤的解釋。


接下來我們要去掃描我們的controller,即有@Controller的類。因此我們使用@ComponentScan進行掃描,該註解等同於<context:componet-scan>。


Spring MVC需要對視圖的解析進行一次定義,因此我們需要在該類中實例化一個ResourceViewResolver,該類的定義視具體需要而定。


具體的代碼如下:


@Configuration
// <mvc:annotation-driven/>
@EnableWebMvc
@ComponentScan(basePackages={"com.sample.controller"})
public class WebMVCConfiguration extends WebMvcConfigurerAdapter {

	// equals: <mvc:default-servlet-handler/>
	@Override
	public void configureDefaultServletHandling(
			DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}

	// add the resolver
	@Bean
	public InternalResourceViewResolver internalResourceViewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/pages/");
		resolver.setSuffix(".jsp");
		return resolver;
	}
}


此時我們添加我們的controller到com.sample.controller包下,然後定義我們的requestmapping,再次啓動server,你會看到會增加之前檢測到的controller的信息。

INFO: Mapped "{[/test],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.sample.controller.TestController.test()


至此,簡單的替換已經完成,更多的功能會在後續的文章中繼續加入,如:spring-security, thymeleaf(一個很不錯的視圖框架)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章