摘要:
“約定優於配置”這是一個相當棒的經驗,
SOAP服務性能差、基於配置、緊耦合,
restful服務性能好、基於約定、松耦合,現在我就把使用Spring MVC發布restful服務的過程同大家分享
。代碼之優雅、過程之簡單、編碼之愉快,不是發布SOAP服務所能匹敵的。
關鍵字:java, rest, webservice
, spring mvc
前提:IntelliJ IDEA (
13.1.5 版本),
apache maven
(
3.2.3 版本),
Tomcat(7.0.56版本), Spring(3.2.4版本)
“約定優於配置”這是一個相當棒的經驗,對於我來說,恐怕是自“面向對象”以來對我最大沖擊的理念了吧。首先,SOAP服務可以說是基於配置的,它在HTTP的基礎上使用XML配置表達服務與數據,為了實現遠程訪問,它生成的服務信息尤其復雜,無論是C#客戶端還是JAVA客戶端,甚至可以通過WSDL服務描述來自動生成一整套代碼,這樣基於配置的服務的缺點就在於服務端與客戶端有着較強的編碼耦合性,服務端接口修改后,需要對客戶端的服務依賴代碼重新生成。而restful服務是基於約定的,是http的get、delete、post還是put都約定好了不同的含義,我們依照約定來進行http請求便可以實現各式的操作。更不用說SOAP服務的性能之差、與restful服務不是一個數量級之缺點了。基於約定,我們可以實現代碼間的松耦合。雖然Hessian性能略優於restful服務、其實是一個數量級、restful編解碼做好了就
性能
差不多,但Hessian也還是基於代碼的緊耦合了。
首先,我們先在IDEA中新建一個名為dp-parent的Project,作為所有工程的父節點,其<packaging>pom</packaging>。然后,我們在
dp-parent下新建一個名為dp-restfulservice的Module,其
<packaging>war</packaging>,並在其pom.xml中添加其所需的spring依賴。如:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version> 3 . 2 . 4 .RELEASE</version>
</dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version> 3 . 2 . 4 .RELEASE</version>
</dependency>
其次,
我們在src/main目錄下創建名為webapp的目錄,為什么要叫這個名字呢?
這其實也是一個約定。並且,我們在webapp目錄下創建名為WEB-INF的目錄(
為什么要叫這個名字呢?
這其實也是一個約定
)。在
WEB-INF目錄下創建名為web.xml的文件
(
為什么要叫這個名字呢?
這其實也是一個約定,這句話我說了太多遍了,
“約定優於配置”此理念真是百試不爽
)。下面是web.xml的主要內容。
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<web-app xmlns= "http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version= "3.1" >
<servlet>
<servlet- name >restful</servlet- name >
<servlet- class >org.springframework.web.servlet.DispatcherServlet</servlet- class >
<load-on-startup> 1 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet- name >restful</servlet- name >
< url -pattern>/</ url -pattern>
</servlet-mapping>
</web-app>
<web-app xmlns= "http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version= "3.1" >
<servlet>
<servlet- name >restful</servlet- name >
<servlet- class >org.springframework.web.servlet.DispatcherServlet</servlet- class >
<load-on-startup> 1 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet- name >restful</servlet- name >
< url -pattern>/</ url -pattern>
</servlet-mapping>
</web-app>
然后,我們要在
WEB-INF目錄下創建一個名為restful-servlet.xml的文件
(
為什么要叫這個名字呢?
這其實也是一個約定,在web.xml中規定的servlet-name加上-servlet約定為servlet配置文件名
)。
restful-servlet.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:context= "http://www.springframework.org/schema/context"
xmlns:mvc= "http://www.springframework.org/schema/mvc"
xsi:schemaLocation= "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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" >
<context:component-scan base -package= "com.jsc.dp.controllers" ></context:component-scan>
<mvc:resources mapping= "/resources/**" location= "/WEB-INF/resources/" ></mvc:resources>
<mvc:annotation-driven/>
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name = "prefix" value = "/WEB-INF/views/" />
<property name = "suffix" value = ".jsp" />
<!-- 如果 .jsp 文件中含有 jstl,需要這一行 -->
<property name = "viewClass" value = "org.springframework.web.servlet.view.JstlView" />
</bean>
</beans>
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context= "http://www.springframework.org/schema/context"
xmlns:mvc= "http://www.springframework.org/schema/mvc"
xsi:schemaLocation= "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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" >
<context:component-scan base -package= "com.jsc.dp.controllers" ></context:component-scan>
<mvc:resources mapping= "/resources/**" location= "/WEB-INF/resources/" ></mvc:resources>
<mvc:annotation-driven/>
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name = "prefix" value = "/WEB-INF/views/" />
<property name = "suffix" value = ".jsp" />
<!-- 如果 .jsp 文件中含有 jstl,需要這一行 -->
<property name = "viewClass" value = "org.springframework.web.servlet.view.JstlView" />
</bean>
</beans>
下面是要編寫代碼spring mvc中的C(Controller)了。在main/java中創建名為com.jac.dp.controllers的包,在此包下新建一個名為AbcController的類,其通過@Controller注解注入進spring框架中。具體的restful代碼如下圖所示。從圖中可以看到,其實現了一個名為getAbcs的方法,使用get用以對get式的 http://localhost:8088/restfulservice/abcs 請求進行響應。還實現了一個名為getAbc的方法,使用get以對get式的
http://localhost:8088/restfulservice/abcs/3 請求進行響
應,來獲取某一對象,返回給前端的是一Json字符串:
{"myInt":3,"myString":"myString"}
。名為putAbc的方法,其使用put以對put式的
http://localhost:8088/restfulservice/abcs/3 請求進行響
應,來更新某一對象。下圖中也展示了,使用工具REST Client來進行http put請求測試的過程與結果,在這里,返回的是一個對象轉成的Json字符串,在IDEA中可以看到其Response是:{"myInt":-1,"myString":"post true"},與預想中的一樣
;同樣的post和get也可以如此測試,測試get請求也可以直接使用瀏覽器執行。

代碼編寫完成后,需要進行服務發布了,我們使用Tomcat作為服務容器。在IDEA中如何進行Tomcat配置就不多說了,這里提一下Run/Debug Configurations。在Application context中配置成restfulservice才有上面的效果哦。

有時候一個理念讓人茅塞頓開、醍醐灌頂。
“約定優於配置”就是這樣的理念。感謝教給我這個理念的人,王某連雲港人。
