利用JavaConfig配置Spring及SpringMvc的开发环境

来源:互联网 发布:淘宝发短信给客户 编辑:程序博客网 时间:2024/06/09 21:31

记录自己的学习总结--关于o配置web.xml

1.导Spring相关的包,略。

2.由于要全使用JavaConfig来配置,所以必须是servlet3.0及以上才可以。

3.servlet容器(如tomcat)启动的时候会去调用ServletContainerInitializer接口(见servlet3.0api),而Spring的SpringServletContainerInitializer类就是这个接口的实现;

下面是源码:

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

@Override
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);
}
}

}

从源码可以看出;

Spring实现了ServletContainerInitializer的onStartup(Set<Class<?>> c, ServletContext ctx)方法,并引入了自己的另一个接口WebApplicationInitializer (上述代码的最后就是调用WebApplicationInitializer 的onStartup()方法);

4.下面来看WebApplicationInitializer 接口;

public interface WebApplicationInitializer {

void onStartup(ServletContext servletContext) throws ServletException;
}

接口中只有一个onStartup()方法;

5.WebApplicationInitializer 实现类

public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer

public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer

public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer

5.1我们来看一下上述抽象类对应的源码:

public abstract class AbstractContextLoaderInitializer implements WebApplicationInitializer {

//实现接口的onStartup()方法
@Override
public void onStartup(ServletContext servletContext) throws ServletException {

//调用下面的方法
registerContextLoaderListener(servletContext);
}
//将SpringRoot容器上下文的监听器注册到servlet上下文中
protected void registerContextLoaderListener(ServletContext servletContext) {

//调用下面的创建SpringRoot容器
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
}
else {
logger.debug("No ContextLoaderListener registered, as " +
"createRootApplicationContext() did not return an application context");
}
}
//创建Spring容器方法
protected abstract WebApplicationContext createRootApplicationContext();

protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
return null;
}
}

5.2 

//这个类主要的作用就是将DispatcherServlet注册到ServletContext 中

public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
}

protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return empty or null");

WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext,
"createServletApplicationContext() did not return an application " +
"context for servlet [" + servletName + "]");

FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());

ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
Assert.notNull(registration,
"Failed to register servlet with name '" + servletName + "'." +
"Check if there is another servlet registered under the same name.");

registration.setLoadOnStartup(1);
registration.addMapping(getServletMappings());
registration.setAsyncSupported(isAsyncSupported());

Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
for (Filter filter : filters) {
registerServletFilter(servletContext, filter);
}
}

//将注册的dispatcherServlet的动态servlet传递出来,方便扩展修改
customizeRegistration(registration);
}

protected String getServletName() {
return DEFAULT_SERVLET_NAME;
}
//自己创建mvc容器方法
protected abstract WebApplicationContext createServletApplicationContext();

protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
return new DispatcherServlet(servletAppContext);
}

protected ApplicationContextInitializer<?>[] getServletApplicationContextInitializers() {
return null;
}

protected abstract String[] getServletMappings();

protected Filter[] getServletFilters() {
return null;
}

protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
String filterName = Conventions.getVariableName(filter);
Dynamic registration = servletContext.addFilter(filterName, filter);
if (registration == null) {
int counter = -1;
while (counter == -1 || registration == null) {
counter++;
registration = servletContext.addFilter(filterName + "#" + counter, filter);
Assert.isTrue(counter < 100,
"Failed to register filter '" + filter + "'." +
"Could the same Filter instance have been registered already?");
}
}
registration.setAsyncSupported(isAsyncSupported());

registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName());
return registration;
}

private EnumSet<DispatcherType> getDispatcherTypes() {
return (isAsyncSupported() ?
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC) :
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
}

protected boolean isAsyncSupported() {
return true;
}

protected void customizeRegistration(ServletRegistration.Dynamic registration) {
}


}

5.3

public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer {

//重写创建Spring容器方法(5.1中的)
@Override
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}

//重写创建mvc容器方法(5.2中的)
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}

//得到Spring的配置类
protected abstract Class<?>[] getRootConfigClasses();

//得到Springmvc的配置类
protected abstract Class<?>[] getServletConfigClasses();

}

6.所以我们采用JavaConfig的方式类配置Spring的话有两种:要么继承AbstractAnnotationConfigDispatcherServletInitializer 抽象类,要么实现WebApplicationInitializer接口

public class CoreWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{

@Override
protected Class<?>[] getRootConfigClasses() {
//引入Spring的配置类
return new Class<?>[]{SpringConfig.class};
}
@Override
protected Filter[] getServletFilters() {
//定义字符过滤器
return new Filter[]{new CharacterEncodingFilter("utf-8", true)};
}
@Override
protected void customizeRegistration(Dynamic registration) {
// 扩展修改默认实现的DispatcherServlet
super.customizeRegistration(registration);
}
@Override
protected Class<?>[] getServletConfigClasses() {
//引入Springmvc的配置类
return new Class<?>[] {SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
// 默认DispatcherServlet的映射,拦截所有请求
return new String[]{"/"};
}

}

/**
 * Spring容器配置
 * @author admin
 */
@Configuration
@ComponentScan(basePackages={"com.tete.dao","com.tete.service","com.tete.config"})
@EnableAsync
public class SpringConfig {

}

/**
 * springMvc容器的配置
 * @author admin
 */
@Configuration
@ComponentScan(basePackages="com.tete.controller")
@EnableWebMvc
public class SpringMvcConfig {

//配置视图解析器
@Bean
public InternalResourceViewResolver jspViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".jsp");
return resolver;
}
}

通过继承AbstractAnnotationConfigDispatcherServletInitializer类实现就完成了。

关于实现WebApplicationInitializer接口,就是实现他的onStartup()方法

......


原创粉丝点击