参考:http://blog.csdn.net/greensurfer/article/details/19296247 例子,并做调试,补充调试中的要点:
在restful-test项目中,我们用到thymeleaf框架,所以配置方面稍稍复杂。
1. pom.xml, 注意json数据响应页面成功,保证添加两个依赖包:jackson-core-asl-*.jar,jackson-mapper-asl-*.jar
<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.springframework.samples.service.service</groupId> <artifactId>restful-test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <jetty.version>7.6.8.v20121106</jetty.version> <!-- Generic properties --> <java.version>1.6</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Web --> <jsp.version>2.2</jsp.version> <jstl.version>1.2</jstl.version> <servlet.version>2.5</servlet.version> <!-- Spring --> <spring-framework.version>3.2.8.RELEASE</spring-framework.version> <!-- Hibernate / JPA --> <hibernate.version>4.2.1.Final</hibernate.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> <sitemesh.version>2.4.2</sitemesh.version> <!-- Test --> <junit.version>4.11</junit.version> <!-- json --> <jackson.version>1.9.13</jackson.version> </properties> <dependencies> <!-- Spring MVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Other Web dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring3</artifactId> <version>2.0.5</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.9</version> </dependency> <dependency> <groupId>opensymphony</groupId> <artifactId>sitemesh</artifactId> <version>${sitemesh.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.1</version> </dependency> <!-- fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> <!-- Hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Test Artifacts --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring-framework.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- jetty --> <dependency> <groupId>org.eclipse.jetty.aggregate</groupId> <artifactId>jetty-webapp</artifactId> <version>${jetty.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jsp</artifactId> <version>${jetty.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- jetty插件, 设定context path与spring profile --> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>${jetty.version}</version> <configuration> <systemProperties> <systemProperty> <name>spring.profiles.active</name> <value>development</value> </systemProperty> </systemProperties> <useTestClasspath>true</useTestClasspath> <webAppConfig> <contextPath>/${project.artifactId}</contextPath> </webAppConfig> </configuration> </plugin> </plugins> </build> </project>
2. web.xml
注意:为了支持HTTP PUT and PATCH请求,需要添加过滤器HttpPutFormContentFilter
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>restful-test</display-name> <!-- 上下文侦听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:/application-config.xml </param-value> </context-param> <!-- UTF-8 编码过滤 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>springServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- To support HTTP PUT and PATCH requests, the spring-web module provides the filter HttpPutFormContentFilter --> <filter> <filter-name>httpPutFormFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>httpPutFormFilter</filter-name> <servlet-name>springServlet</servlet-name> </filter-mapping> <display-name>UikitTest</display-name> <welcome-file-list> <welcome-file>/WEB-INF/views/rest.jsp</welcome-file> </welcome-file-list> </web-app>
参考: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html 中
Working with "application/x-www-form-urlencoded" data 一段
3. mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 自动扫描且只扫描@Controller --> <context:component-scan base-package="com.kakaka.restful.web.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!-- 将StringHttpMessageCOnverter的默认编码设为UTF-8 --> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8" /> </bean> </mvc:message-converters> </mvc:annotation-driven> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 以字节为单位的最大上传文件的大小 --> <property name="maxUploadSize" value="1000000" /> </bean> <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"> <property name="characterEncoding" value="UTF-8" /> <property name="prefix" value="/WEB-INF/" /> <property name="suffix" value=".html" /> <property name="templateMode" value="HTML5" /> <!-- Template cache is set to false (default is true). --> <property name="cacheable" value="false" /> </bean> <bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver" /> </bean> <!-- - The ContentNegotiatingViewResolver delegates to the InternalResourceViewResolver and BeanNameViewResolver, - and uses the requested media type (determined by the path extension) to pick a matching view. - When the media type is 'text/html', it will delegate to the InternalResourceViewResolver's JstlView, - otherwise to the BeanNameViewResolver. --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="contentNegotiationManager" ref="cnManager" /> <property name="viewResolvers"> <list> <!-- Used here for 'xml' and 'atom' views --> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="3" /> </bean> <bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine" /> <property name="characterEncoding" value="UTF-8" /> <property name="order" value="2" /> <property name="viewNames" value="thymeleaf/**" /> </bean> <!-- Default viewClass: JSTL view (JSP with html output) --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- Example: a logical view name of 'vets' is mapped to '/WEB-INF/jsp/vets.jsp' --> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> <property name="order" value="1" /> </bean> </list> </property> </bean> <!-- Simple strategy: only path extension is taken into account --> <bean id="cnManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="true" /> <property name="ignoreAcceptHeader" value="true" /> <property name="defaultContentType" value="text/html" /> <property name="mediaTypes"> <map> <entry key="html" value="text/html" /> <entry key="xml" value="application/xml" /> <entry key="json" value="application/json" /> <entry key="atom" value="application/atom+xml" /> </map> </property> </bean> <!-- 容器默认的DefaultServletHandler处理 所有静态内容与无RequestMapping处理的URL --> <mvc:default-servlet-handler /> <!-- 定义无需Controller的url<->view直接映射 --> <!-- <mvc:view-controller path="/" view-name="redirect:login/success" /> --> <!-- 将Controller抛出的异常转到特定View,保持SiteMesh的装饰效果 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.Throwable">error/500</prop> </props> </property> </bean> </beans>