Restlet重用InputStream

Restlet reuse InputStream

考虑下一个代码。

过滤器:

public class InputFilter extends Filter {

  @Override
  protected int beforeHandle(Request request, Response response) {

    int result = CONTINUE;
    InputStream inputStream = request.getEntity().getStream();
    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer, "UTF-8");

    String theString = writer.toString();
    JsonRepresentation jRep = new JsonRepresentation(theString);

    String token = jRep.getJsonObject().getString("token");
    .
    .
    .
    return result;
  }
}

资源:

public class inputResource extends GsServerResource {

  @Post
  public JsonRepresentation getInput(JsonRepresentation jRep) {
    String token = jRep.getJsonObject().getString("token");
    .
    .
    .
  }
}

jRep 为 NULL。

我在过滤器中使用了一次流,由于它不是 transient.

,所以它被关闭供以后使用

我当前的修复:

在过滤器中(检索流后):

request.getAttributes().putIfAbsent("token", token);

在资源中:

String token = (String) getRequest().getAttributes().get("token");

除了将数据放入 filter 中的 context 然后在 resource 中检索数据之外,还有其他解决方案吗?

事实上,您可以根据从请求中提取的实体文本在 StringRepresentation 过滤器中再次设置请求的实体,如下所述:

// Get entity text
Representation repr = request.getEntity();
String content = repr.getText();

// Use entity text
InputStream inputStream = request.getEntity().getStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");

String theString = writer.toString();
JsonRepresentation jRep = new JsonRepresentation(theString);

String token = jRep.getJsonObject().getString("token");

// Set again the entity for the request
StringRepresentation sRepr = new StringRepresentation(
                           content, repr.getMediaType());
request.setEntity(sRepr);

使用这种方法,您可以再次读取过滤器后面的资源中的请求实体。

希望对你有帮助, 蒂埃里

有一种更简单的方法来编写过滤器:

    Filter filter = new Filter(getContext()) {
        @Override
        protected int beforeHandle(Request request, Response response) {
            try {
                JsonRepresentation jrep = new JsonRepresentation(request.getEntity());
                JSONObject jo = jrep.getJsonObject();
                String token = jo.getString("token");
                System.out.println(token);
                request.setEntity(new JsonRepresentation(jo));
            } catch (JSONException | IOException e) {
                throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
            }

            return super.beforeHandle(request, response);
        }
    };

实际上,如果 JsonRepresentation class 保留已解析的对象,甚至会更容易。我已经为该主题输入了一个问题 (https://github.com/restlet/restlet-framework-java/issues/1067)。 在那种情况下,我们可以简单地写:

    Filter filter = new Filter(getContext()) {
        @Override
        protected int beforeHandle(Request request, Response response) {
            try {
                JsonRepresentation jrep = new JsonRepresentation(request.getEntity());
                String token = jrep.getJsonObject().getString("token");
                System.out.println(token);
                request.setEntity(jrep);
            } catch (JSONException | IOException e) {
                throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
            }

            return super.beforeHandle(request, response);
        }
    };