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);
}
};
考虑下一个代码。
过滤器:
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);
}
};