如何在JAX-RS中管理状态?

问题描述:

如何配置JAX-RS 2实现(RESTEasy 3)以将应用程序的状态发送到客户端?

How do I configure JAX-RS 2 implementation (RESTEasy 3) to send the state of the application to the client?

在JSF中,我可以使用STATE_SAVING_METHOD参数来做到这一点.

In JSF I am able to do it using the STATE_SAVING_METHOD parameter.

是否有使用JAX-RS的标准方法?

Is there a standard way of doing it using JAX-RS?

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

仅是一个示例来说明我的问题,我想配置JAX-RS提供程序以将cart变量状态返回给客户端,这样我就不会将数据保留在内存中或保留会话状态.

Just an example to illustrate my problem, I would like to configure the JAX-RS provider to return the cart variable state to the client, in that way I won't keep the data in-memory or persist the session state.

@Path("/cart")
public class ShoppingCart {

    // List of products presented to the user
    private List<Product> availableProducts;

    // Products selected by the user
    private List<Product> cart;

    @GET
    public List<Product> addProduct() {
        return availableProducts;
    }

    @POST
    public void addProduct(Product product) {
        cart.add(product);
    }

}

更新

我想添加一些引用来支持管理应用程序状态的想法.我同意,从理论上讲,所有服务都应该是无状态的,但是在实践中,我发现,如果可以维持状态,则很多情况下更有意义,尤其是出于安全性和生产力的原因.

Update

I would like to add references that support the idea of managing the state of the appliations. I agree that in theory, all services should be stateless, but in practice I found out that many scenarios would make more sense if the state could be maintained, specially for security and productivity reasons.

似乎该模式通常是通过超链接完成的,其内容已正确加密以保护数据和完整性.我现在正在研究支持这些方案的JAX-RS工具.

It seems that the pattern is usually done via hyperlinks, with the content properly encrypted to secure data and integrity. I am now looking into the JAX-RS tools that support these scenarios.

如何管理应用程序状态 RESTful Web服务指南:

由于HTTP是无状态协议,因此每个请求都独立于任何请求 先前的要求.但是,交互式应用程序通常需要 客户按照特定顺序执行一系列步骤.这 强制服务器将每个客户的当前位置临时存储在 协议之外的那些序列.诀窍是管理状态 这样您就可以在可靠性,网络 性能和可伸缩性.

Since HTTP is a stateless protocol, each request is independent of any previous request. However, interactive applications often require clients to follow a sequence of steps in a particular order. This forces servers to temporarily store each client’s current position in those sequences outside the protocol. The trick is to manage state such that you strike a balance between reliability, network performance, and scalability.

并且也来自 JAX-RS文档:

通过超链接进行的有状态交互:每次与 资源是无状态的;也就是说,请求消息是独立的. 有状态的交互基于显式状态的概念 转移.存在几种交换状态的技术,例如URI 重写,Cookie和隐藏的表单字段.状态可以嵌入 响应消息以指向交互的有效未来状态. 请参阅使用实体提供者映射HTTP响应和请求实体 "JAX-RS概述"文档中的实体和构建URI"以获取更多信息 信息.

Stateful interactions through hyperlinks: Every interaction with a resource is stateless; that is, request messages are self-contained. Stateful interactions are based on the concept of explicit state transfer. Several techniques exist to exchange state, such as URI rewriting, cookies, and hidden form fields. State can be embedded in response messages to point to valid future states of the interaction. See Using Entity Providers to Map HTTP Response and Request Entity Bodies and "Building URIs" in the JAX-RS Overview document for more information.

lefloh 提供了一个非常清晰的答案,我想添加一些其他细节,以帮助您了解REST架构.

While lefloh provided a very clear answer, I'd like to add a few more details that will help you to understand the REST architecture.

REST 代表 Re 代表性的 S tate T 转移.该体系结构是与协议无关的,但它是经常通过HTTP协议实现的.

REST stands for Representational State Transfer. This architecture is protocol independent but it is frequently implemented over the HTTP protocol.

第5章罗伊·托马斯·菲尔丁(Roy Thomas Fielding)博士论文的a>.并将以下约束集添加到该体系结构样式中:

The REST architectural style was defined in the chapter 5 of Roy Thomas Fielding's PhD dissertation. And the following set of constraints was added to this architectural style:

  • Client-server
  • Stateless
  • Cache
  • Uniform interface
  • Layered system
  • Code-on-demand

通过应用上面定义的约束,可以引入某些体系结构属性,例如可见性,可移植性,可靠性,可伸缩性和网络效率.

Through the application of the constraints defined above, certain architectural properties are induced, such as visibility, portability, reliability, scalability and network efficiency.

在REST应用程序中,从客户端到服务器的每个请求必须包含服务器必须理解的所有必要信息.使用它,您将不依赖于存储在服务器上的任何会话上下文,并且不会破坏

In a REST applications, each request from the client to the server must contain all the necessary information to be understood by the server. With it, you are not depending on any session context stored on the server and you do not break the stateless constraint:

5.1.3无状态

[...]通信本质上必须是无状态的,使得从客户端到服务器的每个请求都必须包含理解该请求所必需的所有信息,并且不能利用服务器上的任何存储上下文.服务器.因此,会话状态完全保留在客户端上. [...]

[...] communication must be stateless in nature [...], such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]

例如,当访问需要身份验证的受保护资源时,每个请求必须包含所有必要的数据,以便正确地进行身份验证/授权.这意味着将对每个请求执行身份验证.

When accessing protected resources that require authentication, for example, each request must contain all necessary data to be properly authenticated/authorized. It means the authentication will be performed for each request.

使用JAX-RS创建REST应用程序时,您具有资源类,即使用JAX-RS批注实现相应Web资源的Java类.

When creating a REST application using JAX-RS, you have resource classes, that is, Java classes that uses JAX-RS annotations to implement a corresponding Web resource.

资源类是POJO,它们至少具有一种用 @DELETE @GET @HEAD @OPTIONS @POST @PUT ,使用 @HttpMethod ).

Resource classes are POJOs that have at least one method annotated with @Path or a request method designator (@DELETE, @GET, @HEAD, @OPTIONS, @POST, @PUT, custom annotations created with @HttpMethod).

根据 JAX-RS规范,资源类遵循明确定义的生命周期:

According to the JAX-RS specification, resource classes follow a well defined lifecycle:

3.1.1生命周期和环境

默认情况下,为对该资源的每个请求创建一个新的资源类实例.首先调用构造函数,然后注入所有请求的依赖项,然后调用适当的方法,最后使该对象可用于垃圾回收. [...]

By default a new resource class instance is created for each request to that resource. First the constructor is called, then any requested dependencies are injected , then the appropriate method is invoked and finally the object is made available for garbage collection. [...]

在JAX-RS中,没有这样的 javax.faces.STATE_SAVING_METHOD 或类似名称.没有状态.没有会议.

In JAX-RS, there's no such javax.faces.STATE_SAVING_METHOD or similar. There's no state. There's no session.

您的资源类可以遵循 lefloh answer .并且不要忘记,您总是可以对资源类进行注入:

Your resource class can follow the pseudo-code suggested in lefloh's answer. And don't forget you always can perform injections into your resource class:

@Path("/cart")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class ShoppingCart {

    @Inject
    private ShoppingCartService service;

    @GET
    public Response getProducts() {
        ...
    }

    @POST
    public Response addProduct(Product product) {
        ...
    }
}

JAX-RS中的超链接

REST的一个非常重要的方面是超链接(URI),URI表示客户端可以用来将Web服务转换为新的应用程序状态.这被称为超媒体,它是应用程序状态的引擎,通常缩写为 HATEOAS .

Hyperlinks in JAX-RS

A very important aspect of REST is hyperlinks, URIs, in representations that clients can use to transition the web service to new application states. This is known as hypermedia as the engine of application state, frequently abreviated as HATEOAS.

JAX-RS 2.0引入了 Link 类,它表示 RFC 5988 href>中定义的网络链接>. JAX-RS Link 类增加了API支持,可在HTTP消息中提供其他元数据.

JAX-RS 2.0 introduced the Link class, which serves as a representation of the web link defined in RFC 5988. The JAX-RS Link class adds API support for providing additional metadata in HTTP messages.

A Link 可以作为其他HTTP标头序列化到HTTP响应(可能提供了多个Link标头,因此可以在一条消息中提供多个链接).这样的HTTP标头可能看起来像:

A Link can be serialized to the HTTP response as additional HTTP header (there might be multiple Link headers provided, thus multiple links can be served in a single message). Such HTTP header may look like:

Link: <http://example.com/api/books/1/chapter/2>; rel="prev"; title="previous chapter"

产生 Link 使用JAX-RS API的>可以按以下步骤完成:

Producing Links with JAX-RS API can be done as following:

Response response = Response.ok()
                      .link("http://example.com/api/books/1/chapter/2", "prev")
                      .build();

Link 也可以通过调用 ="nofollow noreferrer"> Link API,该API返回

Instances of Link can be also created directly by invoking one of the factory methods on the Link API that returns a Link.Builder that can be used to configure and produce new links:

URI uri = URI.create("http://example.com/api/books/1/chapter/2");
Link link = Link.fromUri(uri).rel("prev").title("previous chapter").build();

Response response = Response.ok().link(link).build();

Link 也可以将s添加到您的响应实体模型中:

Links can be also added to your response entity models:

public class Book {

    private String title;

    private Link link;

    // Default constructor, getters and setters ommited
}

例如,当序列化为JSON时,您将拥有类似的东西:

When serialized to JSON, for example, you will have something like:

{
    "title" : "The Lord of the Rings",
    "link" : {
        "rel" : "self",
        "uri" : "http://example.com/api/books/1",
        "title": "self"
      }
}