原文地址:http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/
这是使用Spring3.1创建RESTfull web应用系列文章的第一篇。这篇文章我们主要介绍启动一个web应用,并讨论怎样从XML转到Java而完全不需要使用XML配置文件。
Spring REST系列文章包括:
part 2-使用Spring3.1和基于Java的配置创建一个RESTful web service
part 3-使用Spring Security3.1创建安全的RESTful web service
part 4-RESTful web service的创新性
part 5-Spring REST Service的创新性
The mavne pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org</groupId> <artifactId>rest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>${cglib.version}</version> <scope>runtime</scope> </dependency> </dependencies> <build> <finalName>rest</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> <properties> <spring.version>3.1.0.RELEASE</spring.version> <cglib.version>2.2.2</cglib.version> </properties> </project>
如果使用Spring3.2 milestones(目前还没有),需要增加下面的maven repository到pom.xml中
<repository> <id>org.springframework.maven.milestone</id> <name>Maven Central Compatible Spring Milestone Repository</name> <url>http://maven.springframework.org/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository>
cglib依赖的理由
你想知道为什么需要cglib依赖-结果是有一个合理的理由包含这个依赖-如果不包含cglib依赖整个配置文件不会生效。如果去掉这个依赖,Spring会抛出:
抛出这个错误的原因是Spring处理@Configuration注解类的方式。这些类是一些有效地beans,正因为如此,他们需要上下文和生命周期以及其它的bean语义,这些可通过为每一个@Configuration动态创建一个cglib代理来获得,因此cglib不可缺少。
另外,也正因为如此,configuration注解类有一些限制:
基于Java的web配置:
@Configuration @ImportResource( { "classpath*:/rest_config.xml" } ) @ComponentScan( basePackages = "org.rest" ) public class AppConfig{ @Bean public static PropertyPlaceholderConfigurer properties(){ PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); final Resource[] resources = new ClassPathResource[ ] { new ClassPathResource( "persistence.properties" ), new ClassPathResource( "restfull.properties" ) }; ppc.setLocations( resources ); ppc.setIgnoreUnresolvablePlaceholders( true ); return ppc; } }
首先,@Configuration注解-基于java的Spring配置使用的主要构件;它自身是@Component注解的元注解,让带注解的类成为一个标准的bean,也支持组件扫描。@Configuration类的主要目的是成为Spring IoC容器注入定义备案的来源。更多的细节描述,请参考官方文档。
然后,@ImportResource注解用于导入已存在的基于XML的Spring配置文件。这个注解可以把XML配置文件迁移到Java,或者只要你愿意可以简化遗留的配置文件。总之,把它导入到容器,对成功迁移来说是非常重要的,只需小的代价,而且不必冒风险。可以用下面的XML来代替注解:
<import resource=”classpath*:/rest_config.xml” />
再看看@ComponentScan-这个配置组件扫描指令,可以用下面的XML代替:
<context:component-scan base-package=”org.rest” />
自Spring3.1 RC2版本起,@Configuration注解默认是排除路径扫描的——可以参考 this JIRA issue 。在Spring3.1之前,这些被排除的类应该显示地指明:
excludeFilters = { @ComponentScan.Filter( Configuration.class ) }
带Configuration注解的类不应该被自动发现,因为他们已经被指定,并且被容器使用——允许他们被发现和被Spring上下文引入将会导致下面错误:
最后使用@Bean注解来配置properties支持——PropertyPlaceholderConfigurer通过@Bean的注解方法来初始化,指明她讲产生一个Spring容器管理的bean。这个新注解
可以用下面的XML代替:
<context:property-placeholder location=”classpath:persistence.properties, classpath:restfull.properties” ignore-unresolvable=”true”/>
web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>rest</display-name> <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.rest.spring.root</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>rest</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.rest.spring.rest</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rest</servlet-name> <url-pattern>/api/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file /> </welcome-file-list> </web-app>
首先,root上下文定义和配置使用AnnotationConfigWebApplicationContext来代替默认的XmlWebApplicationContext。这个新的AnnotationConfigWebApplicationContext接受
@Configuration注解的类作为容器配置文件的输入并且是设置基于java的上下文必不可少的。
不像XmlWebApplicationContext,她假设没有默认的配置文件类的位置,因此servlet必须要设置contextConfigLocation,它指出@Configuration注解类所在Java包的位置,也支持这个类的全名。
接下来,配置使用同样的方式配置DispatcherServlet ,唯一不同的地方是加载配置文件的类时不同的Java包。
除此之外,web.xml不是真正的从XML转到了基于Java的配置。
结论
已提出的方法允许Spring配置文件从XML到Java的顺利迁移,混合旧的和新的方法。有很多旧的基于XML配置的工程不能一次全部迁移,这对于旧工程来说非常重要。
web.xml和启动web应用是迁移的第一步,余下的XML beans将逐步介绍。
在 part2部分,我将涉及Spring MVC配置,HTTP状态码得配置,负荷组装和内容协商。同时,你可以从github project 检出工程。