转载本文需注明出处:EAII企业架构创新研究院,违者必究。如需加入微信群参与微课堂、架构设计与讨论直播请直接回复公众号:“EAII企业架构创新研究院”。(微信号:eaworld)java
1,背景知识;程序员
1.1)了解Rest是什么?web
1.2)了解JAX-RS是什么?编程
1.3)RestEasy简介设计模式
2,手把手教你使用Resteasy;浏览器
3,揭秘Resteasy的实现原理;服务器
4,总结;微信
1、Rest简介及Resteasy产生背景restful
1.1)了解Rest是什么:架构
REST是英文RepresentationalState Transfer 的缩写,有中文翻译为“具象状态传输”。REST 这个术语是由 RoyFielding 在他的博士论文《Architectural Styles and the Design ofNetwork-based Software Architectures 》中提出的。REST并不是标准,而是一种开发 Web 应用的架构风格,能够将其理解为一种设计模式。REST 基于 HTTP,URI,以及 XML 这些现有的普遍流行的协议和标准,伴随着 REST,HTTP 协议获得了更加正确的使用。
相较于基于 SOAP 和 WSDL 的 Web 服务,REST 模式提供了更为简洁的实现方案。目前,愈来愈多的 Web 服务开始采用 REST 风格设计和实现,真实世界中比较著名的 REST 服务包括:Google AJAX 搜索 API、Amazon Simple Storage Service (AmazonS3) 等。
基于 REST 的 Web 服务遵循一些基本的设计原则:
1)系统中的每个对象或是资源均可以经过一个惟一的 URI 来进行寻址,URI 的结构应该简单、可预测且易于理解,好比定义目录结构式的 URI。
2)以遵循RFC-2616 所定义的协议的方式显式地使用 HTTP 方法,创建建立、检索、更新和删除(CRUD:Create, Retrieve, Update and Delete)操做与 HTTP 方法之间的一对一映射:
若要建立资源,应该使用 POST方法, URI : xxx/book(在服务器端新建图书信息,需提供该图书全部信息)
若要检索某个资源,应该使用 GET 方法, URI:xxx/book/{ID} (从服务器端得到某图书信息)
若要更改资源状态或对其进行更新,应该使用 PUT 方法,URI:xxx/book/{ID}(在服务器端更新某已存在的图书信息,需提供更新的内容)
若要删除某个资源,应该使用 DELETE 方法, URI :xxx/book/{ID} (从服务器端删除某图书信息)
URI 所访问的每一个资源均可以使用不一样的形式加以表示(好比 XML 或者 JSON),具体的表现形式取决于访问资源的客户端,客户端与服务提供者使用一种内容协商的机制(请求头与 MIME 类型)来选择合适的数据格式,最小化彼此之间的数据耦合。
1.2) 了解JAX-RS是什么?
Java EE 6 引入了对 JSR-311 的支持。JSR-311(JAX-RS:JavaAPI for RESTful Web Services)旨在定义一个统一的规范,使得 Java 程序员可使用一套固定的接口来开发 REST 应用,避免了依赖于第三方框架。同时,JAX-RS 使用 POJO 编程模型和基于标注的配置,并集成了JAXB,从而能够有效缩短 REST 应用的开发周期。
JAX-RS是一套用java实现REST服务的规范,提供了一些标注将一个资源类,一个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。
更通俗些说若是你用java写了一套框架,当开发者本身写的JAVA类使用了JAX-RS定义的这些注解标注过,而后经过你写的这套框架就能够将有这些JAX-RS标注的类发布成web资源,供其余客户端程序去调用。那么你写的这套框架就是一套RestFul Web Service框架,就是JAX-RS规范的实现者之一,是JAX-RS标准定义的这些标注的解释执行者。
目前比较流行的JAX-RS实现有如下几种:
Apache CXF,开源的Web服务框架开源组织Apache的实现。Jersey,由Sun提供的JAX-RS的参考实现。RestEasy,JBoss的JAX-RS的实现。
与其余几个框架相比较而言,RestEasy以其高性能,轻量级,简单易上手,高可靠性和稳定性以及易于与其余容器集成等特色,愈来愈受到开发人员的欢迎。
1.3)Resteasy简介:
RESTEasy是JBoss的一个开源项目,提供一套完整的框架帮助开发人员构建RESTful Web Service和RESTful Java应用程序。它是JAX-RS 2.0规范的一个完整实现并经过JCP认证,经过Http协议对外提供基于Java API的 RestFul Web Service。
RestEasy能够运行在任何Servlet容器中,做为JBoss的官方实现它能够更好的和Jboss服务器紧密融合从而提供更好的用户体验。
做为JAX-RS的标准实现,RestEasy还具备如下亮点特性:
1)不须要配置文件,只要把JARs文件放到类路径里面,添加 @Path等标注就能够了
2)彻底的把 RESTEeasy 配置做为Seam 组件来看待
3)HTTP 请求由Seam来提供,不须要一个额外的Servlet
4)Resources 和providers能够做为Seam components (JavaBean or EJB),具备全面的Seaminjection,lifecycle, interception, 等功能支持
5)支持在客户端与服务器端自动实现GZIP解压缩
6)支持异步请求处理
7)支持多种数据传输格式: XML, JSON, YAML, Fastinfoset, Multipart, XOP, Atom
……
2、手把手教你使用Resteasy
Resteasy的配置方法有不少种,本节内容是为了给下节讲解RestEasy原理作个铺垫,便于你们理解其实现原理,因此使用了RestEasy最基础的配置方式,其余配置方法你们能够去官网找到相关资料。
RestEasy的配置使用很是的简单,如今咱们经过一个 Demo来看一下如何使用RestEasy。
新建一个JAVA Web工程: 我使用了Maven来建立webapp项目:
引入依赖包:pom.xml 配置以下:
新建Java 资源类,并添加相应的注解;(要发布成rest服务的类)
配置web.xml,添加使用Resteasy将资源类发布成rest服务的能力,配置以下:
验证,启动服务器打开浏览器访问:
http://localhost:8080/resteasydemo/path1/subpath/123
出现以上结果说明经过Resteasy发布 Rest服务成功.怎么样 SoEasy吧。
3、揭秘Resteasy的实现原理
经过上面的Demo相信你们都已经学会如何使用Resteasy把一个JavaBean发布成Rest服务了,接下来咱们结合Demo一块儿来看一下Resteasy的实现原理。
我本人研究Resteasy实现原理的方法是:经过上面这个Demo来调试阅读Resteasy的源码进而理解其实现原理。
首先要发布restful的service要解决如下几个问题:
1) 谁来接受来自客户端的请求,并进行分发交给对应的对象的方法去处理。
2) 负责处理客户端请求的对象由谁来负责产生(上面Demo中的TestRest对象)。
3) 如何解析Java类上面的JAX-RS注解,使客户端过来的请求能够找到对应的对象的方法去执行。
带着上面的三个问题咱们来看一下Resteasy是如何设计实现来解决上面的问题的。
在上面的Demo中要把TestRest发布成Rest服务首先在web.xml文件中作了如下配置:
其中ResteasyBootstrap做为监听器是拉起Resteasy服务的入口,在服务启动时主要作了如下动做:
1)经过ListenerBootstrap组件读取在web.xml文件中的一些系统配置信息,建立ResteasyDeployment对象,并将这些配置信息初始化到该对象中,其中就包括将”resteasy.resources”中配置的资源类的路径初始化到其成员变量resourceClasses中;
2)经过调用ResteasyDeployment的start()方法,并根据相关配置信息初始化Resteasy的核心组件ResteasyProviderFactory ,Dispatcher,Registry.
3)最关键的部分是调用registration(),在该方法中会遍历以前在web.xml中配置的资源并将其注册到Registry中, 以Demo中的例子来看会遍历resourceClasses中配置好的TestRest资源路径,并加载该类而后经过调用registry.addPerRequestResource(clazz)注册到Registry中; 详见如下代码片断:
在addPerRequestResource()中作了两个主要的事情:其中一个是会使用相应的ResourceFactory来包装资源类TestRest,见如下代码片断:
经过阅读POJOResourceFactory的源码能够了解到其做用就是包含了资源类的全部元信息,所以它能够利用ResteasyProviderFactory提供的注入器在须要时经过createResource()来建立资源类TestRest的对象;
第二个主要的事情是Registry能够经过资源类中的元信息来解析上面的JAX-RS注解,并将该注解的路径和对应的方法生成的invoker对象注册到Registry中,在Demo中就是把”/path1/subpath/{id}”和 test()方法的invoker对象注册到Registry中。
(Resteasy在服务启动时初始化过程图)
在web.xml文件中另外一个配置是配置了HttpServletDispatcher,该类是HttpServlet的实现是全部请求的入口,经过其service()方法最终将请求交给以前启动服务时已经初始化好的Dispatcher对象来处理. 以Demo为例,当请求”http://localhost:8080/resteasydemo/path1/subpath/123”过来时,Dispatcher对象会调用其成员变量Registry对象来解析该请求中的路径”/path1/subpath/123”, 而后匹配到相应的invoker来执行客户端请求(详见如下代码段),并将结果返回,页面会显示”Hello 123”;
(Resteasy 客户端请求处理流程图)
4、总结
经过对Resteasy源码的解读分析咱们就能够解答刚开始的三个问题:
1)谁来接受来自客户端的请求,并进行分发交给对应的对象的方法去处理。
----->HttpServletDispatcher,(接受并分发客户端http请求)
2)负责处理客户端请求的对象由谁来负责产生。
----->ResourceFactory (在服务器启动时经过web.xml读取class的配置信息而后经过反射机制产生)
3)如何解析Java类上面的注解,使客户端过来的请求能够找到对应的方法去执行。
------>Registry(服务器启动时加载用户自定义Rest资源时,会解析上面的注解,并将注解相对路径和该类中执行的方法创建对应关系注册到Registry中,当客户端请求过来时会根据请求中的相对路径去Registry中查找对应的invoker对象,而后执行并将处理结果返回)
Resteasy就是经过以上几个核心组件的相互配合,最终将一个JavaBean发布成Rest服务,这种基于服务注册的实现方式,使得Resteasy具备较好的可扩展性,例如它能很好的和Spring进行整合将SpringBean发布成Rest服务,它是如何作到的呢?首先扩展了Resteasy的ResourceFactory实现了一个SpringResourceFactory(用来从Spring容器中得到对象),而后在服务启动时当Spring容器初始化好之后,经过扩展Spring的BeanFactoryPostProcessor,将Spring容器中初始化好的SpringBean以及对应的SpringResourceFactory注册到Resteasy的Registry中.这样客户端请求过来后,当请求路径在Registry中匹配到相应的SpringBean时就能够调用该SpringBean的ResourceFactory的createResource方法,该方法能够从Spring容器中得到对象来处理请求。
Tips:
Resteasy发布Rest服务的两种方式:
一种是经过listener (ResteasyBootstrap)方式在server启动时经过该listener的contextInitialized()初始化Resteasy核心组件及Rest资源。
第二种是若是没有在web.xml中配置ResteasyBootstrap监听器,则在HttpServletDispatcher,第一次请求过来时经过servlet的init方法初始化Resteasy核心组件及Rest资源。
不管哪一种方式原理都是同样的,只是初始化的时机不一样。
关于做者:
王磊
现任普元SOA产品部高级软件工程师,曾供职于Newegg,The ActiveNetWork等知名外企,在Newegg工做期间曾担任项目经理带领团队完成美蛋网O2O平台LocalPros的开发上线,在J2EE企业级应用方面有丰富的实战经验。
关于EAII
EAII(Enterprise Architecture Innovation Institute)企业架构创新研究院,致力于软件架构创新与实践,加速企业数字化转