springmvc基于java config的实现

参考资料:servlet-3_1-final.pdf(servlet 3.1规范)8.2.4Shared libraries / runtimes pluggability
通过ServletContainerInitializer来实现可插拔性,至少需要servlet 3+.


1.以上的参考资料提到可以通过ServletContainerInitializer实现可插拔性.每个应用在启动时,容器都会创建一个ServletContainerInitializer实例.

2.框架提供在jar包的META-INF/service目录下的javax.servlet.ServletContainerInitializer文件内容就是指向ServletContainerInitializer实现类.
spring mvc提供的这个实现类叫做org.springframework.web.SpringServletContainerInitializer,这个jar的文件名是spring-web-X.X.X.X.jar.

3.这个实现类的HandlesTypes注解用在表示那些感兴趣的类,这些类或者它的超类是由HandlesTypes值指定的,HandlesTypes的应用与metadata-complete的设置无关.
spring mvc的HandlesTypes值只有WebApplicationInitializer.class一个,那么凡是在类路径上的WebApplicationInitializer子类都是感兴趣的类.它们将会传入onStartup方法的第一个参数.下面是org.springframework.web.SpringServletContainerInitializer#onStartup方法

public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
		throws ServletException {
	List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
	if (webAppInitializerClasses != null) {
		for (Class<?> waiClass : webAppInitializerClasses) {
			// Be defensive: Some servlet containers provide us with invalid classes,
			// no matter what @HandlesTypes says...
			if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
					WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
				try {
					initializers.add((WebApplicationInitializer) waiClass.newInstance());
				}
				catch (Throwable ex) {
					throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
				}
			}
		}
	}
	if (initializers.isEmpty()) {
		servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
		return;
	}
	AnnotationAwareOrderComparator.sort(initializers);
	servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
	for (WebApplicationInitializer initializer : initializers) {
		initializer.onStartup(servletContext);
	}
}


从此方法可看出,在启动应用时,所有有效(这个有效的意思可以看上面的try外层的if)的Initializer都共用同一个ServletContext,一个一个去启动它的onStartup方法.如果要更改initializers顺序,应该可通过@Order注解(数值越低排序越前 )或实现Ordered接口去实现.

基于java-config的spring mvc,我们一般都会继承AbstractAnnotationConfigDispatcherServletInitializer(它当然是WebApplicationInitializer的实现类)来写一个Initializer.这个Initializer最基本的就帮我们注册了DispatcherServlet.


如果容器不支持servlet3+(有些老古董思想,要绕一下路),那么就离不开web.xml,下面替代方案:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <display-name>web</display-name>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <!-- Configuration locations must consist of one or more comma- or space-delimited
         fully-qualified @Configuration classes. Fully-qualified packages may also be
         specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.xxx.auth.web.config.AppConfig</param-value>
    </context-param>
    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>charsetFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>charsetFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.xxx.auth.web.config.MvcConfig</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>
</web-app>


基于javaConfig的springMvc,不是不使用web.xml,而是可以不使用web.xml,应理解web.xml不是必须的(所以那些所谓的零配置,我认为是不准确的),比如session-config,jsp-config,mime-mapping,error-page还是要使用web.xml,可参考servlet-3_1-final.pdf



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值