zoukankan      html  css  js  c++  java
  • RESTEASY ,从学会使用到了解原理。

    转载本文需注明出处:EAII企业架构创新研究院,违者必究。如需加入微信群参与微课堂、架构设计与讨论直播请直接回复公众号:“EAII企业架构创新研究院”。(微信号:eaworld)


    1,背景知识;

    1.1)了解Rest是什么?

    1.2)了解JAX-RS是什么?

    1.3)RestEasy简介

    2,手把手教你使用Resteasy;

    3,揭秘Resteasy的实现原理;

    4,总结;

    一、Rest简介及Resteasy产生背景

     

    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

    ……

    二、手把手教你使用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吧。

    三、揭秘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 客户端请求处理流程图)

    四、总结

    通过对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)企业架构创新研究院,致力于软件架构创新与实践,加速企业数字化转

  • 相关阅读:
    ROS安装过程与常遇问题
    Linux中Vim工具的使用
    秋招总结
    SpringBoot项目打包war包步骤
    hiredis windows静态库编译
    Access去除字段值后面空格
    AspNetCore容器化(Docker)部署(四) —— Jenkins自动化部署
    AspNetCore容器化(Docker)部署(三) —— Docker Compose容器编排
    AspNetCore容器化(Docker)部署(二) —— 多容器通信
    AspNetCore容器化(Docker)部署(一) —— 入门
  • 原文地址:https://www.cnblogs.com/langtianya/p/7624647.html
Copyright © 2011-2022 走看看