spring mvc是当前最流行的web项目框架之一。基于spring mvc。我们可以很快的搭建一个web项目。
(除此之外,springboot 提供了另外一种方式来快速搭建一个包括web项目在内的各种项目,这里先不说明。)
传统的方式需要我们在web.xml配置文件里面配置applicationContext,DispatcherServlet,filter等各种组件来启动spring 容器和mvc组件。spring还提供了另外一个方式。通过这种方式,我们可以无需配置web.xml。全部用java代码来配置。
在Spring-web项目中有类SpringServletContainerInitializer,它实现了Servlet3.0的ServletContainerInitializer接口,且优先级会高于xml中配置的listener。源码
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
*********
}
}
因为这个类声明了HandlesTypes,并指定了类型为WebApplicationInitializer.class,在Servlet3.0+中web容器启动时,会扫描类路径下所有的WebApplicationInitializer接口实现类,并提供一个set集合给onStartup方法执行。
onStartup方法执行时,会遍历该set,并使用newInstance()方式进行实例化,实例化后依据@Order注解进行排序,最后在依次调用onStartup(ServletContext)方法,完成初始化。
WebApplicationInitializer 。源码如下:
public interface WebApplicationInitializer {
/**
* Configure the given {@link ServletContext} with any servlets, filters, listeners
* context-params and attributes necessary for initializing this web application. See
* examples {@linkplain WebApplicationInitializer above}.
* @param servletContext the {@code ServletContext} to initialize
* @throws ServletException if any call against the given {@code ServletContext}
* throws a {@code ServletException}
* @see SpringServletContainerInitializer
* @see org.springframework.web.context.AbstractContextLoaderInitializer
* @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
* @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer
这里我们用AbstractAnnotationConfigDispatcherServletInitializer来示范如何进行code-based.
maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
继承AbstractAnnotationConfigDispatcherServletInitializer
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{ContextConfig.class}; //配置
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Filter[] getServletFilters() {
return new Filter[]{characterEncodingFilter(), corsFilter()};
}
//跨域过滤器添加
private CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration); // 4
return new CorsFilter(source);
}
//编码过滤器添加
private Filter characterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
}
对应的WebConfig处理springmvc的 依赖注入。需要继承WebMvcConfigurerAdapter,并开启@EnableWebMvc注解,在这里配置的跨域需要配合 @CrossOrigin实现。
@EnableWebMvc
@ComponentScan({"com.demo.web"})
public class WebConfig extends WebMvcConfigurerAdapter {
//配置跨域方式
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowCredentials(true)
.allowedOrigins("*");
}
}
ContextConfig的代码如下,配置扫描路径的时候需要将WebConfig排除,否则将注入两次,即spring容器中有两个springmvc组件。该配置中的对象将被整个项目共享,适合处理数据库连接池,缓存池,基础业务服务等这些组件
@Configuration
@PropertySources(@PropertySource({"classpath:config/application.properties"}))
@ImportResource({"classpath:applicationContext.xml"})
@ComponentScan(value = {"com.demo"},
excludeFilters = {@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class),
@Filter(type = FilterType.REGEX, pattern = {"com.demo.web.*"})})
public class ContextConfig {
}
通过以上配置可以实现无web.xml配置的,甚至无applicationContext.xml的spring mvc项目。