RESTEasy和restful WebService

   REST简介

    REST(Representational State Transfer)中文解释为“表述性状态转移”,是2000年由Roy Fielding 在他的博士论文 《Architectural Styles and the Design of Network-based Software Architectures》中提出的架构风格。REST是基于HTTP,URI,XML,JSON等协议或者标准,它促使了http协议的更加正确使用。相对于SOAP和WSDL提供的web service方案,REST显得更加简单。

    基于REST的web service应该遵守一些基本的原则:

    1:资源的识别:系统中的每一个对象或是资源都可以通过一个唯一的 URI 来进行寻址,URI 的结构应该简单、可预测且易于理解,比如定义目录结构式的 URI。

    2:协议:以遵循HTTP/1.1 RFC2616所定义的协议的方式显式地使用 HTTP 方法,建立创建、检索、更新和删除(CRUD:Create, Retrieve, Update and Delete)操作与 HTTP 方法之间的一对一映射:

  • POST:  在服务器上创建资源;
  • GET:  检索某个资源;
  • PUT:  更改资源状态或对其进行更新;
  • DELETE:  删除某个资源。

    3:自描述的消息:URI 所访问的每个资源都可以使用不同的形式加以表示(比如 XML 或者 JSON),具体的表现形式取决于访问资源的客户端,客户端与服务提供者使用一种内容协商的机制(请求头与 MIME 类型)来选择合适的数据格式,最小化彼此之间的数据耦合。

     Java Rest Framework

    1:Restlet: 出现的较早,在JAX-RS之前就有了,支持的框架较多,但是使用起来不够简单。

    1:CXF: 是Celtix 和 XFire合并后的项目,支持SOAP,WSDL,JSR-WS,REST,配置较为复杂,侵入性太强,单纯构建restful web service显得较重。

    2:Resteasy: 是jboss下面一个对JAX-RS(JSR311)的一个实现,使用起来简单方便,支持spring,oauth等。

    3:Jersey: 是sun公司对JAX-RS(JSR311)的一个参考实现,不过现在在逐渐的摆脱参考实现的阴影,逐渐渗透到企业应用,和sun的glassfish和netbeans结合使用可以很方便的构建restful web service。

    实现restful web service使用CXF和restlet都显得太重,使用Jersey总是觉得这个是官方的参考实现,看看Easyrest的文档还是较为全面,所以选择Easyrest来作为rest api的java框架。

    注:JSR 311 或 JAX-RS(用于 RESTful Web Services 的 Java API)的提议开始于 2007 年,1.0 版本到 2008 年 10 月定稿。目前,JSR 311 版本 1.1 还处于草案阶段。该 JSR 的目的是提供一组 API 以简化 REST 样式的 Web 服务的开发。

     RESTEasy的一些功能点

  1. 实现中遵守 JAX-RS 规范
  2. 需要 JDK 5 或者以上版本的应用服务器中运行
  3. 支持在应用服务器中作 junit 测试
  4. 使用annotations更简单的写客户端应用 (JAX-RS 只定义了服务器端的)
  5. 支持HTTP 1.1缓存语义包括缓存。
  6. 支持多种格式: XML, JSON, YAML, Fastinfoset, Multipart, XOP, Atom, etc.
  7. 支持JAXB 和XML, JSON, Jackson, Fastinfoset, and Atom 互转
  8. 支持GZIP ,JBoss Web, Tomcat 6, and Servlet 3.0,EJB, Seam, Guice, Spring, and Spring MVC integration

     使用Resteasy构建 restful web service

   把对图书馆的书籍的操作作为例子,讨论使用resteasy构建restful web service的方法。中间包括pom.xml的配置,web.xml的配置,相关上下文类的实现,核心类中到一些方法。

    1:创建工程,配置pom.xml

mvn archetype:create -DgroupId=com.longtask.rest.easyrest -DartifactId=easyrest -DarchetypeArtifactId=maven-archetype-webapp

mvn eclipse:eclipse

导入maven工程到eclipse,然后添加如下内容到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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.longtask.rest.easyrest</groupId>
    <artifactId>easyrest</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>easyrest Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>jboss</id>
            <url>http://repository.jboss.org/maven2</url>
        </repository>
    </repositories>
    <dependencies>
        <!– core library –>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>2.0.1.GA</version>
        </dependency>
        <!– resteasy-jaxb-provider –>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxb-provider</artifactId>
            <version>2.0.1.GA</version>
        </dependency>
       
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>jaxrs-api</artifactId>
            <version>2.0.1.GA</version>
        </dependency>
       
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-oauth</artifactId>
            <version>2.0-beta-2</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-atom-provider</artifactId>
            <version>2.0-beta-2</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-cache-core</artifactId>
            <version>2.0-beta-2</version>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>easyrest</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

       需要把相关到JAX-RS规范实现的包和相关的使用到的resteasy的包添加进去。

2:web.xml的配置

    RESTeasy 实现了部署为WAR文件的 Servlet , 在 WEB-INF/web.xml 需要配置相关到信息。具体配置如下:

   <web-app>
    <display-name>easyrest</display-name>

    <context-param>
      <param-name>javax.ws.rs.core.Application</param-name>
      <param-value>com.longtask.rest.resteasy.EasyRestApplication</param-value>
   </context-param>

   <context-param>
      <param-name>resteasy.servlet.mapping.prefix</param-name>
      <param-value>/services</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>/services/*</url-pattern>
   </servlet-mapping>

</web-app>

3:应用的实现

应用:按照JSR-RS的规范,在web.xml中的配置的类,需要通过继承javax.ws.rs.core.Application实现一个类来告知有哪些应用。

   public class EasyRestApplication extends Application {

    HashSet<Object> singletons = new HashSet<Object>();

    public EasyRestApplication() {
        singletons.add(new Library());
    }

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>();
        //set.add(Library.class);
        return set;
    }

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

POJO对象:用来传递相关内容,使用javax.xml.bind.annotation将Java pojo定制成XML 模式映射,提供给resteasy返回内容的时候调用。对象必须有相关到构造函数,否则报错。

    JAX-RS 支持使用 JAXB (Java API for XML Binding) 将 JavaBean 绑定到 XML 或 JSON,反之亦然。JavaBean 必须使用 @XmlRootElement 注释。清单 8 使用 Contact bean 作为示例。没有明确 @XmlElement 注释的字段将包含一个名称与之相同的 XML 元素。

   @XmlRootElement(name = "book")
public class Book {
    private String name;
    private String content;

    public Book() {
    }

    public Book(String name, String content) {
        this.name = name;
        this.content = content;
    }

    @XmlElement
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElement
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

应用访问路径的设置:

   @Path("/library")
public class Library{}

注:@Path表示访问到路径,必须存在于类或者是资源方法中,如果不存在,则通过相对路径来关联类或者方法。如果有@Path,而没有HTTP方法,则该方法为JAXRSResourceLocators。

GET:获取一个资源

   public static List<Book> books = new ArrayList<Book>();
    static{
        books.add(new Book("huhu","huhu"));
        books.add(new Book("haha","haha"));
    }
    
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Path("/books")
    
    public List<Book> listBooks(){
        return books;
    }
    
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    @Path("/book/{id}")
    public Book getBook(@PathParam("id") String id){
        if("1".equals(id))
            return new Book("huhu","huhu");
        else
            return new Book("haha","haha");
    }

通过启动tomcat后,通过访问:curl -i -H "Accept: application/json" http://localhost:8081/easyrest/services/library/books 可以获取相关到返回结果。相关参数到一些说明:

@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}):返回的内容格式设置

@PathParam :访问到路径对于到参数

PUT:

   @PUT
    @Path("/book/{name}")
    public void updateBook(@PathParam("name") PathSegment book){
        Iterator<Book> it = books.iterator();
        String name = String.valueOf(book.getMatrixParameters().get("name"));
        String content = String.valueOf(book.getMatrixParameters().get("content"));
        while(it.hasNext()){
            Book booktmp = it.next();
            if(name.equals(booktmp.getName())){
                booktmp.setContent(content);
                break;
            }
        }
    }

PathSegment是传递多个参数的接口,可以在POST方法后面添加多个参数传入给相关方法中。

POST:

   @POST
    @Path("/book/{name}/{content}")
    public void addBook(@PathParam("name") String name,@PathParam("name") String content){
        books.add(new Book(name,content));
    }

DELETE:

@DELETE
    @Path("/book/{name}")
    public void delBook(@PathParam("name") String name){
        Iterator<Book> it = books.iterator();
        while(it.hasNext()){
            Book book = it.next();
            if(name.equals(book.getName())){
                it.remove();
            }
        }
    }  

使用mvn package命名打包工程,把工程放到tomcat webapps目录下面。目前的应用只是简单到测试,涉及到和Spring等框架的交互,OAUTH协议等内容暂时不考虑。更多到内容请参考官方文档

     用cURL简单测试restful web service

#test GET
curl -i -H "Accept: application/json" http://localhost:8081/easyrest/services/library/books
curl -i -H "Accept: application/json" http://localhost:8081/easyrest/services/library/book/1

#test POST
curl -i -H "Accept: application/json" -X POST http://localhost:8081/easyrest/services/library/book/lala/lala
curl -i -H "Accept: application/json" http://localhost:8081/easyrest/services/library/books

#test DELETE
curl -i -H "Accept: application/json" -X DELETE http://localhost:8081/easyrest/services/library/book/lala

#test PUT not success
curl -i -H "Accept: application/json"  -X PUT http://localhost:8081/easyrest/services/library/book;name=haha;content=xiugai  

注:Curl 是一个流行的命令行工具,可以向使用 HTTP 和 HTTPS 协议的服务器发送请求。这是一个与 RESTful Web 服务通讯的好工具,因为它可以通过任何 HTTP 方法发送内容。Curl 已经在 Linux 和 Mac 中自带。

     参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值