分布式springboot 关键技术(分布式系统REST风格架构常用技术)

几乎所有的编程语言都支持REST服务的开发其中,Java一直跟进最新的企业应用开发的规范的支持在REST开发领域,Java用于开发REST服务的规范,主要是JAX-RS规范该规范使得Java程序员可以使用一套固定、统一的接口来开发REST应用,从而避免了依赖于第三方框架同时,JAX-RS使用POJO编程模型和基于注解的配置,并集成了JAXB,从而可以有效缩短REST应用的开发周期Java EE 6引入了对JSR-311的支持,Java EE 7支持JSR-339规范,今天小编就来聊一聊关于分布式springboot 关键技术?接下来我们就一起去研究一下吧!

分布式springboot 关键技术(分布式系统REST风格架构常用技术)

分布式springboot 关键技术

常用技术

几乎所有的编程语言都支持REST服务的开发。其中,Java一直跟进最新的企业应用开发的规范的支持。在REST开发领域,Java用于开发REST服务的规范,主要是JAX-RS规范。该规范使得Java程序员可以使用一套固定、统一的接口来开发REST应用,从而避免了依赖于第三方框架。同时,JAX-RS使用POJO编程模型和基于注解的配置,并集成了JAXB,从而可以有效缩短REST应用的开发周期。Java EE 6引入了对JSR-311的支持,Java EE 7支持JSR-339规范。

JAX-RS定义的API位于javax.ws.rs包中。

伴随着JSR 311规范的发布,Sun同步发布了该规范的参考实现Jersey。JAX-RS的具体实现第三方还包括Apache的CXF以及JBoss的RESTEasy等。未实现该规范的其他REST框架还包括Spring Web MVC等。

JAX-RS规范

随着REST的流行,Java开始着手制订REST开发规范,并在Java EE6引入了对JSR-311的支持。JAX-RS是一个社区驱动的标准,用于使用Java构建RESTful Web服务。它不仅定义了一套用于构建RESTful网络服务的API,同时也通过增强客户端API功能简化了REST客户端的构建过程。从2007年诞生至今,JAX-RS经过了多次重大版本的发布,也经过多次的提案与审查,终于在2017年8月22日发布了2.1版本(JSR-370)。

JAX-RS规范制订了以下目标。

·基于POJO的API。该规范所定义的API将提供一组注解和相关的类、接口,可用于POJO以将它们公开为Web资源。同时,该规范将定义对象生命周期和范围。·以HTTP为中心。该规范将假定HTTP是底层网络协议,并将提供HTTP和URI元素以及相应的API类和注解之间的明确映射。API将为常见的HTTP使用模式提供高级别的支持,并且将具有足够的灵活性来支持各种HTTP应用程序,包括WebDAV和Atom发布协议。

·格式独立性。该规范所定义的API将适用于各种各样的HTTP实体主体内容类型。它将提供必要的可插入性,从而允许应用程序以标准方式添加其他类型。

·容器独立性。使用该规范所定义的API的部件可以部署在各种Web容器中。该规范定义了如何在Servlet容器和JAX-WS提供程序中部署部件。

·包含在Java EE中。规范将定义托管在Java EE容器中的Web资源类的环境,并将指定如何在Web资源类中使用Java EE功能和组件。

JAX-RS规范包含了以下核心概念。

1.根资源类

根资源类(Root Resource Classes)是带有@PATH注解的,包含至少一个@PATH注解的方法或者方法带有@GET、@PUT、@POST、@DELETE资源方法指示器的POJO。资源方法是带有资源方法指示器(Resource Method Designator)注解的方法。

下面这段代码就是一个带有JAX-RS注解的简单示例。

import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("helloworld") public class HelloWorldResource { public static final String CLICHED_MESSAGE = "Hello World!"; @GET @Produces("text/plain") public String getHello() { return CLICHED_MESSAGE; } }

其中,@Path是一个URI的相对路径,在上面的例子中,设置的是本地的URI的/helloworld。这是一个非常简单的关于@Path的例子,有时,我们也会嵌入变量到URI里面。URI的路径模板是由URI和嵌入URI的变量所组成的。变量在运行时将会被匹配到的URI的那部分所代替。

例如下面的@Path注解。

@Path("/users/{username}")

按照这种类型的例子,一个用户可以方便地填写他的名字,同时服务器也会按照这个URI路径模板响应这个请求。例如用户输入了名字“Wa”,那么服务器就会响应http://example.com/users/Way。

为了接收到用户名变量,@PathParam用在接收请求的方法的参数上,例如:

@Path("/users/{username}") public class UserResource { @GET @Produces("text/xml") public String getUser(@PathParam("username") String userName) { ... } }

@GET、@PUT、@POST、@DELETE、@HEAD是JAX-RS定义的注解,它非常类似于HTTP的方法名。在上面的例子中,这些注解是通过HTTP的GET方法实现的。资源的响应就是HTTP的响应。

2.*Param参数注解

资源方法中,带有基于参数注解的参数可以从请求中获取信息。前面的一个例子就是在匹配了@Path之后,通过@PathParam来获取URL请求中的路径参数。

@QueryParam用于从请求URL的查询组件中提取查询参数。观察下面的例子。

@Path("smooth") @GET public Response smooth( @DefaultValue("2") @QueryParam("step") int step, @DefaultValue("true") @QueryParam("min-m") boolean hasMin, @DefaultValue("true") @QueryParam("max-m") boolean hasMax, @DefaultValue("true") @QueryParam("last-m") boolean hasLast, @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor, @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor, @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor) {... }

如果step的参数存在,那么赋值给它,否则默认是@DefaultValue定义的值2。如果step的内容不是32位的整型,那么会返回404错误。

@PathParam和其他参数注解@MatrixParam、@HeaderParam、@CookieParam以及@FormParam遵循与@QueryParam一样的规则。

@MatrixParam从URL路径提取信息。@HeaderParam从HTTP头部提取信息,@CookieParam从关联在HTTP头部的cookies里提取信息。

@FormParam稍有特殊,因为它提取信息,要求MIME媒体类型必须为“application/x-www-form urlencoded”,并且符合指定的HTML编码的形式。此参数提取对于HTML表单请求是非常有用的,例如从发布的表单数据中提取名称是name的参数信息。

@POST @Consumes("application/x-www-form-urlencoded") public void post(@FormParam("name") String name) { // ... }

另一种注解是@BeanParam允许注入一个bean到参数中。

@BeanParam可以用于注入这种bean到资源或资源的方法。以下是@BeanParam的用法。

public class MyBeanParam {@PathParam("p") private String pathParam; @MatrixParam("m") @Encoded @DefaultValue("default") private String matrixParam; @HeaderParam("header") private String headerParam; private String queryParam; public MyBeanParam(@QueryParam("q") String queryParam) { this.queryParam = queryParam; } public String getPathParam() { return pathParam; } ... }

将MyBeanParam以参数形式注入。

@POST public void post(@BeanParam MyBeanParam beanParam, String entity) { final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p" // ... }

3.子资源

@Path可以用在类上,这样的类称为根资源类,它也可以被用在根资源类的方法上。这使得许多资源的方法被组合在一起,能够被重用。

@Path是用在资源的方法上,这类方法被称为子资源方法(Sub-Resource Method)。

以下是一个完整的根资源类和子资源方法的示例。

@Singleton @Path("/printers") public class PrintersResource { @GET @Produces({"application/json", "application/xml"}) public WebResourceList getMyResources() { ... } @GET @Path("/list") @Produces({"application/json", "application/xml"}) public WebResourceList getListOfPrinters() { ... } @GET @Path("/jMakiTable")@Produces("application/json") public PrinterTableModel getTable() { ... } @GET @Path("/jMakiTree") @Produces("application/json") public TreeModel getTree() { ... } @GET @Path("/ids/{printerid}") @Produces({"application/json", "application/xml"}) public Printer getPrinter( @PathParam("printerid") String printerId) { ... } @PUT @Path("/ids/{printerid}") @Consumes({"application/json", "application/xml"}) public void putPrinter(@PathParam("printerid") String printerId, Printer printer) { ... } @DELETE @Path("/ids/{printerid}") public void deletePrinter( @PathParam("printerid") String printerId) { ... } }

4.根资源类生命周期

默认情况下,根资源类的生命周期是每个请求,即根资源类的新实例在每次请求的URI路径匹配根资源时创建。利用构造函数和范围可以构造一个很自然的编程模型,而无须关心对同一资源的多个并发请求。

总的来说这不太可能成为导致性能问题的原因。近年来,类的构造以及JVM的GC已大大改善,在服务和处理HTTP请求并返回HTTP响应中,许多对象将被创建和丢弃。

单个的根资源类的实例可以通过一个应用实例声明。

使用Jersey特定注解让Jersey拥有更多生命周期管理。表8-2所示为根资源类生命周期。

表8-2 根资源类生命周期

5.注入规则

注入可以用在属性、构造方法参数、资源/子资源/子资源定位方法的参数和bean setter方法上。以上介绍的这些注入的情况具体如下。

@Path("{id:\\d }") public class InjectedResource { // 注入属性 @DefaultValue("q") @QueryParam("p") private String p; // 注入构造函数参数 public InjectedResource(@PathParam("id") int id) { ... } // 注入资源参数 @GET public String get(@Context UriInfo ui) { ... } // 注入子资源方法参数 @Path("sub-id") @GET public String get(@PathParam("sub-id") String id) { ... } // 注入子资源方法参数定位器方法参数 @Path("sub-id") public SubResource getSubResource( @PathParam("sub-id") String id) { ... } // 注入 bean setter 方法 @HeaderParam("X-header") public void setHeader(String header) { ... } }

有一些限制,当注入一个生命周期为单例的资源类时,类的属性或构造函数的参数不能被注入请求特定的参数。例如,以下是不允许的。

@Path("resource")@Singleton public static class MySingletonResource { @QueryParam("query") String param; //错误:不能将特定参数注入单例资源,否则会使程序初始化失败 @GET public String get() { return "query param: " param; } }

上面的例子验证了应用程序不能为单例资源注入请求特定的参数,否则验证失败。同样的例子,如果查询的参数将被注入一个单例构造函数参数则失败。换句话说,如果你希望一个资源实例的服务被很多次请求,则资源实例不能绑定到一个特定的请求参数上。

存在一个例外,特定请求对象可以注入构造函数或类属性。这些对象的运行时注入的代理可以同时服务多个请求。这些请求的对象是HttpHeaders、Request、UriInfo、SecurityContext。这些代理可以使用@Context注解进行注入。下面的示例展示将代理注入单例资源类。

@Path("resource") @Singleton public static class MySingletonResource { @Context Request request; // 这个是允许的: //请求的代理将会被注入单例 public MySingletonResource( @Context SecurityContext securityContext) { // 这个也是允许的: // SecurityContext的代理将会被注入单例 } @GET public String get() { return "query param: " param; } }

Jersey

Jersey是官方JAX-RS规范的参考实现,可以说是全面地实现了JAX-RS规范所定义的内容。Jersey框架是开源的。Jersey框架不仅是JAX-RS参考实现,还提供了自己的API,它扩展了JAX-RS工具包的附加功能和实用程序,以进一步简化RESTful服务和客户端开发。

Jersey也公开了大量的扩展SPI,以便开发人员可以扩展Jersey以满足他们的需求。

Jersey项目的目标可以归纳为以下3点。

·跟踪JAX-RS API,并定期发布GlassFish所定义的参考实现。

·提供API来扩展Jersey,不断构建用户和开发人员的社区。

·使用Java和Java虚拟机可以轻松构建RESTful Web服务。

Apache CXF

Apache CXF是另外一款支持JAX-RS的框架。除了支持JAX-RS外,Apache CXF还支持传统的JAX-WS协议。Apache CXF可以使用各种协议,如SOAP、XML/HTTP、RESTful HTTP或CORBA,并可用于各种传输,如HTTP、JMS或JBI。Apache CXF支持JAX-RS 2.0(JSR-339)以及JAX-RS 1.1(JSR-311)。

同样Apache CXF也是开源的,具有高性能、可扩展、易于使用等特点。

Spring Web MVC

Spring Web MVC框架,也简称为“Spring MVC”,实现了Web开发中的经典的MVC(Model-View-Controller)模式。MVC由以下3个部分组成。

·模型(Model):应用程序的核心功能,管理这个模块中用到的数据和值。·视图(View):视图提供模型的展示,管理模型如何显示给用户,它是应用程序的外观。

·控制器(Controller):对用户的输入做出反应,管理用户和视图的交互,是连接模型和视图的枢纽。

Spring Web MVC是基于Servlet API来构建的,自Spring框架诞生之日起,它就包含在Spring里面了。严格意义上来说,Spring Web MVC并没有遵守JAX-RS规范,所以也称不上是REST框架。但是,Spring WebMVC所暴露的接口,可以是REST风格的API,所以自然也能拿来开发REST服务。

本文给大家讲解的内容是分布式系统核心:REST风格架构的常用技术,Jersey, Apache CXF,Spring MVC
  1. 下篇文章给大家讲解的是分布式系统核心:REST风格架构实战:基于Java实现REST API;

  2. 觉得文章不错的朋友可以转发此文关注小编;

  3. 感谢大家的支持!

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页