diggbag

          BlogJava 聯系 聚合 管理
            0 Posts :: 13 Stories :: 6 Comments :: 0 Trackbacks

          RESTful簡要介紹

          RESTful風格的WebService之所以當下如此流行,是由于其相對于SOAP風格的WebService更簡潔、更輕量級,REST風格的WebService傳輸的是JSON或極其簡潔的XML,因而其效率和性能都比較理想。

          RESTful風格的WebService主張重用HTTP協議,面向資源編程(ROA)。扼要的說,RESTful風格WebService中,每一個URL即表示一個資源,比如http://www.example.com/employees/1 表示id1的員工。

          1. 如果對此URL調用HTTP GET方法,則返回員工的XML形式;

          2. 如果對此URL調用HTTP POST/PUT方法,則可以新增或者修改此員工;

          3. 如果對此URL調用HTTP DELETE方法,則可以刪除此員工;

          因此,我們在設計一個RESTful風格的接口時,一定要擁有面向資源設計的考量!

          此外,在實現接口的過程中,要遵循RESTful風格的幾個特性,他們分別是:

          1. 無狀態性:HTTP本身即是無狀態協議,因此RESTful天然的具備無狀態性,具備優良的水平擴展能力!

          2. 冪等性:GET/PUT/DELETE方法具備此特性,冪等性可概述為無論重復調用多少次,其結果都一致!POST例外,不過設計的時候也可以按照此特性設計!

          3. 唯一性:即URL地址要唯一的表示一個資源!

          關于事務、安全等更多的高級特性這里不闡述,有興趣的可參考《Restful Web Service中文版》一書。

          下面以開發一個普通接口和開發REST風格WebService接口為對比,指導大家快速入門。

          開發一個普通的接口

          2.1 定義DTO

          public class Info implements Serializable {

          private String id;

          private String name;

          private String description;

          public String getId() {

          return id;

          }

          public void setId(String id) {

          this.id = id;

          }

          public String getName() {

          return name;

          }

          public void setName(String name) {

          this.name = name;

          }

          public String getDescription() {

          return description;

          }

          public void setDescription(String description) {

          this.description = description;

          }

          }

          2.2 定義接口

          public interface SaleService extends Serializable {

          public List<Info> getInfos();

          public Info getInfo(String id);

          public void saveOrUpdateInfo(Info info);

          public void deleteInfo(String id);

          }

          2.3 實現類

          接口的實現,就此省略。

          開發RESTful風格WebService服務端

          3.1 定義資源(定義DTO

          @XmlRootElement(name = "Info")

          public class Info implements Serializable {

          private String id;

          private String name;

          private String description;

          @XmlElement(name = "ID")

          public String getId() {

          return id;

          }

          public void setId(String id) {

          this.id = id;

          }

          @XmlElement(name = "NAME")

          public String getName() {

          return name;

          }

          public void setName(String name) {

          this.name = name;

          }

          @XmlElement(name = "DESCRIPTION")

          public String getDescription() {

          return description;

          }

          public void setDescription(String description) {

          this.description = description;

          }

          }

          解析:@XmlRootElement(name = "Info")之類的注釋,是JAXB規范,用于XMLJava對象之間的互相轉換。不熟悉JAXB規范的可以自行搜索相關資料。

          Info對象對應的XML格式如下:

          <Info>

          <DESCRIPTION>des1</DESCRIPTION>

          <ID>1</ID>

          <NAME>name1</NAME>

          </Info>

          3.2 開發接口

          @Produces({ MediaType.APPLICATION_XML })

          public interface SaleService extends Serializable {

          @GET

          @Path("/infos")

          public List<Info> getInfos();

          @GET

          @Path("/infos/{id}")

          public Info getInfo(@PathParam("id") String id);

          @POST

          @Path("/infos")

          @Consumes({ MediaType.APPLICATION_XML, MediaType.TEXT_XML,

          MediaType.APPLICATION_JSON })

          public void saveOrUpdateInfo(Info info);

          @DELETE

          @Path("/infos/{id}")

          public void deleteInfo(@PathParam("id") String id);

          }

          解析:接口中的注釋均為JSR311中的規范。

          @Produces表示這個接口響應格式為XML


          表示響應
          http://www.example.com/.../infosGET請求,返回Info列表。


          表示響應
          http://www.example.com/.../infos/? 的GET請求,URL中的“?”作為參數代入方法中,最終返回對應的Info


          表示響應http://www.example.com/.../infos 的POST請求,可以接受APPLICATION_XMLTEXT_XML,JSON格式,最終保存Info對象。


          表示響應http://www.example.com/.../infos/? 的DELETE請求,URL中的“?”作為參數代入方法中,最終刪除對應的Info

          3.3 實現類

          接口的實現,同上。

          3.4 配置CXF(整合Spring、maven

          3.4.1 接口的Spring配置文件

          定義接口的實現類

          <bean id="saleService" class="com.csair.acp.service.impl.SaleServiceImpl" />

          3.4.2 CXFSpring配置文件

          <?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:jaxrs="http://cxf.apache.org/jaxrs"

          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

          http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

          <import resource="classpath:META-INF/cxf/cxf.xml" />

          <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />

          <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

          <jaxrs:server id="saleRestService" address="/v1">

          <jaxrs:serviceBeans>

          <ref bean="saleService" />

          </jaxrs:serviceBeans>

          </jaxrs:server>

          </beans>

          解析:<ref bean="saleService" />對應接口的Spring定義,address="/v1"定義地址的前綴。比如: http://www.example.com/xxx/v1/infos/?

          強烈建議加前綴!以此來提供不同版本的WebService訪問!

          3.4.3 修改web.xml

          <context-param>

          <param-name>contextConfigLocation</param-name>

          <param-value>classpath*:spring/*.xml</param-value>

          </context-param>

          <listener>

          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

          </listener>

          <servlet>

          <servlet-name>CXFServlet</servlet-name>

          <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

          <load-on-startup>1</load-on-startup>

          </servlet>

          <servlet-mapping>

          <servlet-name>CXFServlet</servlet-name>

          <url-pattern>/*</url-pattern>

          </servlet-mapping>

          3.4.4 Maven配置

          maven中使用cfx發布webservice需要添加如下依賴:

          <dependency>

          <groupId>org.apache.cxf</groupId>

          <artifactId>cxf-bundle</artifactId>

          <version>2.2.4</version>

          </dependency>

          <dependency>

          <groupId>org.apache.cxf</groupId>

          <artifactId>cxf-bundle-jaxrs</artifactId>

          <version>2.2.4</version>

          </dependency>

          <dependency>

          <groupId>org.apache.cxf</groupId>

          <artifactId>cxf-rt-core</artifactId>

          <version>2.2.4</version>

          </dependency>

          <dependency>

          <groupId>org.apache.cxf</groupId>

          <artifactId>cxf-rt-frontend-jaxrs</artifactId>

          <version>2.2.4</version>

          </dependency>

          到此,配置完畢,可以啟動部署到web容器中啟動,在FireFox中訪問http://localhost:8080/v1/infos ,看看是否有XML格式的輸出。

          開發RESTful風格WebService客戶端(Java

          4.1 定義客戶端接口

          public interface SaleClient extends Serializable {

          public List<Info> getInfos();

          public Info getInfo(String id);

          public void saveOrUpdateInfo(Info info);

          public void deleteInfo(String id);

          }

          4.2 定義實現類

          客戶端如果能引用服務端的jar包,那么開發將非常簡單。

          import com.csair.acp.resources.Info; //引用自服務端

          import com.csair.acp.service.SaleService; //引用自服務端

          public class SaleClientImpl implements SaleClient {

          private static String BASE_ADDRESS = "http://localhost:8080/v1";

          SaleService service;

          public SaleClientImpl() {

          initProxy();

          }

          private SaleService initProxy() {

          service = JAXRSClientFactory.create(BASE_ADDRESS, SaleService.class);

          WebClient.client(service).accept(MediaType.APPLICATION_XML);// 一定需要

          return service;

          }

          @Override

          public List<Info> getInfos() {

          try {

          return service.getInfos();

          catch (WebApplicationException ex) {

          ex.printStackTrace();

          return null;

          }

          }

          @Override

          public Info getInfo(String id) {

          try {

          return service.getInfo(id);

          catch (WebApplicationException ex) {

          ex.printStackTrace();

          return null;

          }

          }

          @Override

          public void saveOrUpdateInfo(Info info) {

          try {

          service.saveOrUpdateInfo(info);

          catch (WebApplicationException ex) {

          ex.printStackTrace();

          }

          }

          @Override

          public void deleteInfo(String id) {

          try {

          service.deleteInfo(id);

          catch (WebApplicationException ex) {

          ex.printStackTrace();

          }

          }

          }

          客戶端的開發十分簡便,如果用其他語言,那么需要自行使用對應的HTTP類庫進行編碼。

          如果使用spring injecting proxies 方式進行配置,則使用如下配置:

          <jaxrs:client id ="saleClient " address="http://localhost:8080/v1" serviceClass="com.csair.acp.service.SaleService">

          </jaxrs:client>

          具體配置參照:http://cxf.apache.org/docs/jax-rs-client-api.html

          范例

          本文對應的例子為maven構建:

          rest-server為服務端,運行jetty:run即可

          rest-client為客戶端,運行rest-client/src/test/java/com/csair/acp/client/impl/SaleClientImplTest.java單元測試類即可

          posted on 2011-10-24 17:27 哲同 閱讀(7982) 評論(0)  編輯  收藏 所屬分類: java相關
          主站蜘蛛池模板: 台湾省| 舒兰市| 兴海县| 安远县| 白山市| 佛山市| 桂平市| 佳木斯市| 桐梓县| 陕西省| 红原县| 北安市| 广宁县| 中宁县| 巧家县| 应城市| 安庆市| 新营市| 始兴县| 威信县| 南川市| 扎赉特旗| 寿阳县| 武穴市| 海林市| 临湘市| 忻州市| 景德镇市| 永州市| 中西区| 杨浦区| 保康县| 晴隆县| 财经| 吉林省| 兖州市| 旬邑县| 科技| 高邑县| 永和县| 邢台县|