spring-mvc注解方式加载配置
一、web.xml方式
1.web.xml配置内容
spring使用3.2.4版本
如下为配置的web.xml文件
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.springsource.cloudfoundry.mvc.services.config.ServicesConfiguration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<servlet-name>appServlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.springsource.cloudfoundry.mvc.web.WebMvcConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.spring监听
这个监听是加载非spring-mvc注解的注解配置(如@Controller)
- 启动spring监听
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
-
监听使用的参数:
(1)contextClass:
spring使用的加载配置类(ApplicationContext),这里显式写出使用AnnotationConfigWebApplicationContext注解方式加载配置。如果没有填写默认使用WebApplicationContext
(2)contextConfigLocation:
配置注解类(org.springsource.cloudfoundry.mvc.services.config.ServicesConfiguration),多个类使用","逗号分隔。 如:org.springsource.cloudfoundry.mvc.services.config.ServicesConfiguration1,org.springsource.cloudfoundry.mvc.services.config.ServicesConfiguration2。具体根据实际项目里的配置填写
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.springsource.cloudfoundry.mvc.services.config.ServicesConfiguration</param-value>
</context-param>
如下为源码
/**
* Return the WebApplicationContext implementation class to use, either the
* default XmlWebApplicationContext or a custom context class if specified.
* @param servletContext current servlet context
* @return the WebApplicationContext implementation class to use
* @see #CONTEXT_CLASS_PARAM
* @see org.springframework.web.context.support.XmlWebApplicationContext
*/
protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
}
}
}
3.spring-mvc注解配置
和spring监听相同的参数
contextClass和contextConfigLocation,只是用来注解mvc相关注解。contextConfigLocation有多个文件的话使用","分隔
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.springsource.cloudfoundry.mvc.web.WebMvcConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
4.相关的注解类
WebMvcConfiguration
@Configuration
@EnableWebMvc
@ComponentScan
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setViewClass(JstlView.class);
internalResourceViewResolver.setPrefix("/WEB-INF/views/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
@Bean
public MessageSource messageSource() {
String[] baseNames = "messages".split(",");
ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
resourceBundleMessageSource.setBasenames(baseNames);
return resourceBundleMessageSource;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/web/**").addResourceLocations("/web/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("customers");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
ServicesConfiguration
@Configuration
@PropertySource("/config.properties")
@EnableCaching
@EnableTransactionManagement
@Import({CloudFoundryDataSourceConfiguration.class, LocalDataSourceConfiguration.class})
@ComponentScan(basePackageClasses = {CustomerService.class})
public class ServicesConfiguration {
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) throws Exception {
return new JpaTransactionManager(entityManagerFactory);
}
}
二、纯注解配置
spring使用5.0.4.RELEASE版本
通过继承AbstractAnnotationConfigDispatcherServletInitializer来实现,继承这个类在容器初始化是会被检测调用。
MvcShowcaseAppInitializer
/**
- Initialize the Servlet container. This class is detected by the Servlet
- container on startup.
*/
public class MvcShowcaseAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new DelegatingFilterProxy("csrfFilter") };
}
}
RootConfig
// Root Context: defines shared resources visible to all other web components
@Configuration
public class RootConfig {
```
// CSRF protection. Here we only include the CsrfFilter instead of all of Spring Security.
// See http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf
// for more information on Spring Security's CSRF protection
@Bean
public CsrfFilter csrfFilter() {
return new CsrfFilter(new HttpSessionCsrfTokenRepository());
}
// Provides automatic CSRF token inclusion when using Spring MVC Form tags or Thymeleaf.
// See http://localhost:8080/#forms and form.jsp for examples
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return new CsrfRequestDataValueProcessor();
}
```
}
WebMvcConfig
// DispatcherServlet context: defines Spring MVC infrastructure
// and web application components
@Configuration
@ComponentScan(basePackages = "org.springframework.samples.mvc")
@EnableWebMvc
@EnableScheduling
public class WebMvcConfig implements WebMvcConfigurer {
```
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatterForFieldAnnotation(new MaskFormatAnnotationFormatterFactory());
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new CustomArgumentResolver());
}
// Handle HTTP GET requests for /resources/** by efficiently serving
// static resources under ${webappRoot}/resources/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper pathHelper = new UrlPathHelper();
pathHelper.setRemoveSemicolonContent(false); // For @MatrixVariable's
configurer.setUrlPathHelper(pathHelper);
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(3000);
configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor());
}
@Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
```
}
为什么AbstractAnnotationConfigDispatcherServletInitializer就会被容器加载?因为这个类实现了WebApplicationInitializer接口。SpringServletContainerInitializer中实现了ServletContainerInitializer接口,并使用@HandlesTypes,在容器初始化时就会加载实现WebApplicationInitializer接口的类
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {