RestEasy技术说明

转载:http://blog.csdn.net/bynhack/article/details/6565809

简介

RESTEasy

RESTEasy是JBoss的一个开源项目,提供各种框架帮助你构建RESTful Web Services和RESTful Java应用程序。它是JAX-RS规范的一个完整实现并通过JCP认证。作为一个JBOSS的项目,它当然能和JBOSS应用服务器很好地集成在一起。但是,它也能在任何运行JDK5或以上版本的Servlet容器中运行。RESTEasy还提供一个RESTEasy JAX-RS客户端调用框架。能够很方便与EJB、Seam、Guice、Spring和Spring MVC集成使用。支持在客户端与服务器端自动实现GZIP解压缩。

RESTEasy 项目是 JAX-RS 的一个实现,集成的一些亮点:

•不需要配置文件,只要把JARs文件放到类路径里面,添加 @Path 标注就可以了。 
•完全的把 RESTEeasy 配置作为Seam 组件来看待。 
•HTTP 请求由Seam来提供,不需要一个额外的Servlet。 
•Resources 和providers可以作为 Seam components (JavaBean or EJB),具有全面的Seam injection,lifecycle, interception, 等功能支持。 
•支持在客户端与服务器端自动实现GZIP解压缩。 
名词解释:

JAX-RS: Java API for RESTful Web Services是一个Java编程语言的应用程序接口,支持按照 表象化状态转变 (REST)架构风格创建Web服务Web服务[1]. JAX-RS使用了Java SE 5引入的Java 标注来简化Web服务客户端和服务端的开发和部署。

规范内容

JAX-RS提供了一些标注将一个资源类,一个POJOJava类,封装为Web资源。标注包括:

@Path,标注资源类或方法的相对路径

@GET,@PUT,@POST,@DELETE,标注方法是用的HTTP请求的类型

@Produces,标注返回的MIME媒体类型

@Consumes,标注可接受请求的MIME媒体类型

@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,例如@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。

REST

维基百科REST词条的解释

深入浅出REST

详细介绍

如何配置

单独配置

在 WEB-INF/web.xml 中配置如下:

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

org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher

</servlet-class><init-param><param-name>javax.ws.rs.Application</param-name><param-value>com.restfully.shop.services.ShoppingApplication</param-value></init-param></servlet><servlet-mapping><servlet-name>Resteasy</servlet-name><url-pattern>/*</url-pattern></servlet-mapping></web-app>

配置开关

Resteasy采用 <context-param>元素来配置,参数如下:

参数名 
默认值 
描述

resteasy.servlet.mapping.prefix 
no default 
If the url-pattern for the Resteasy servlet-mapping is not /*

resteasy.scan 
FALSE 
Automatically scan WEB-INF/lib jars and WEB-INF/classes directory for both @Provider and JAX-RS resource classes (@Path, @GET, @POST etc..) and register them

resteasy.scan.providers 
FALSE 
Scan for @Provider classes and register them

resteasy.scan.resources 
FALSE 
Scan for JAX-RS resource classes

resteasy.providers 
no default 
A comma delimited list of fully qualified @Provider class names you want to register

resteasy.use.builtin.providers

TRUE 
Whether or not to register default, built-in @Provider classes. (Only available in 1.0-beta-5 and later)

resteasy.resources

no default

A comma delimited list of fully qualified JAX-RS resource class names you want to register

resteasy.jndi.resources

no default

A comma delimited list of JNDI names which reference objects you want to register as JAX-RS resources

javax.ws.rs.Application

no default

Fully qualified name of Application class to bootstrap in a spec portable way

resteasy.media.type.mappings

no default

Replaces the need for an Accept header by mapping file name extensions (like .xml or .txt) to a media type. Used when the client is unable to use a Accept header to choose a representation (i.e. a browser). See JAX-RS Content Negotiation chapter for more details.

resteasy.language.mappings

no default

Replaces the need for an Accept-Language header by mapping file name extensions (like .en or .fr) to a language. Used when the client is unable to use a Accept-Language header to choose a language (i.e. a browser). See JAX-RS Content Negotiation chapter for more details

使用ServletContextListener来配置

<web-app><listener><listener-class>

org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap

</listener-class></listener><!-- ** INSERT YOUR LISTENERS HERE!!!! --><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>/resteasy/*</url-pattern></servlet-mapping></web-app>

使用ServletFilter来配置

<web-app><filter><filter-name>Resteasy</filter-name><filter-class>

org.jboss.resteasy.plugins.server.servlet.FilterDispatcher

</filter-class><init-param><param-name>javax.ws.rs.Application</param-name><param-value>com.restfully.shop.services.ShoppingApplication</param-value></init-param></filter><filter-mapping><filter-name>Resteasy</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

与Spring集成

<web-app><display-name>Archetype Created Web Application</display-name><listener><listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class></listener><listener><listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</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>

使用@Path,@Get,@Post等标注

示例:

@Path("/library")

public class Library {

@GET

@Path("/books")

public String getBooks() {...}

@GET

@Path("/book/{isbn}")

public String getBook(@PathParam("isbn") String id) {

// search my database and get a string representation and return it

}

@PUT

@Path("/book/{isbn}")

public void addBook(@PathParam("isbn") String id, @QueryParam("name") String name) {...}

@DELETE

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

public void removeBook(@PathParam("id") String id {...}

}

以下操作都是针对library这个资源的

GET http://myhost.com/services/library/books 意思为获得所有的books调用的方法为getBooks

GET http://myhost.com/services/library/book/333 意思为获得ID为333的book调用的方法为getBook

PUT http://myhost.com/services/library/book/333 新增一个ID为333的book调用的方法为addBook

DELETE http://myhost.com/services/library/book/333 删除一个ID为333的book调用的方法为removeBook

@Path这个标注可以在类上也可以在方法上,如果类和方法上都有的话,那么方法上的路径是级联的如上面例子的/library/book/

@Path和使用正则表达式匹配路径

@Path不仅仅接收简单的路径表达式,也可以使用正则表达式:

@Path("/resources)

public class MyResource {

@GET

@Path("{var:.*}/stuff")

public String get() {...}

}

如下操作就能获得该资源

GET /resources/stuff

GET /resources/foo/stuff

GET /resources/on/and/on/stuff

表达式的格式为:

"{" variable-name [ ":" regular-expression ] "}"

正则表达式部分是可选的,当未提供时,则会匹配一个默认的表达式"([]*)"

@Path("/resources/{var}/stuff")

会匹配如下路径

GET /resources/foo/stuff

GET /resources/bar/stuff

下面的则不会匹配

GET /resources/a/bunch/of/stuff

@PathParam

@PathParam 参数标注是用来获取映射路径上的变量值供方法使用

@Path("/library")

public class Library {

@GET

@Path("/book/{isbn}")

public String getBook(@PathParam("isbn") String id) {

// search my database and get a string representation and return it

}

}

GET http://myhost.com/services/library/book/333 就会调用到getBook方法,id的值就会被自动映射为333

@Path中的变量名要和@PathParam中的变量名一致,参数类型可以是任意类型,一个String,一个Java对象,注意如果是Java对象时,这个对象要拥有一个带String类型参数的构造器或者一个返回值为String的静态valueOf方法,例如:

构造器方式:

@GET

@Path("/book/{isbn}")

public String getBook(@PathParam("isbn") ISBN id) {...}

public class ISBN {

public ISBN(String str) {...}

}

valueOf方式:

public class ISBN {

public static ISBN valueOf(String isbn) {...}

}

这样做的目的是底层会把请求的参数通过String的方式传递的前端,构造对象的方式由业务层来自己构建

@PathParam高级使用

允许指定一个或多个路径参数在一个URI段中。例如:

1.@Path("/aaa{param}bbb") 
"/aaa111bbb"会匹配,param=111

1.@Path("/{name}-{zip}") 
"/bill-02115" 会匹配,name=bill,zip=02115

1.@Path("/foo{name}-{zip}bar") 
"/foobill-02115bar " 会匹配,name=bill,zip=02115

正则表达式方式例子:

@GET

@Path("/aaa{param:b+}/{many:.*}/stuff")

public String getIt(@PathParam("param") String bs, @PathParam("many") String many) {...}

GET /aaabb/some/stuff bs=bb,many=some

GET /aaab/a/lot/of/stuff bs= b,many=a/lot/of

@QueryParam

@QueryParam这个标注是给通过?的方式传参获得参数值的,如:

GET /books?num=5&index=1

@GET

public String getBooks(@QueryParam("num") int num,@QueryParam("index") int index) {

...

}

这里同上面的@PathParam,参数类型可以是任意类型

@HeaderParam

这个标注时用来获得保存在HttpRequest头里面的参数信息的,如:

@PUT

public void put(@HeaderParam("Content-Type") MediaType contentType, ...)

这里同上面的@PathParam,参数类型可以是任意类型

@CookieParam

用来获取保存在Cookie里面的参数,如:

@GET

public String getBooks(@CookieParam("sessionid") int id) {

...

}

@FormParam

用来获取Form中的参数值,如:

页面代码:

<form method="POST" action="/resources/service">

First name:

<input type="text" name="firstname"><br>

Middle name:

<input type="text" name="middlename">

Last name:

<input type="text" name="lastname"> 
</form>

后台代码

@Path("/")

public class NameRegistry {

@Path("/resources/service")

@POST

public void addName(@FormParam("firstname") String first, @FormParam("lastname") String last) {...}

标注了@FormParam,会把表达里面的值自动映射到方法的参数上去.

如果要取得Form里面的所有属性,可以通过在方法上增加一个MultivaluedMap<string string> form这样的对象来获得,如下:

@Path("/resources/service")

@POST

public void addName(@FormParam("firstname") String first, @FormParam("lastname") String last,MultivaluedMap<string string> form) {...}

@Form

上面已经说的几种标注都是一个属性对应一个参数的,那么如果属性多了,定义的方法就会变得不好阅读,此时最好有个东西能够把上面的几种自动标注自动封装成一个对象,@Form这个标注就是用来实现这个功能的,如:

public class MyForm {

@FormParam("stuff")

private int stuff;

@HeaderParam("myHeader")

private String header;

@PathParam("foo")

public void setFoo(String foo) {...}

}

@POST

@Path("/myservice")

public void post(@Form MyForm form) {...}

@DefaultValue

在以上标注使用的时候,有些参数值在没有值的情况下如果需要有默认值,则使用这个标注,如:

@GET

public String getBooks(@QueryParam("num") @DefaultValue("10") int num) {...}

满足JAX-RS规范的 Resource Locators和子资源

资源处理类定义的某个方法可以处理某个请求的一部分,剩余部分由子资源处理类来处理,如:

@Path("/")

public class ShoppingStore {

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

public Customer getCustomer(@PathParam("id") int id) {

Customer cust = ...; // Find a customer object

return cust;

}

}

public class Customer {

@GET

public String get() {...}

@Path("/address")

public String getAddress() {...}

}

当我们发起GET /customer/123这样的请求的时候,程序会先调用 ShoppingStore的 getCustomer这个方法,然后接着调用 Customer里面的 get方法

当我们发起GET /customer/123/address这样的请求的时候,程序会先调用 ShoppingStore的 getCustomer这个方法,然后接着调用 Customer里面的 getAddress 方法

JAX-RS Content Negotiation

@Consumes

我们从页面提交数据到后台的时候,数据的类型可以是text的,xml的,json的,但是我们在请求资源的时候想要请求到同一个资源路径上面去,此时怎么来区分处理呢?使用@Consumes标注,下面的例子将说明:

@Consumes("text/*")

@Path("/library")

public class Library {

@POST

public String stringBook(String book) {...}

@Consumes("text/xml")

@POST

public String jaxbBook(Book book) {...}

当客户端发起请求的时候,系统会先找到所有匹配路径的方法,然后根据content-type找到具体的处理方法,比如:

POST /library

content-type: text/plain

就会执行上面的 stringBook这个方法,因为这个方法上面没有标注@ Consumes,程序找了所有的方法没有找到标注 @ Consumes(“text/plain”)这个类型的,所以就执行这个方法了.如果请求的content-type=xml,比如:

POST /library

content-type: text/xml

此时就会执行 jaxbBook这个方法

@Produces

当服务器端实行完成相关的逻辑需要返回对象的时候,程序会根据@Produces返回相应的对象类型

@Produces("text/*")

@Path("/library")

public class Library {

@GET

@Produces("application/json")

public String getJSON() {...}

@GET

public String get() {...}

如果客户端发起如下请求

GET /library

那么则会调用到get方法并且返回的格式是json类型的

这些标注能不能写多个呢?答案是可以的,但是系统只认第一个

Content Marshalling/Providers

这个东西是用来根据消息题格式来组装对象或者根据对象生成相应的消息体的,默认的对应关系如下

Media Types 
Java Type

application/*+xml, text/*+xml, application/*+json, application/*+fastinfoset, application/atom+*

JaxB annotated classes

application/*+xml, text/*+xml

org.w3c.dom.Document

*/*

java.lang.String

javax.activation.DataSource

java.io.File

byte[]

application/x-www-form-urlencoded

javax.ws.rs.core.MultivaluedMap

text/plain

primtives, java.lang.String, or any type that has a String constructor, or static valueOf(String) method for input, toString() for output

生成 JavaScript API

RESTEasy能够生成JavaScript API使用AJAX来执行 JAX-RS操作,比如:

@Path("orders")

public interface Orders {

@Path("{id}")

@GET

public String getOrder(@PathParam("id") String id){

return "Hello "+id;

}

}

以上代码可以在js里面通过var order = Orders.getOrder({id: 23});

这种方式来调用,很酷吧,这里应该是跟Google的一项技术类似的Java代码可以通过js方式来调用

通过JavaApi调用资源

上面介绍了生成jsapi的方式调用,另外如果别的应用需要通过Java的方式调用资源该怎么处理呢,下面的例子将说明:

ClientRequest request = new ClientRequest("http://localhost:8080/rest/services/demoservice/child/22222");

// request.header("custom-header", "value");

// We're posting XML and a JAXB object

// request.body("application/xml", someJaxb);

// we're expecting a String back

ClientResponse<object> response = request.get(Object.class);

if (response.getStatus() == 200) // OK!

{

Object str = response.getEntity();

System.out.println(str);

}

把资源当做一个标准servlet接收处理方法

我们可以把一个资源url当做一个接收servlet请求的处理类或者处理方法

jaxb介绍 
对@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam参数的处理

@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam标注传递的参数类型是String型的,对于这些参数我们的方法可能希望接收的参数是经过转换后的对象类型的参数,比如如下的方法:

void put(@QueryParam("pojo")POJO q, @PathParam("pojo")POJO pp,@MatrixParam("pojo")POJO mp,@HeaderParam("pojo")POJO hp);

这里的Put方法需要的是一个Pojo类型的参数,但是@PathParam, @QueryParam, @MatrixParam, @FormParam, and @HeaderParam传递的都是String类型的,怎么是怎么转换为对象的呢?

可以使用StringConverter或者StringParamUnmarshaller

StringConverter

package org.jboss.resteasy.spi;

public interface StringConverter<t>

{

T fromString(String str);

String toString(T value);

}

实现类如下:

@Provider

public static class POJOConverter implements StringConverter<pojo>

{

public POJO fromString(String str)

{

System.out.println("FROM STRNG: " + str);

POJO pojo = new POJO();

pojo.setName(str);

return pojo;

}

public String toString(POJO value)

{

return value.getName();

}

}

FromString就是你自己需要实现的如何把接收的String参数转换为Pojo类

toString方法是用来把Pojo对象转换为String

现在已经能够把String参数转换为对象了,我们更进一步的想使用一些自定义的标注来做一些逻辑,比如说日期的格式化,就要使用下面的StringParamUnmarshaller

StringParamUnmarshaller

package org.jboss.resteasy.spi;

public interface StringParameterUnmarshaller<t>

{

void setAnnotations(Annotation[] annotations);

T fromString(String str);

}

实现类

public class DateFormatter implements StringParameterUnmarshaller<date>

{

private SimpleDateFormat formatter;

public void setAnnotations(Annotation[] annotations)

{

DateFormat format = FindAnnotation.findAnnotation(annotations, DateFormat.class);

formatter = new SimpleDateFormat(format.value());

}

public Date fromString(String str)

{

try

{

return formatter.parse(str);

}

catch (ParseException e)

{

throw new RuntimeException(e);

}

}

}

使用方式:

@Path("/datetest")

public class Service

{

@GET

@Produces("text/plain")

@Path("/{date}")

public String get(@PathParam("date") @DateFormat("MM-dd-yyyy") Date date)

{

System.out.println(date);

Calendar c = Calendar.getInstance();

c.setTime(date);

Assert.assertEquals(3, c.get(Calendar.MONTH));

Assert.assertEquals(23, c.get(Calendar.DAY_OF_MONTH));

Assert.assertEquals(1977, c.get(Calendar.YEAR));

return date.toString();

}

}

在实际使用中,我们有些参数值并不是通过以上方式来传递的,比如说我们要对session进行操作,那么应该怎么办呢,resteasy并没有直接提供使用自定义标注的方法,所以我们可以使用以上的 StringParamUnmarshaller来变通的实现

首先定义自定义标注

@Retention(RetentionPolicy.RUNTIME)

@StringParameterUnmarshallerBinder(SessionOperator.class)

public @interface Session {

public String value();

}

@StringParameterUnmarshallerBinder(SessionOperator.class)是用来指明这个自定义标注是哪个具体的类来处理, SessionOperator这个类就是Session这个自定义标注的处理类

public class SessionOperator implements StringParameterUnmarshaller{

public void setAnnotations(Annotation[] annotations) {

}

public Object fromString(String str) {

return null;

}

}

RestEasy介绍相关推荐

  1. dubbo 即是服务提供者又是消费者_Dubbo详细介绍与安装使用过程

    1 Dubbo介绍 1.1 dubbox简介 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. ...

  2. Dubbo详细介绍与安装使用过程

    1 Dubbo介绍 1.1 dubbox简介 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. ...

  3. JavaEE的RESTful标准技术JAX-RS,jersey-client客户端使用介绍【享学Java】

    软件开发往往是这样:最开始的 90% 代码占用了开始的 90% 的开发时间:剩下10% 代码同样需要 90% 的开发时间. 目录 前言 正文 何为JAX-RS(1.0和2.0) JSR 311 JSR ...

  4. Dubbo的介绍以及Dubbox的区别

    Dubbo官网:  http://dubbo.io/ Dubbox官网: https://github.com/dangdangdotcom/dubbox Dubbo 是阿里巴巴公司开源的一个基于Ja ...

  5. WebService基本介绍

    什么是WebService? W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用, ...

  6. RestEasy的入门与使用

    文章目录 RestEasy的入门与使用 背景 传统Servlet JAX-RS和JSR 为什么要看规范? 简单解读JSR370 Applications Resources Providers Res ...

  7. RESTEasy搭建

    1.所需要引入的依赖 一种是自己导包,一种是用集成的包 第一种,需要配置web.xml <dependency><groupId>org.jboss.resteasy</ ...

  8. RESTEasy入门

    RESTEasy入门 博客分类: RESTEasy mavenWebServiceJBossServletWeb  RESTEasy是JBoss的开源项目之一,是一个RESTful Web Servi ...

  9. RestEasy简介

    RestEasy简介 RestEasy技术说明 简介 RESTEasy RESTEasy是JBoss的一个开源项目,提供各种框架帮助你构建RESTful Web Services和RESTful Ja ...

最新文章

  1. 计算机网络谢希仁第七版课后答案第五章 传输层
  2. 决策树 随机森林 xgboost_一文搞定XGboost 面试常见问题
  3. java 64位 默认分配内存大小_查看你机器中Java程序堆内存的默认初始大小和最大大小...
  4. 程序员面试题精选100题(07)-翻转句子中单词的顺序[算法]
  5. Java ADF开发入门-简单ArcGIS Server Web ADF应用
  6. 阿里云linux下web服务器配置
  7. eslint quo_Quo Vadis JUnit
  8. OSGi服务测试助手:ServiceRegistrationRule
  9. 15数字华容道解法 图解_密不外传的点穴秘技:15个穴位的取穴、点法、解法(上)...
  10. Linux之父道歉后,Linux社区颁布开发人员行为准则
  11. 如何选择一个合适的大数据可视化工具
  12. 岛主 同学给我出的算法题
  13. P-Called-Party-ID 头域的应用说明
  14. 风车im即时通讯源码
  15. 公式经纬度换算度分秒,度分秒换算经纬度
  16. tomcat乱码的几种解决
  17. 第三方支付业务流程介绍
  18. 【Win10自带录屏工具】
  19. XJOI1131换零钱
  20. 坐标转换-大地转高斯平面平面坐标转换

热门文章

  1. 解决虚拟机黑屏的问题,你只需要一行代码(某大神教的~记录记录)
  2. discuz php升级,DiscuzX 论坛安装升级
  3. 用户注册、加密、激活、登录、退出
  4. Zookeeper的学习与应用
  5. 放弃“一阳指”,改练“六脉神剑”的OPPO何时能“后发先至”?
  6. 干货 | 携程机票 Android Jetpack 与 Kotlin Coroutines 实践
  7. 公司财务会计制度范本
  8. 模态框的学习——巧妙处理setVisible(true)的阻塞问题
  9. JS jQuery显示隐藏div的几种方法
  10. js控制div滚动条的显示/隐藏