Spring @MVC configuration without XML
2015-06-06 00:00
381 查看
XML is no longer hip. Actually, there is nothing as unhip as last year’s hip. That is until it becomes hip again 30 years later in failed irony.
Honestly, if you’ve been programming Java EE since the 90s, you know full well how error prone XML config files can be. A glance at an EJB XML config file – especially the CMP relationship config from version 2 – would make any sane person run screaming into
the night. Tools were supposed to help, but they really didn’t.
Even the Spring Framework, a music major’s wildly successful solution to Java EE’s problems, has been inundated by XML config files. Until now.
Let’s see how we can configure a Spring @MVC web app with no XML.
Starting with the Servlet 3.0 specification, we can do away with the venerable WEB-INF/web.xml configuration file. In order to do this you must do the following:
Write a class that implements
Create a file named META-INF/services/javax.servlet.ServletContainerInitializer which contains the fully qualified name of your implementation.
Beginning with release 3.1, Spring provides an implementation of the ServletContainerInitializer interface aptly named SpringServletContainerInitializer.
Take a peek inside spring-web-[version 3.1 and above].jar and you’ll see the META-INF/services file mentioned above.
The SpringServletContainerInitializer class delegates to an implementation of
org.springframework.web.WebApplicationInitializer that
you provide. There is just one method that you need to implement: WebApplicationInitializer#onStartup(ServletContext). You are handed the ServletContext that you need to initialize.
The RootConfig Java class we specified in the previous example needs to use the @Configuration annotation. Essentially this class corresponds to the <beans> element in Spring XML config files. The <bean> elements are now methods with the @Bean annotation that
return a bean instance. The <context:component-scan> element is now the class level annotation @ComponentScan.
XML namespaces are replaced by class level annotations that begin with @Enable.
@EnableWebMvc
@EnableAsync
@EnableScheduling
@EnableLoadTimeWeaving
@EnableTransactionManagement
Right now we configure MVC using the mvc: XML namespace, for example: <mvc:annotation:driven/>. The @EnableWebMvc annotation is the replacement.
Write a configuration class that contains the @EnableWebMvc annotation, which is defined byDelegatingWebMvcConfiguration.
In addition, you will probably do a component scan for controllers here.
To customize the defaults, implement WebMvcConfigurer or
extend WebMvcConfigurerAdapter.
Any overridden method that does not return NULL will use that value instead of the default.
Github project
Spring MVC
Spring
MVC config
Spring
Java-based container configuration
Tomcat 7 mapping bug
Servlet 3.0 Specification
Beams’ 3.1 presentation
Honestly, if you’ve been programming Java EE since the 90s, you know full well how error prone XML config files can be. A glance at an EJB XML config file – especially the CMP relationship config from version 2 – would make any sane person run screaming into
the night. Tools were supposed to help, but they really didn’t.
Even the Spring Framework, a music major’s wildly successful solution to Java EE’s problems, has been inundated by XML config files. Until now.
Let’s see how we can configure a Spring @MVC web app with no XML.
Java EE update
Starting with the Servlet 3.0 specification, we can do away with the venerable WEB-INF/web.xml configuration file. In order to do this you must do the following:Write a class that implements
javax.servlet.ServletContainerInitializer
Create a file named META-INF/services/javax.servlet.ServletContainerInitializer which contains the fully qualified name of your implementation.
Spring
Beginning with release 3.1, Spring provides an implementation of the ServletContainerInitializer interface aptly named SpringServletContainerInitializer.Take a peek inside spring-web-[version 3.1 and above].jar and you’ll see the META-INF/services file mentioned above.
The SpringServletContainerInitializer class delegates to an implementation of
org.springframework.web.WebApplicationInitializer that
you provide. There is just one method that you need to implement: WebApplicationInitializer#onStartup(ServletContext). You are handed the ServletContext that you need to initialize.
12345678910111213 | public class WebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) { WebApplicationContext appContext = set up the context ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } } |
Setting up the app contexts
Since we are avoiding writing XML config files, I suggest that instead of using the XmlWebApplicationContext class, use the AnnotationConfigWebApplicationContext which supports classpath scanning for Spring annotation based configuration. You can explicitly add configuration classes, or have the context scan for them.To start up and shut down the context, we add a ContextLoaderListener.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | @Override public void onStartup(ServletContext servletContext) throws ServletException { // Create the root appcontext AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(RootConfig.class); // since we registered RootConfig instead of passing it to the constructor rootContext.refresh(); // Manage the lifecycle of the root appcontext servletContext.addListener(new ContextLoaderListener(rootContext)); servletContext.setInitParameter("defaultHtmlEscape", "true"); // now the config for the Dispatcher servlet AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext(); mvcContext.register(WebMvcConfig.class); // The main Spring MVC servlet. ServletRegistration.Dynamic appServlet = servletContext.addServlet( "appServlet", new DispatcherServlet(mvcContext)); appServlet.setLoadOnStartup(1); Set<String> mappingConflicts = appServlet.addMapping("/"); if (!mappingConflicts.isEmpty()) { for (String s : mappingConflicts) { logger.error("Mapping conflict: " + s); } throw new IllegalStateException( "'appServlet' cannot be mapped to '/' under Tomcat versions <= 7.0.14"); } } |
Java config files
The RootConfig Java class we specified in the previous example needs to use the @Configuration annotation. Essentially this class corresponds to the <beans> element in Spring XML config files. The <bean> elements are now methods with the @Bean annotation thatreturn a bean instance. The <context:component-scan> element is now the class level annotation @ComponentScan.
12345678910 | @Configuration@ComponentScan(basePackages = { "com.rockhoppertech.mvc.service", "com.rockhoppertech.mvc.repositories.internal" })public class RootConfig { @Bean public SomeClass someClass() { return someInstance; } } |
Filters
You can also create any Servlet Filters here. Here are a few Spring provided Filters.In this example I set up the CharacterEncodingFilter.1 2 3 4 5 6 7 8 9 10 11 12 13 | @Override public void onStartup(ServletContext servletContext) throws ServletException { ... FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", new CharacterEncodingFilter()); fr.setInitParameter("encoding", "UTF-8"); fr.setInitParameter("forceEncoding", "true"); fr.addMappingForUrlPatterns(null, true, "/*"); ... } |
@Enable*
XML namespaces are replaced by class level annotations that begin with @Enable.@EnableWebMvc
@EnableAsync
@EnableScheduling
@EnableLoadTimeWeaving
@EnableTransactionManagement
Right now we configure MVC using the mvc: XML namespace, for example: <mvc:annotation:driven/>. The @EnableWebMvc annotation is the replacement.
Spring MVC configuration
Write a configuration class that contains the @EnableWebMvc annotation, which is defined byDelegatingWebMvcConfiguration.In addition, you will probably do a component scan for controllers here.
To customize the defaults, implement WebMvcConfigurer or
extend WebMvcConfigurerAdapter.
Any overridden method that does not return NULL will use that value instead of the default.
1 2 3 4 5 6 7 8 | @Configuration @EnableWebMvc // scan for controllers @ComponentScan(basePackages = { "com.rockhoppertech.mvc.web" }) public class WebMvcConfig extends WebMvcConfigurerAdapter { @Bean ViewResolver viewResolver() { ... } @Bean MessageSource messageSource() { ... } etc. |
Resources
Github projectSpring MVC
Spring
MVC config
Spring
Java-based container configuration
Tomcat 7 mapping bug
Servlet 3.0 Specification
Beams’ 3.1 presentation
相关文章推荐
- MD5加密结果在不同的环境下出现不一致
- 【SSH进阶之路】Struts + Spring + Hibernate 进阶开端(一)
- Eclipse配色方案
- SSO单点登陆环境搭建
- java高级工程师需要掌握的技术
- 斐波那契堆(Fibonacci heap)原理详解(附java代码实现)
- 【JAVA基础知识总结】Java自定义异常
- 【JAVA基础教程】java中异常机制总结
- java project 连接hibernate 出错
- [note] java与DB
- Java for LeetCode 168 Excel Sheet Column Title
- Java学习篇之---LinkedList
- Java for LeetCode 166 Fraction to Recurring Decimal
- java.lang.IllegalArgumentException: Illegal character in scheme at index 0
- java相关知识介绍
- 史上最全最强SpringMVC详细示例实战教程
- Spring4 Jar包详解
- 迭代器(Iterator)的java.util.NoSuchElementException错误的改正
- Java学习篇之---Collection接口
- 一个Java编写的小玩意儿---多人在线聊天工具