RESTEasy入門學習

      RESTEasy是JBoss的開源項目之一,是一個RESTful Web Services框架。RESTEasy的開發者Bill Burke同時也是JAX-RS的J2EE標準制定者之一。JAX-RS是一個JCP制訂的新標準,用於規範基於HTTP的RESTful Web Services的API。咱們已經有SOAP了,爲何須要Restful WebServices?用Bill本身的話來講:"若是是爲了構建SOA應用,從技術選型的角度來說,我相信REST比SOAP更具優點。開發人員會意識到使用傳統方式有進行SOA架構有多複雜,更不用提使用這些作出來的接口了。這時他們就會發現Restful Web Services的光明之處。「 說了這麼多,咱們使用RESTEasy作一個項目玩玩看。java

首先創造一個maven的web項目:程序員

Java代碼:web

mvn archetype:create -DgroupId=org.bluedash \  

-DartifactId=try-resteasy -DarchetypeArtifactId=maven-archetype-webapp 

     準備工做完成後,咱們就能夠開始寫代碼了,假設咱們要撰寫一個處理客戶信息的Web Service,它包含兩個功能:一是添加用戶信息;二是經過用戶Id,獲取某個用戶的信息,而交互的方式是標準的WebService形式,數據交換格式爲XML。假設一條用戶包含兩個屬性:Id和用戶名。那麼咱們設計交換的XML數據以下:apache

<user>
	<id>1</id>
	<name>liweinan</name>
</user>

 首先要作的就是把上述格式轉換成XSD2,網上有在線工具能夠幫助咱們完成這一工做3,在此不詳細展開。使用工具轉換後,生成以下xsd文件:api

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="user" type="userType" />
  <xsd:complexType name="userType">
    <xsd:sequence>
      <xsd:element name="id" type="xsd:int" />
      <xsd:element name="name" type="xsd:string" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

有了xsd文件,咱們即可以使用JDK自帶工具的xjc將xsd轉換成爲Java的Class。將上述xsd文件存爲 user.xsd,並使用以下命令進行轉換:安全

xjc user.xsd

 執行結束後咱們會獲得一系列的類文件:服務器

Li-Weinans-MacBook-Pro:Desktop liweinan$ xjc user.xsd 
parsing a schema...
compiling a schema...
generated/ObjectFactory.java
generated/UserType.java

這樣,咱們的XML格式的交換數據便轉化爲面向對像的Java類了,是否是感受有點像Hibernate的ORM理念?沒錯,將XML映射成成面向對象的數據類,這個過程叫作XML Binding,即XML綁定。這個過程也有J2EE標準,叫作JAXB4。而RESTEasy是全面支持JAXB的。能夠說RESTEasy所支持的JAX-RS標準,當與JAXB標準結合在一塊兒使用時,就能夠發揮出最大優點,讓程序員少寫一堆一堆的代碼。有關JAXB標準,會在 獨立的篇章中 詳細討論,在此先不展開。總之咱們將生成的Java類放進項目中等候使用。咱們能夠看一下UserType類的內容:架構

 

package org.bluedash.resteasy;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "userType", propOrder = {
    "id",
    "name"
})
public class UserType {

    protected int id;
    @XmlElement(required = true)
    protected String name;

    /**
     * Gets the value of the id property.
     * 
     */
    public int getId() {
        return id;
    }

    /**
     * Sets the value of the id property.
     * 
     */
    public void setId(int value) {
        this.id = value;
    }

    /**
     * Gets the value of the name property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the value of the name property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setName(String value) {
        this.name = value;
    }

}

 

能夠看到,XML格式就是經過一些JAXB的標記被映射成了Java類。咱們沒寫什麼代碼,已經把數據模型定義清楚了。接下來咱們撰寫最核心的WebService API。咱們的WebService包含兩個接口:一個是添加用戶接口createUser,另外一個是獲取用戶接口getUser:app

 

package org.bluedash.resteasy;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;

@Path("/users")
public class UserServlet {

	private Map<Integer, UserType> userStore = 
		new ConcurrentHashMap<Integer, UserType>();
	private AtomicInteger idGenerator = new AtomicInteger();

	@POST
	@Consumes("application/xml")
	public Response createUser(UserType user) {
		user.setId(idGenerator.incrementAndGet());
		userStore.put(user.getId(), user);
		System.out.println(user.getName() + " created: " 
			+ user.getId());
		return Response.created(URI.create("/users/" 
			+ user.getId())).build();
	}

	@GET
	@Path("{id}")
	@Produces("application/xml")
	public UserType getUser(@PathParam("id") int id) {
		UserType u = userStore.get(id);
		if (u == null) {
			throw new WebApplicationException(
				Response.Status.NOT_FOUND);
		}
		return u;
	}

}

     用幾個簡單的JAX-RS標記,便把普通的函數變成了WebService接口。而這些標記將由RESTEasy支持生效。接下來咱們將要進行RESTEasy的配置工做。RESTEasy的配置方法有多種多樣,能夠和Spring等容器集成,也能夠獨立運行,由於咱們用的Servlet的形式使RESTEasy進行工做,這也是最主流的方式,所以在這裏使用web容器來加載它,首先定義一個配置類:框架

package org.bluedash.resteasy;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.core.Application;

public class BluedashResteasyApplication extends Application {
	private Set<Object> singletons = new HashSet<Object>();
	private Set<Class<?>> classes = new HashSet<Class<?>>();

	public BluedashResteasyApplication() {
//		classes.add(UserServlet.class);
		singletons.add(new UserServlet());
	}

	@Override
	public Set<Class<?>> getClasses() {
		return classes;
	}

	@Override
	public Set<Object> getSingletons() {
		return singletons;
	}
}

   這個類擴展JAX-RS的Application接口,用於封裝咱們的WebService API方法。咱們能夠看到JAX-RS支持兩種封裝方法,一種是classes封裝,由容器管理WebServices類的實例化和銷燬等動做,一個線程一個實例,開發者不須要關心線程安全問題。但這種方法可能比較浪費資源。若是開發者想本身管理線程安全,共線程共用一個WebServices實例,那麼就用singletons封裝。咱們在這裏用的singletons封裝,這也就解釋了爲何咱們在 UserServlet中使用了ConcurrentHashMap和AtomicInteger這些保障線程安全的類。接下來就是在web.xml中啓動RESTEasy:

 

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Archetype Created Web Application</display-name>

	<context-param>
		<param-name>javax.ws.rs.core.Application</param-name>
		<param-value>org.bluedash.resteasy.
		BluedashResteasyApplication</param-value>
	</context-param>

	<listener>
		<listener-class>org.jboss.resteasy.plugins.server.
		servlet.ResteasyBootstrap</listener-class>
	</listener>

	<servlet>
		<servlet-name>Resteasy</servlet-name>
		<servlet-class>org.jboss.resteasy.plugins.server.servlet.
		HttpServletDispatcher</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>Resteasy</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

沒錯,就是這麼簡單,這樣,咱們的WebService就完成了!還差點什麼呢?嗯,還差一個Test Case來使用咱們的WebService接口,並驗證它的正確性,讓咱們來寫一個TestUserAPI

 

package org.bluedash.resteasy.test.integration.test;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import junit.framework.TestCase;

public class TestUserAPI extends TestCase {
	public static final String USER_API = 
		"http://127.0.0.1:8080/try-resteasy/users";

	public void testCreateUserAndGetUser() throws IOException {
		URL url = 
			new URL(USER_API);
		HttpURLConnection connection = 
			(HttpURLConnection) url.openConnection();
		connection.setRequestMethod("POST");
		connection.setRequestProperty("Content-Type", "application/xml");
		connection.setDoOutput(true);
		connection.setInstanceFollowRedirects(false);
		connection.setConnectTimeout(1000);

		String userXML = "<user><name>liweinan</name></user>";
		OutputStream os = connection.getOutputStream();
		os.write(userXML.getBytes());
		os.flush();

		assertEquals(HttpURLConnection.HTTP_CREATED, connection
				.getResponseCode());		
		connection.disconnect();

	}
}

一切都已經準備就緒,最後咱們要配置一下Maven,讓它下載所需的RESTEasy等庫,而後配置Maven使用Jetty Web服務器,來把咱們的服務和測試跑起來:

 

 

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.bluedash</groupId>
  <artifactId>try-resteasy</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>try-resteasy Maven Webapp</name>
  <url>http://maven.apache.org</url>
   <repositories>
        <repository>
            <id>JBossMavenRepo</id>
            <name>JBoss Maven2 repo</name>
            <url>http://repository.jboss.org/maven2</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>1.2.RC1</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxb-provider</artifactId>
            <version>1.2.RC1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>try-resteasy</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>**/integration/**</exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>integration-tests</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <skip>false</skip>
                            <excludes>
                                <exclude>none</exclude>
                            </excludes>
                            <includes>
                                <include>**/integration/**</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.15</version>
                <configuration>
                    <scanIntervalSeconds>5</scanIntervalSeconds>
                    <stopKey>foo</stopKey>
                    <stopPort>9999</stopPort>
                </configuration>
                <executions>
                    <execution>
                        <id>start-jetty</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <scanIntervalSeconds>5</scanIntervalSeconds>
                            <daemon>true</daemon>
                        </configuration>
                    </execution>
                    <execution>
                        <id>stop-jetty</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

有關Maven的配置就不詳細展開了。配置完成後咱們即可以運行單元測試,看看WebServices是否正確運行。執行下述命令

 

mvn integration-test

執行結果以下:

 

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.bluedash.resteasy.test.integration.test.TestUserAPI
liweinan created: 1
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.372 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

能夠看到,咱們的測試按預期執行成功了。這篇文章中,我簡單向你們介紹了RESTEasy的初步使用方法,但願對你們在架構SOA應用時,有所幫助。JAX-RS標準作爲J2EE家庭中相對較新的一員,其應用前景是十分廣闊的

相關文章
相關標籤/搜索